YLISP 3.7 WIN32





                              Y L i s p  3.7

                  = Дополнительные возможности системы =


     В данном файле перечисляются наиболее существенные расширения, включен-
     ные в систему YLisp 3.7, дополнительные переменные и функции, не специ-
     фицированные в стандарте [CLTL], диалоговые средства, которые обеспечи-
     вают  удобный  интерфейс  и  отладку программ. Для получения подробной
     информации  о  функциях  и  переменных,  упомянутых здесь, используйте
     справку (F1 на имени функции).

     Свертка-развертка (rolling)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     Свертка образа Лисп-среды (rolling out) есть копирование (дамп) текуще-
     го содержимого основных областей памяти интерпретатора:  списковых яче-
     ек, ячеек символов и кучи - в файл на диске. Развертка образа Лисп-сре-
     ды (rolling in) есть восстановление содержимого  памяти  интерпретатора
     из файла свертки.

     Традиционно, в качестве расширения файла свертки  используется  ".ROL".
     Помимо указанных областей, в этом .ROL-файле сохраняются  параметры ин-
     терпретатора: размеры регионов, цвет окон, значения некоторых режимов и
     т.п. Механизм свертки-развертки позволяет осуществить  быстрый  рестарт
     без загрузки исходных файлов, а также используется  при  вызове подпро-
     цесса (spawn). Ниже описываются  встроенные  примитивы,  обеспечивающие
     пользователю непосредственный контроль к перечисленным средствам.

     - Специальная переменная *roll-pathname* всегда связана с  именем  пути
       ROL-файла, с которым была выполненa последняя  операция  свертки  или
       развертки.

     - Функцию rollin вызывает развертку файла, указанного в  качестве аргу-
       мента.

     - Функция rollout осуществляет свертку  текущего  образа  Лисп-среды  в
       файл на диске.

     Создание подпроцесса (spawn)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     Система YLisp  предоставляет  возможность  выполнения  любой  программы
     (подпроцесса) без выхода из среды  интерпретатора.  Это  осуществляется
     обращением к функции spawn, которая  выгружает  текущую  Лисп-среду  во
     временный файл, освобождает выделенную под Лисп-структуры память  и за-
     пускает указанную в качестве аргумента программу.

     Редактор
     ~~~~~~~~
     Система  YLisp  допускает  использование  любого  внешнего  редактора,
     который  вызывается  в  режиме  подпроцесса  (с  помощью  spawn). Путь
     выполняемого  файла  этого  редактора  должен  быть помещен в качестве
     значения специальной переменной *editor-pathname*. Установить значение
     этой переменной необходимо для правильной работы встроенной функции ed
     и других компонентов системы, например, отладчика. Сохранить установку
     для последующих сеансов можно вызовом функции rollout.

     Символьный отладчик (break-loop debugger)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     Система программирования YLisp имеет  достаточно  мощный  отладчик,
     который позволяет

     - просматривать стек вызовов, перемещаясь по нему вверх и вниз,

     - просматривать  значения  параметров  функций  (встроенных и определя-
       емых), локальных переменных (как лексических, так и специальных),

     - редактировать формы, находящиеся в стеке,

     - редактировать определения функций и макросов,

     - модифицировать значения переменных и параметров, включая ключевые,

     - оценить любую форму так, словно это делается на верхнем уровне.

     Выход из отладчика возможен как в точку вызова, так и  следующими двумя
     способами:

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

       2) Возврат значения - вместо значения некоторых  форм  допустимо вер-
          нуть другое, так называемое козначение.  Такой возврат возможен из
          точек прерываний, вызванных некоторыми `непродолжаемыми' в обычном
          смысле ошибками, а также из состояния пошагового оценивания (step)
          для самой нижней формы.

          Осуществляется возврат козначения вводом

               "(return )"

          в ответ на подсказку отладчика "debug>" или обработчика прерываний
          "break>".

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

     Суперскобки {  }
     ~~~~~~~~~~~~~~~~
     Известную трудность для программирующих на Лиспе представляет синтакси-
     ческий баланс скобок ( ). Дабы избавить программиста  от  утомительного
     подсчета числа необходимых закрывающих скобок, в YLisp встроены так на-
     зываемые суперскобки (super parentheses) - макрознаки '{' и '}'.  Тако-
     вые существуют в диалектах Interlisp и FranzLisp. Как и круглые скобки,
     суперскобки должны быть сбалансированы. Открывающая '{'  ведет  себя  в
     точности так же, как и '('. За ней могут следовать какие-либо вложенные
     подсписки. Закрывающая '}' завершает все эти подсписки,  "вставляя" ав-
     томатически требуемое число круглых ')'. Примеры  синтаксически эквива-
     лентных S-выражений:

          {a b (c d (e f}           эквивалентно    (a b (c d (e f)))
          {a {b (1 2} (c d (e f}    эквивалентно    (a (b (1 2)) (c d (e f)))

     Программа   структурной   печати    (вызываемая,    когда    переменная
     *print-pretty* отлична от nil) для списков  со  вложенными  подсписками
     автоматически формирует такой печатный вид, который содержит суперскоб-
     ки вместо обычных на каждом третьем уровне вложенности.

     При вводе выражений с суперскобками нужно учитывать следующее.

     - Информация о вложенности суперскобок не сохранятся  между  различными
       вызовами функции read и между считыванием из различных файлов.

     - Сочетание   #{   отнюдь  не  предназначено для ввода вектора, как это 
       делает сочетание #(. Так что конструкция

               #{1.0 2.0 (3.0 4.0}

       недопустима. Но допустима форма

          {1.0 2.0 #(3.0 4.0}.

     - Синтаксис #{ } зарезервирован в системе YLisp  в  качестве  печатного
       вида стандартных объектов (см. файл CLOS.TXT), который не зависит  от
       значения *print-pretty*.


     Загрузка файлов и формирование проекта (build project)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     Коммон Лисп-программа, естественно, может состоять из  нескольких моду-
     лей, каждый из которых может, в свою очередь, включать несколько исход-
     ных файлов. Загрузка каждого их них выполняется с помощью функция load.
     В системе YLisp ключевой аргумент :verbose этой функции  несет дополни-
     тельную нагрузку: если явно указать его значение, отличное от  nil,  то
     содержимое загружаемого файла будет  отображаться  на  экране,  в  окне
     *terminal-io*.

     По-особенному  реализована  возможность  автоматической  загрузки неск-
     ольких модулей с целью формирования проекта  (ala  утилита  make). Гло-
     бальная переменная *modules* содержит список, в котором, вместе  с име-
     нем каждого из файлов проекта, сохранена дата его последней модификации
     в универсальном формате времени (universal time), какой она была  в мо-
     мент последней загрузки файла. Функция require сама  формирует значение
     *modules* (оно запоминается в файле свертки) и  автоматически загружает
     все исходные файлы, которые были изменены позже сохраненной даты.

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

     Таблицы клавиш (keymaps)
     ~~~~~~~~~~~~~~~~~~~~~~~~
     Таблица клавиш содержит информацию  о  назначении  клавиатуры,  которое
     действует в конкретной среде работы, или конкретном  диалоге,  системы.
     В YLisp эти таблицы реализуются ассоциативными списками, в которых зна-
     ки,  представляющие  клавиши  (возможны  аккорды,   задаваемые   битами
     Control, Alt или Shift), связываются с функциями  без  аргументов (точ-
     нее, объектами типа function). В системе  предусмотрены  следующие гло-
     бальные переменные, имеющие в качестве значений таблицы клавиш.

     *keymap*        Таблица клавиш верхнего уровня интерпретатора.

     *break-keymap*  Таблица клавиш, предопределяющая действия в среде пре-
                     рывания.

     *step-keymap*   Назначение клавиш при пошаговом оценивании (step).

     *debug-keymap*  Назначение клавиш, действующих в сеансе отладчика.

     Изменить назначение клавиатуры, действующее в том или ином  режиме, до-
     бавить или переопределить реакцию системы на нажатие  определенной кла-
     виши можно с помощью макроса defkey. Выяснить печатный вид интересующей
     клавиши легче всего при помощи такого рода кода:

                     (dotimes (i 10) (print (read-char)))


     Экранный ввод-вывод, управление курсором
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     Понятие потока расширено классом "окно". При запуске системы создается
     три   таких  объекта:  *terminal-io*  (а  также *query-io* и несколько
     других  переменных,  связанных  с  одним  потоком),  *status-output* и
     *gc-output*.   Все   стандартные   потоки,   кроме   *terminal-io*   и
     *gc-output*    можно  переназначать.  *terminal-io*  не  рекомендуется
     переназначать   в  CLTL2,  а  *gc-output*   -   потому,   что   выводу
     сборщика  мусора это не помешает. Дополнительные  окна  можно  создать
     функцией  MAKE-WINDOW,  а закрыть - функцией  CLOSE.  Обычные  функции
     вывода   и   чтения  поддерживают  такие  потоки.   Ниже   перечислены
     функции,  которые  могут  быть полезны при реализации интерфейса.

     (MAKE-WINDOW  rect  color)  - создание окна в области экрана, заданной
     вектором  rect  #(top  left  bottom  right). Координаты области экрана
     задаются  начиная с нуля. Color: старый - добрый BIOS - цвет: байт,
     биты в котором отвечают за цвета и дополнительные атрибуты

            7 6 5 4 3 2 1 0
            | | | | | | | Синий текст
            | | | | | | Зеленый текст
            | | | | | Красный текст 
            | | | | Повышенная яркость текста
            | | | Синий фон
            | | Зеленый фон
            | Красный фон
            Повышенная яркость фона

     При  задании цвета удобно пользоваться шестнадцатеричными константами,
     например,  #x1D.  Цвет, указанный при создании окна может быть изменен
     позднее.  Операция  создания  окна  не  производит  никакого вывода на
     экран.

     (CLOSE stream) - обычная функция закрытия потока. Необходимо закрывать
     ненужные  окна,  так  как  при  открытии  окна  выделяется память. При
     попытке закрыть одно из трех стандартных окон выдается ошибка.

     (WINDOW-SIZE  wstream)  -  форма,  доступная для setf, устанавливает и
     возвращает  вектор #(rows columns), содержащий размеры окна, заданного
     параметром wstream. Чтобы узнать размер всего экрана, нужно передать в
     запросе в качестве wstream NIL.

     (WINDOW-POSITION  wstream)  -  форма,  доступная  для  setf - чтение и
     изменение  позиции окна. Может понадобиться, например, чтобы подвинуть
     или  скрыть,  убрав  за  пределы экрана некоторые из стандартных окон.
     Позиция в начале координат - #(0 0). Будет выдана ошибка, если одна из
     координат  устанавливается  меньшей 0, однако, координату, большую чем
     размер консоли, усановить можно. Этим можно пользоваться, чтобы скрыть
     вывод сборщика мусора.

     (CURSOR-POSITION  wstream)  -  форма,  доступная  для  setf - чтение и
     установка позиции курсора, одновременно с текущей позицией вывода. При
     установке  возвращает  предыдущую  позицию  курсора.

     (SET-CURSOR-SHAPE  shape)  -  установить  вид  курсора. Параметр shape
     может  принимать следующие значения: NIL - скрыть курсор, возвращается
     T/NIL,  соответствующее  прежнему  состоянию  курсора,  T  -  показать
     курсор,  возвращается  T/NIL,  fixnum  > (<) 0 - установить заданное в
     процентах  заполнение  курсора  (используется  абсолютное  значение) и
     показать (скрыть) курсор. Возвращается +/- прежнее заполнение курсора.

     (WINDOW-COLOR  wstream)  -  форма,  доступная  для  setf  -  чтение  и
     установка  текущего  цвета вывода. При установке возвращает предыдущий
     цвет.

     (CLEAR-WINDOW wstream) - заполняет всю область окна пробелами текущего
     цвета.

     (WINDOW-SHOT  wstream)  -  запоминает  содержимое  экрана  в  области,
     принадлежащей окну во внутренний буфер.

     (WINDOW-RESTORE    wstream)    -   восстанавливает   область   экрана,
     принадлежащую   окну   содержимым   буфера,   сохраненным  при  вызове
     предыдущей  функции.  Возможно  только  поочередное использование этих
     функций.  При  их  разработке  имелись  в  виду  две  возможности: 1 -
     сохранение  содержимого  окна,  которое  будет временно закрыто другим
     окном;  2  -  сохранение экрана с содержимым нижележащего окна в буфер
     закрывающего  его  окна. CLOSE так же как и WINDOW-RESTORE и изменение
     размера окна освобождает память, выделенную под буфер.

     Функции  (VIEWSTRINGS  strings  &optional  (title  "")  (prompt "")) и
     (VIEWOBJ  obj  &optional  (title  "") (prompt "")) - функции просмотра
     списка   строк  и  произвольного  (большого)  лисп-объекта  в  окне  с
     прокруткой.

     Обычные  функции  чтения  read,  read-line  и т.п. поддерживают ввод и
     редактирование  в  пределах  окна,  а  функции  чтения одного символа,
     такие,   как   read-char,   read-char-no-hang,  peek-char  могут  быть
     использованы   для   организации   работы  с  управляющими  клавишами.
     Назначение  директивы  FORMAT  изменения  регистра  изменено: ~n(...~)
     изменяет цвет выдачи на n. Атрибут шрифта литеры, описанный в CLTL2
     не исключен, как того требует X3J13, а кодирует ее цвет.

     Системные функции и переменные
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

     *arguments* - список строк - аргументов, переданных программе при 
     запуске. Первый элемент списка - полное имя исполняемого модуля 
     программы.

     (CURRENT-DIRECTORY) - возвращает текущую директорию

     (OSDIRECTORY path) - выдает список файлов в виде списка записей 
                          типа OSDIRREC

     (SET-CLIPBOARD str) - копирует строку str в буфер обмена Windows.
                           результат: t - успех, nil - неудача.

     (GET-CLIPBOARD) - результатом является строка, содержащая текст из
                       буфера обмена или nil, если в буфере не текст или 
                       произошла ошибка.

     Многопоточность
     ~~~~~~~~~~~~~~~

     Основной   лисп-функцией   реализации   многопоточности  является  ф-я
     thfuncall  -  аналог  funcall, инициирующий выполнение функции в новой
     нити.  Функция возвращает целое число - идентификатор запущенной нити.
     Идентификатор    является    уникальным    в    течение   лисп-сессии.
     Многопоточность  реализована  с  целью  использования ylisp в windows-
     приложениях.

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

     Несмотря  на  многопоточность,  сборка  мусора  не  может  выполняться
     независимо.  Нить,  испытывающая  недостаток памяти, начинает ожидать,
     пока  все  остальные  нити  придут  в состояние, подходящее для начала
     сборки   мусора.   В   основном  это  выделение  памяти  или  операция
     ввода-вывода. В этот момент все нити синхронизованно занимаются только
     сборкой.  Все  это может привести к замиранию всех ниток, если одна из
     них  не  достигает  длительное  время  точки  проверки  на  недостаток
     ресурсов.  Очевидное - ожидание ввода, функция sleep - имеют указанные
     проверки.

     Консольный  ввод-вывод имеет некоторую синхронизацию: функции верхнего
     уровня  захватывают  "мутекс"  ввода или вывода и осуществляют его без
     путаницы. Функции отладочного в/в имеют приоритет, причем это основная
     цель синхронизации в/в (отладка многопоточных программ).