На этом шаге мы рассмотрим порядок создания программ в muLISP85.
Состав системы
Загрузка и работа системы
Редактирование строк
Чтение исходных файлов и файлов среды
Отладчик системы
Система muLISP85 содержит следующие файлы (табл.1):
Компилятор и интерпретатор muLISP. | |
Утилита преобразования COM-файла в EXE-файл. | |
Исходный файл редактора. | |
Исходный файл отладчика. | |
Графические средства muLISP. | |
Обеспечение интерфейса между muLISP и Microsoft Mouse. | |
Файл совместимости с muLISP83. | |
Функции-утилиты диалекта INTERLISP. | |
Функции-утилиты диалекта COMMON LISP. Диалекты MACLISP и ZETALISP тесно связаны с диалектом COMMON LISP, поэтому данный файл полезен и для этих диалектов языка LISP. | |
Основной файл. | |
Файлы с уроками по диалекту muLISP. | |
Игра "Подсчет зверей". | |
Дерево данных для игры "Подсчет зверей". | |
Имитация действий врача-психотерапевта. | |
Игра "Гребные состязания". | |
Игра "Ханойские башни". | |
Игра "Расшифровка секретного кода". |
После загрузки системы на экране дисплея появится сообщение:
muLISP-85 5.nn ( mm/dd/yy )
xxxxxxxxxxx version
Copyright (c) 1982 to 85 SOFT WAREHOUSE, Inc.
Licensed by MICROSOFT corp.
Соответственно, появляются номера версии (5.nn), месяц (mm), день (dd) и год (yy). Номер и дата версии вместе с серийным номером будут включаться во все справки системы.
Символы ххххххххххх в сообщении обозначают тип компьютера, на котором данная версия muLISP может работать.
Ниже сообщения высвечивается подсказка muLISP, состоящая из знака доллара ($), за которым следует пустая строка. Подсказка означает, что система готова к вводу с консоли.
Вы можете вводить выражения языка LISP.
После ввода выражения и нажатия клавиши Enter, muLISP оценивает это выражение (вычисляет его значение) и печатает результат вычисления значения в начале новой строки. Этот цикл взаимодействия повторяется вновь и вновь до тех пор, пока не появится обращение к функции SYSTEM, которая завершает работу muLISP и возвращает управление операционной системе. Циклический принцип muLISP иногда называют "овальным"LISP (oval-LISP).
С консоли могут быть введены выражения, записанные в буквенном и (или) точечном виде. Выражение не оценивается до тех пор, пока все скобки не будут сбалансированы, поэтому у вас может получиться выражение, занимающее несколько строк экрана дисплея. После того, как вы нажмете "последний" раз клавишу Enter, выражение будет "прочитано" функцией READ, "вычислено" функцией EVAL, и результат будет выведен на экран дисплея с помощью функции PRINT.
Продемонстрируем основной цикл на примере:
$ 'DOG
DOG
$ (+ 5 -2 4)
7
$ (EQUAL 'DOG 'CAT)
NIL
$ (member 'dog' (cat cow dog pig))
(DOG PIG)
Замечание 2. Основной интерфейс пользователя с muLISP обеспечивается функцией цикла "чтение-вычисление-печать" DRIVER.
После инициализации области данных, muLISP вводит вычисляемый драйвер-цикл верхнего уровня. Данный цикл верхнего уровня устанавливает внутренний счетчик <break-level> в 0, а контрольные переменные RDS и WRS - в NIL, делая консоль одновременно и текущим входным источником (CIS) и выходным потоком (COS), устанавливает контрольную переменную READ-CHAR в 'READ-CHAR, настраивая ввод с консоли на линейное редактирование, чистит буфер линейного редактирования и вызывает текущее значение переменной DRIVER.
На языке LISP это выглядит так:
(LOOP
(SETQ break-level 0)
(SETQ RDS NIL)
(SETQ WRS NIL)
(SETQ READ-CHAR 'READ-CHAR)
(CATCH NIL (FUNCALL DRIVER))
)
Значение переменной DRIVER, принимаемое по умолчанию, - это функция DRIVER, которая рассматривается ниже. Как только новая функция DRIVER определена, команда (RETURN) завершает выполнение функции DRIVER, определенной по умолчанию, а драйвер-цикл верхнего уровня инициирует новую функцию DRIVER.
На примере показано, как осуществлется цикл "чтение-вычисление-печать" для muLISP:
(DEFUN EVAL-QUOTE ()
(CATCH 'RETURN
(LOOP
(CATCH 'DRIVER (PRINC ">")
(PRINT (APPLY (READ) (READ))))))
)
$ (SETQ DRIVER 'EVAL-QUOTE)
EVAL-QUOTE
$ (RETURN)
> CONS (DOG (CAT COW PIG))
(DOG CAT COW PIG)
Функция (DRIVER) осуществляет выполнение цикла "чтение-вычисление-печать" в muLISP. Цикл начинается с высвечивания на дисплей текущего уровня прерывания, если он не нулевой (функция DRIVER не вызывается непосредственно циклом высокого уровня).
Затем высвечивается символ "доллар". Наконец, из текущего входного источника (CIS) с помощью функции READ считывается выражение, которое вычисляется с помощью функции EVAL, а результат пересылается в выходной поток (COS) с помощью функции PRINT.
При прерывании цикла "чтение-вычисление-печать" в ходе чтения, вычисления или печати выражений осуществляется переход на метку DRIVER. Данная возможность позволяет таким функциям, как BREAK, прерывать выполнение программы и сразу же передать управление на текущий уровень цикла.
Данный цикл продолжается до тех пор, пока не будет считано и вычислено выражение (RETURN VALUE). При этом цикл прекращается, а функция DRIVER возвращает VALUE.
Для удобства программирования последние три выражения, считываемые циклом, могут быть заменены переменными: + , ++ и +++ соответственно, а результаты вычисления последних трех выражений - переменными: * , ** и *** соответственно. Текущее считанное выражение заменяется переменной "-".
На примере показано, как можно использовать данные переменные:
$ (CONS 'SAM '(ANN JOE SUE))
(SAM JOE SUE)
$ +
(CONS 'SAM '(ANN JOE SUE))
$ **
(SAM ANN JOE SUE)
Взгляните на реализацию функции DRIVER:
(DEFUN DRIVER ()
(CATCH 'RETURN (LOOP (CATCH 'DRIVER
( ((ZEROP break-level))
(PRIN1 break-level) )
(PRINC "$ ")
(SETQ - (READ))
(PSETQ * (UNWIND-PROTECT (EVAL -)
(SETQ +++ ++ ++ + + -))
*** ** ** *)
(PRINT *) )))
)
Система muLISP85 содержит редактор строк для редактирования предварительно введенных или вводимых в данный момент с клавиатуры строк. Для получения строки текста нужно набрать ряд символов, а затем нажать клавишу Enter.
Редактирование текстов осуществляется с использованием управляющих символов. Вызов управляющего символа - это набор соответствующей буквы с одновременным нажатием клавиши CTRL (табл.2):
Сдвиг слова влево. | |
Сдвиг конца строки влево. | |
Сдвиг символа вправо. | |
Сдвиг слова вправо. | |
Уничтожение символа под курсором. | |
Сдвиг символа влево. | |
Сдвиг вправо до следующей "остановки" табулятора. | |
Запись строки текста. | |
Запись строки текста. | |
Избавление от следующего введенного символа. | |
Сдвиг конца строки вправо. | |
Сдвиг символа влево. | |
Уничтожение слова "под курсором". | |
Переключение режимов "вставка/удаление". | |
Сдвиг конца строки влево. | |
Сдвиг символа влево. | |
Сдвиг конца строки влево. | |
Сдвиг символа влево. | |
Уничтожение символа слева от курсора. | |
Запись строки текста. | |
Запись строки текста. |
Если muLISP работает на IBM PC, то клавиши управления курсором (стрелки, HOME, END, INSERT и т.д.) в правой части клавиатуры также являются функциональными.
Функция (RDS 'drive:name.type) возвращает символ <drive:name.type>, если файл <name.type> найден на диске, размещенном на устройстве <drive>; в противном случае она возвращает NIL.
Если расширение имени файла отсутствует, то ищется файл с расширением ".LSP". Если отсутствует имя устройства, то используется устройство по умолчанию.
Заметим, что для считывания исходных файлов может быть использована команда операционной
системы. Например:
C:\>MULISP ANIMAL.LSP
считывает исходный файл ANIMAL.LSP с устройства по умолчанию после того, как интерпретатор muLISP будет загружен с устройства C.
Вы можете создать исходные файлы текста программы с использованием либо текстового редактора системы muLISP85, либо "внешнего" текстового редактора, генерирующего текстовые файлы в кодах ASCII.
Обычно последней строкой исходного файла является команда (RDS) которая переключает ввод muLISP на консоль после того, как файл будет считан.
Среда muLISP - это текущее состояние системы. Она состоит из всех активных в данный момент структур данных muLISP, значений переменных и определений функций.
Команда SAVE сохраняет текущую среду muLISP в виде SYS-файла,
поэтому среда может быть быстро восстановлена в нужный момент. Например, команда
(SAVE 'C:WHALE)
создает SYS-файл WHALE.SYS на устройстве C. В случае успешного окончания команда SAVE возвращает Т, в противном случае - NIL.
После завершения выполнения команды SAVE среда muLISP может быть восстановлена
с помощью команды LOAD. Например, команда:
(LOAD 'C:WHALE)
загружает файл WHALE.SYS с устройства C. Если SYS-файл не найден, команда LOAD возвращает NIL, в противном случае она не возвращает переменной, но начинает работать с новой средой. Отметим, что после выполнения команды LOAD среда заменяется на ту, которая сохранена в SYS-файле.
SYS-файл можно загрузить с помощью команд операционной системы. Например:
A:\>MULISP C:\WHALE
загружает SYS-файл WHALE.SYS с устройства C после загрузки muLISP с устройства по умолчанию.
Если исходный или SYS-файл не найден при загрузке с использованием команды операционной системы, то на экран дисплея выдается сообщение "File not found".
В любое время в ходе выполнения программы инициированная пользователем система прерываний с консоли может остановить выполнение программы и возвратит управление на консоль.
Прерывание с консоли инициируется путем нажатия клавиши ESC на клавиатуре
консоли. При возникновении прерывания с консоли на экране консоли высвечивается сообщение:
Console Interrupt Break: NIL
За ним на следующей строке появляется подсказка в виде опций прерывания. Пользователь может затем сам решить, как продолжить работу.
Если type - строка, отличная от "COM", то функция (SAVE drive:name.type) сохраняет текущую среду muLISP в виде двоичного SYS-файла name.type на устройстве drive.
Если type отсутствует, то SYS-файлу присваивается тип "SYS". Если отсутствует устройство drive, то SYS-файл сохраняется на текущем устройстве.
Функция (SAVE drive:name.COM) сохраняет интерпретатор muLISP без
компилятора псевдокодов, а также текущую среду muLISP как выполнимый
COM-файл name.COM на устройстве drive. Например:
$ (SAVE 'C:WHALE)
; Сохраняет среду в файле с именем WHALE.SYS
; на дисководе C:
$ (SAVE 'WHALE.COM)
; Сохраняет среду в файле с именем WHALE.COM
; на дисководе, выбранном по умолчанию
Если drive: отсутствует, то COM-файл сохраняется на текущем устройстве. Путем модификации флага в основной странице muLISP есть возможность сохранить и компилятор псевдокодов в COM-файлах, созданных SAVE.
Прежде чем сохранить среду в виде SYS- или COM-файла, функция SAVE автоматически "уплотняет" все активные структуры данных, так что результирующий файл имеет минимальные размеры. Следовательно, размер файла-образа памяти увеличивается с увеличением объема активных структур данных.
Так как COM-файлы больше по размеру, чем SYS-файлы, их компиляторы псевдокодов недействительны, и они не могут быть загружены в действующую систему muLISP, то для сохранения среды muLISP лучше использовать не COM-, а SYS-файлы (по крайней мере в процессе разработки программ).
Если СОМ-файл, созданный функцией SAVE, меньше чем 64К (65536 байт), то он может выполняться как команда MS-DOS. Если СОМ-файл больше, чем 64К, то он может быть преобразован в ЕХЕ-файл с использованием утилиты muLISP COMTOEXE.COM.
Команда вызова данной утилиты имеет следующий вид:
drive1: COMTOEXE drive2: filename.COM drive3: ,
где: drive1 - это устройство, содержащее COMTOEXE.COM,
drive2 - устройство, содержащее filename.COM, a
drive3 - устройство, на котором находится файл с именем filename.EXE.
Заметим, что любое отсутствующее устойство заменяется на текущее.
Функция (LOAD drive:name.type) заменяет текущую среду muLISP на среду, существовавшую во время создания файла drive:name.type.
Если в аргументе функции LOAD .type отсутствует, то по умолчанию подразумевается .sys. Если drive: отсутствует, то SYS-файл загружается на текущее устройство.
Функция LOAD не возвращает какого-либо значения, если SYS-файл
успешно загружен, но начинает выполнение функции, связанной с переменной DRIVER
в среде, которая уже была загружена. Например:
$ (load 'C:WHALE) ; Загружает файл WHALE.SYS
; с дисковода C:
Если SYS-файл не найден, то функция LOAD возвращает NIL.
SYS-файлы могут также быть загружены вместе с MULISP.COM из операционной системы.
Отладочный пакет системы muLISP - это совокупность алгоритмов, обеспечивающих помощь пользователю при проектировании и отладке программ muLISP. Он содержит средства трассировки, прерывания и статистики.
Средства трассировки для каждой функции выдают на экран дисплея информацию о ходе вычисления функции.
Средства прерывания останавливают вычисление функций в критических точках, позволяя пользователю осуществить проверку среды.
Средства статистики помогают определить скорость или глубину критических участков в больших программах.
Средства отладки muLISP находятся в файле DEBUG.LSP, он может быть загружен с помощью команды: (RDS 'DEBUG).
Пусть функции APP и REV определяются следующим образом:
(DEFUN APP (LST1 LST2)
( (NULL LST1) LST2 )
( CONS (CAR LST1) (APP (CDR LST1) LST2) )
)
; --------------
(DEFUN REV (LST)
( (NULL LST) NIL )
( APP (REV (CDR LST)) (LIST (CAR LST)) )
)
Тексты этих функций можно взять здесь.
Функции APP и REV эквивалентны функциям muLISP85 APPEND и REVERSE соответственно, однако APP и REV менее эффективны и имеют максимум два аргумента.
Трассировка функций осуществляется с помощью неразвернутой функции TRACE.
Она вызывается с аргументами, представляющими собой одну или более функций, предназначенных
для трассировки. Например, команда:
(TRACE 'APP 'REV)
трассирует функции APP и REV. Если после этого ввести команду:
(REV '(A B)),
то на экране дисплея вы увидите следующую трассу:
1| REV [LST: (A B)]
2| REV [LST: (B)]
3| REV [LST: NIL]
3| REV = NIL
3| APP [LST1:NIL,LST2: (B)]
3| APP = (B)
2| REV = (B)
2| APP [LST1: (B),LST2: (A)]
3| APP [LST1: NIL,LST2: (A)]
3| APP = (A)
2| APP = (B A)
1| REV = (B A)
(B A)
Если вывод трассы осуществляется слишком быстро, то для временной остановки трассы можно использовать комбинацию клавиш CTRL-S.
С помощью команд:
(SETQ ECHO T)
(WRS 'drive:name.type)
можно направить выходную трассу в файл name.type на устройстве drive:. Как только трассировка закончится, выполните обращение к функции (WRS), которая закрывает файл. Затем можно просмотреть файл в любой нужный момент с помощью текстового редактора.
Для устранения больших объемов ненужной информации можно выбрать момент, когда функция трассировки будет выполнять вывод.
Функция:
(SETQ TRACE NIL)
задерживает вывод трассы для всех функций до тех пор, пока функция TRACE переопределяет
значение, отличное от NIL.
Функция:
(REMFLAG 'TRACE 'name),
где имя - это имя трассируемой функции, задерживает вывод трассы для
данной функции до тех пор, пока не встретится обращение к функции:
(FLAG 'TRACE 'name)
Вывод трассы для всех функций может быть задержен на основе количества вызовов трассируемой функции.
Если управляющая переменная MINCALL имеет своим значением целое положительное число, то весь вывод трассы задерживается до тех пор, пока количество вызовов функции не будет больше или равно этому значению.
Таким же образом на основе количества вызовов может быть задержан вывод трассы для какой-либо одной конкретной функции.
Функция:
(PUT 'MINCALL 'NAME N),
где: NAME - это имя трассируемой функции,
N - положительное целое число,
задерживает вывод трассы функции до тех пор, пока она не будет вызвана N раз.
Вывод трассы для всех функций может быть задержан на основе уровня вложенности вызова функции.
Если управляющая переменная MINLEVEL имеет своим значением положительное целое число, то весь вывод трассы задерживается до тех пор, пока уровень вложенности функции будет больше или равен этому значению.
Точно так же, если MAXLEVEL имеет значением положительное целое число, то вывод трассы задерживается до тех пор, пока уровень вложенности функции будет меньше или равен этому значению.
Точно так же на основе уровня вложенности может быть задержен вывод трассы для какой-либо одной конкретной функции.
Функция:
(PUT 'MINLEVEL 'NAME 'N) ,
где: NAME - это имя трассируемой функции,
N - положительное целое число,
задерживает вывод трассы функции до тех пор, пока уровень ее вложенности больше или равен N.
Точно так же, функция:
(PUT 'MAXLEVEL 'NAME N)
задерживает вывод трассы функции с именем NAME до тех пор, пока уровень ее вложенности меньше или равен N.
Присваивая MAXLEVEL значение 1, можно трассировать вызов функции только верхнего уровня.
Например, функции:
(PUT 'MINLEVEL 'APP2)
(PUT 'MAXLEVEL 'REV1)
(REV '(A B C))
выполняют следующий вывод:
1| REV [LST: (A B C)]
4| APP [LST1: NIL,LST2: (B)]
4| APP = (B)
3| APP [LST1: (B),LST2: (A)]
4| APP [LST1: NIL,LST2: (A)]
4| APP = (A)
3| APP = (B A)
1| REV = (C B A)
(C B A)
Однако даже тогда, когда вывод трассировки был задержан одним из вышеперечисленных способов, трасса может быть выдана на экран дисплея из так называемой истории трассировки. Отладочный пакет автоматически сохраняет "историю" трассировки для последующего восстановления вывода трасс при подобных задержках. "История" сохраняется в буфере фиксированной длины; длина буфера равна значению управляющей переменной HISTLEN. По умолчанию значение HISTLEN равно 15.
Если после предыдущих действий обратиться к функции
(HISTORY),
то на экране появится следующая трасса:
4| APP [LST1: NIL,LST2: (C)]
4| APP = (C)
3| REV = (C)
3| APP [LST1: (C),LST2: (B)]
4| APP [LST1: NIL,LST2: (B)]
4| APP = (B)
3| APP = (C B)
2| REV = (C B)
2| APP [LST1: (C B),LST2: (A)]
3| APP [LST1: (B),LST2: (A)]
4| APP [LST1: NIL,LST2: (A)]
4| APP = (A)
3| APP = (B A)
2| APP = (C B A)
1| REV = (C B A)
Функция CLEAR используется для запрещения трассировки и прерывания функции.
Например, функция:
(CLEAR 'APP 'REV)
запрещает трассировку APP и REV.
Если трассируемая функция прервана, то для счетчика уровня функциональных вызовов
LEVELCOUNT не будет восстановлено его нулевое значение. В этом случае с помощью
функции:
(CLEAR)
восстанавливается нулевое значение LEVELCOUNT и выполняются другие связанные с этим функции.
После вызова функции прерывания вычисление приостанавливается, и вызывается функция muLISP BREAK. Это позволяет проверить содержимое среды в точке прерывания (значения переменных), выдать на экран обратную трассу - схеиу вложенности вызовов функций, а также осуществлять любые изменения в среде. Вы можете "заставить" функцию прерывания осуществлять прерывания только на определенных уровнях вложенности, или только после определенного количества вызовов функции и т.д.
Функция BRK используется для прерывания функций. Она вызывается с одной или
более функциями в качестве аргументов. Например,
(BRK 'REV 'APP)
прерывает работу функций APP и REV.
После обращения к функции:
(REV '(A B C)),
будет выполняться прерывание, и выдается следующее сообщение:
Break-point: REV [LST: (A B C)]
Continue, Break, Abort, Top-level, Restart, System ?
Если вы хотите проверить текущую среду muLISP, выберите опцию "В". Можно также использовать функцию HISTOPY.
Если вы хотите посмотреть стек вызовов функций в точке прерывания, то используйте функцию:
(BACKTRACE)
Функция BACKTRACE выдает на дисплей имена всех функций, вычисляемых в данный момент вместе с их аргументами, начиная с вызова верхнего уровня. В обратную трассу будут включены только те функции, для которых проводилась трассировка или которые были указаны при прерывании.
Для выхода из прерывания обратитесь к функции:
(RETURN)
Вычисление прерванной функции возобновится.
Если вы не хотите, чтобы функция вычислялась дальше, то вместо NIL в предыдущей команде введите имя вычисляемого выражения.
Если же вы хотите прервать вычисление полностью и возвратить управление драйверу muLISP
вышестоящего уровня, обратитесь к функции RETURN:
(RETURN (THROW))
Функция CLEAR, описанная выше, запрещает прерывание функций и восстанавливает их первоначальные определения.
Пользователь может сам выбрать момент, когда прерываемая функция будет действительно прервана.
Функция:
(SETQ BRK NIL)
запрещает все прерывания до тех пор, пока BRK возвращает значения, отличные от NIL.
Функция:
(REMFLAG 'BRK 'NAME),
где NAME - это имя прерываемой функции, запрещает прерывание данной функции до тех пор,
пока возвращается команда:
(FLAG 'BRK 'name).
Прерывание всех функций может быть задержано на основе количества вызовов прерываемых функций.
Если значение управляющей переменной MINCALL - положительное целое число, то все прерывания задерживаются до тех пор, пока количество вызовов функции будет больше или равно этому значению. Точно так же может быть задержано прерывание какой-либо конкретной функции на основе количества вызовов данной функции.
Функция:
(PUT 'MINCALL 'NAME N),
где: NAME - это имя прерываемой функции,
N - положительное целое число,
задерживает прерывание данной функции до тех пор, пока она не будет вызвана N раз.
Прерывание функций может быть задержано на основе уровня вложенности вызова функции. Если значение контрольной переменной BRKLEVEL - положительное целое число, функции не прерываются до тех пор, пока уровень вложенности функции не равен этому значению. Точно так же, на основе уровня рекурсивной вложенности конкретной функции может быть задержано прерывание данной функции.
Функция:
(PUT 'BRKLEVEL 'NAME N),
где: NAME - это имя прерываемой функции,
N - положительное целое число,
задерживает прерывание данной функции до тех пор, пока уровень ее рекурсивной вложенности не равен N.
Например, с помощью функций:
(REMFLAG 'BRK 'REV)
(PUT 'BRKLEVEL 'APP 3)
(REV '(A B C))
будет выполняться следующее прерывание:
Break-point: APP [LST1: NIL, LST2: (A)]
Continue, Break, Abort, Top-level, Restart, System?
Функция (HISTORY) выдаст на экран дисплея трассу:
2| REV [LST: (B C)]
3| REV [LST: (C)]
4| REV [LST: NIL]
4| REV = NIL
4| APP [LST1: NIL, LST2: (C)]
4| APP = (C)
3| REV = (C)
3| APP [LST1: (C), LST2: (B)]
4| APP [LST1: NIL, LST2: (B)]
4| APP = (B)
3| APP = (C B)
2| REV = (C B)
2| APP [LST1: (C B), LST2: (A)]
3| APP [LST1: (B), LST2: (A)]
4| APP [LST1: NIL, LST2: (A)] ,
а функция (BACKTRACE) выдаст следующее:
REV [LST: (A B C)]
APP [LST1: (C B), LST2: (A)]
APP [LST1: (B), LST2: (A)]
APP [LST1: NIL, LST2: (A)]
По завершении вычисления пользователь может определить количество вызовов каждой конкретной отлаживаемой функции.
Значение переменной CALLCOUNT равно общему числу вызовов каждой функции, помеченной для отладки. Счетчик вызовов каждой конкретной функции запоминается в списке свойств переменной CALLCOUNT.
Команда:
(CDR 'CALLCOUNT)
выдает на экран дисплея все помеченные отладчиком функции вместе со счетчиками вызовов для каждой из этих функций.
По завершении вычисления пользователь может также определить максимальный уровень (глубину) вызовов для каждой конкретной функции, помеченной для отладки.
Значение управляющей переменной MAXLEVELCOUNT равен максимальному уровню вызовов для отлаживаемых функций. Максимальный уровень рекурсии для каждой конкретной функции запоминается в списке свойств переменной MAXLEVELCOUNT.
Таким образом, функция:
(CDR 'MAXLEVELCOUNT)
выдает на экран дисплея все помеченные функции вместе с их максимальным уровнем рекурсии.
Пользователь может также определить текущий уровень (глубину) вызовов для каждой конкретной функции, помеченной для отладки.
Значение управляющей переменной LEVELCOUNT равно текущему уровню вызовов для помеченных функций. Текущий уровень рекурсии для конкретных функций запоминается в списке свойств переменной LEVELCOUNT.
Функция
(CDR 'LEVELCOUNT)
выдает на экран дисплея все помеченные функции вместе с их текущими уровнями рекурсии.
Если MESSAGE есть NIL или отсутствует, то данная строка
не вычисляется. Далее выдается строка подсказки в виде опций прерывания:
Continue, Break, Abort, Top-level, Restart, System?
Далее система ждет, пока пользователь выберет одну из опций, указав первую букву ее имени (C, B, A, T или S). Отметим, что данные опции перечислены в порядке усиления их действия:
Для выхода из останова и возврата к вызывающей программе следом за подсказкой прерывания
наберите команду:
(RETURN FORM) ,
где FORM - это выражение, которое вычисляется, и нажмите клавишу Enter.
Например, чтобы вычислить и возвратить OBJECT, переданный с помощью вызова BREAK
в качестве значения функции BREAK, введите:
(RETURN (EVAL BREAK))
При выходе из драйвера BREAK-LEVEL уменьшается; функции READCH и BREAK восстанавливают свои первоначальные значения; значение выражения, которое вводится вслед за RETURN, возвращается как значение останова.
Если после нескольких секунд пользователь не выбрал опцию, генерируется краткое сообщение, информирующее пользователя о возникновении прерывания.
Как только muLISP обнаружит состояние ошибки, вызывается BREAK с соответствующим сообщением об ошибке, позволяющими пользователю принять определенное решение.
Функция BREAK может быть переопределена пользователем для удовлетворения другим требованиям. Посредством введения вызовов BREAK в определения функций пакет прерываний обеспечит отличный механизм отладки.
На следующем шаге мы рассмотрим особенности текстового редактора muLISP85.
Состав системы
Загрузка и работа системы
Редактирование строк
Чтение исходных файлов и файлов среды
Отладчик системы