               4. Компиляция и исполнение РЕФАЛ-программ

                               Введение

     Компиляция, компоновка и исполнение РЕФАЛ-программ  может  произво-
диться  на  IBM  PC  под управлением любых операционных систем в которых
функционирует какая-либо система программирования для  языка  Си  (будем
считать,  например,  что  это Турбо-Си в MS DOS); на ЭВМ типа PDP-11 под
управлением системы RT-11 или ее производных, таких как TSX; на ЭВМ типа
VAX-11 под управлением VMS. 
     Рефал-система представляет собой совокупность следующих файлов:
   - исполняемый (загрузочный) модуль компилятора,
   - объектная библиотека первичных и интерфейсных функций,
   - объектная библиотека отладчика,
   - объектные модули запускающих программ,
   - командные файлы.
     В  комплект  поставки РЕФАЛ-системы обычно также входят тексты пер-
вичных функций на языке Си, а также диагностические  и  демонстрационные
РЕФАЛ-программы. 
     
                     4.1. РЕФАЛ-система на IBM PC

     На IBM PC РЕФАЛ-система хранится в следующих файлах: 
   . refal.exe - компилятор с РЕФАЛа в виде абсолютного образа памяти; 
   . reflib.olb - библиотека объектных модулей, которая содержит первич-
     ные функции, а также программы, обеспечивающие интерфейс  РЕФАЛа  и
     Си; 
   . rfdbg.olb - библиотека  объектных  модулей,  содержащая  отладочные
     средства; 
   . mainrf.obj и rfdbg.obj - объектные модули запускающих программ; 
   . cld.bat, clg.bat - командные файлы для компиляции, компоновки и за-
     пуска РЕФАЛ-программы в режиме отладки и в обычном режиме; 
     При работе с РЕФАЛ-системой нужно обеспечить доступ к директории, в
которой  она  находится.  Для этого можно указать соответствующий путь в
файле autoexec.bat. 
     Пусть, например, РЕФАЛ-система находится на диске D:  в  директории
RF. Тогда перед началом работы с РЕФАЛ-системой следует выполнить коман-
ду 
     path D:\RF;
     Проще всего включить эту команду в файл autoexec.bat, который нахо-
дится  на  системном  диске,  с тем, чтобы она выполнялась автоматически
всякий  раз,  когда  загружается  MS  DOS.  Если,  например,   в   файле
autoexec.bat команда path имела вид 
     path C:\;C:\UTIL;
то для работы с РЕФАЛ-системой ее надо дополнить:
     path C:\;C:\UTIL;D:\RF;

              4.2. Подготовка исходных текстов РЕФАЛ-программ 
                                                       
     Исходные тексты РЕФАЛ-программ можно подготавливать с помощью любо-
го редактора текстов. Файл с исходными  РЕФАЛ-программами  должен  иметь
записи  длиной  не  более 80 литер. Тип файла (расширение у имени файла)
должен быть REF. 
     Первоначальный текст может быть введен непосредственно с экрана при
помощи команды 
     copy con имя_файла.ref
     Пример. Ввод текста с экрана в файл proba.ref:
     copy con proba.ref
     proba start
      entry go
      extrn print
     go    = <f1  'Привет!'>
     f1 e1 = <print  e1>
      end
     ^Z
     
                    4.3. Компиляция РЕФАЛ-программ

     За  один запуск РЕФАЛ-компилятора обрабатывается один файл, где мо-
жет быть один или несколько РЕФАЛ-модулей. Для компиляции необходимо вы-
дать следующую команду: 
     refal  имя_файла  список_опций
     Список_опций либо пуст, либо имеет следующий вид:
     (опция_1, опция_2, ..., опция_k)
где опция_i - имя опции, представляющее собой цепочку литер, не содержа-
щую пробелов. Имена опций отделяются друг от друга запятыми,  пробелы  в
списке опций недопустимы. 
     Имена опций могут сокращаться до двух букв.
     Список_опций  служит  для установки режимов работы компилятора. До-
пускаются следующие имена опций: 
   . nsource - запретить выдачу исходного текста РЕФАЛ-программы с сооб-
     щениями  компилятора  (листинг).  Если не задана эта опция, листинг
     программы выдается в файл имя_файла.lst. 
   . fname  -  установить режим полных имен. Если эта опция задана, то в
     объектный файл ко всем внутренним именам модуля спереди  приписыва-
     ется  имя  модуля и вслед за ним - литера ":". Например, если MOD -
     имя модуля (оно берется из директивы "start" в РЕФАЛ-программе),  а
     GO - имя некоторой функции, то текстовое изображение имени  функции
     GO  преобразуются  в  MOD:GO. Эти расширенные имена затем можно ис-
     пользовать для  управления  прокруткой  при  отладочном  исполнении
     программы с целью различить функции с совпадающими именами в разных
     модулях. 
   . mmodule - компиляция файла, содержащего несколько модулей. Если за-
     дана эта опция, то файл имя_файла.ref может содержать несколько РЕ-
     ФАЛ-модулей.  Результатом  работы компилятора будут файлы с именами
     имя_модуля.obj. Дополнительным результатом работы  компилятора  при
     этом  будет текстовый файл с именем имя_файла.txt, содержащий имена
     модулей. Если опция не задана, то в файле имя_файла.ref может  быть
     только один РЕФАЛ-модуль. 
   . assem  - компиляция в текст на языке ассемблера. Если опция задана,
     то результатом работы компилятора  будет  файл  с  именем  имя_фай-
     ла.asm,  а  в  случае  многомодульной  компиляции - файлы с именами
     имя_модуля.asm. 
   . nname - запретить вставки в код программы текста  имен  РЕФАЛ-функ-
     ций. Это приводит к некоторому уменьшению размера модуля, но не до-
     пускает применения средств отладки к этому модулю. 
     Пример 1.
     refal test1
     Компилируется  модуль  из  файла test1.ref. Исходный текст модуля с
диагностикой выдается в файл test1.lst. Результат работы  компилятора  -
файл test1.obj. 
     Пример 2.
     refal test2 (ns,as)
     Компилируется  модуль из файла test2.ref. Листинг не выводится. Ре-
зультат работы компилятора - файл test2.asm. 
     На терминал выводится протокол работы компилятора, который содержит
имя компилируемого модуля, его длину, длину файла-результата или сообще-
ния об ошибках, если таковые обнаруживаются в процессе компиляции. 
     Кроме вышеупомянутых, во время работы  РЕФАЛ-компилятора  создаются
еще два временных файла в рабочей директории: sysut1.$rf и sysut2.$rf. В
конце работы компилятора эти файлы уничтожаются. При нехватке  места  на
диске  в процессе компиляции могут появится диагностические сообщения об
ошибках в работе с этими файлами. 
     Если в результате работы компилятора  получен  ассемблерный  модуль
(была  задана  опция  "as"),  то объектный модуль можно получить из него
обычным вызовом ассемблера PC. 
     
                    4.4. Исполнение РЕФАЛ-программ

     Запуск РЕФАЛ-программы производится с помощью запускающей программы
mainrf, реализованной на Си, причем РЕФАЛ-программа вызывается из нее по
имени GO. Полученный после компиляции объектный  модуль  РЕФАЛ-программы
должен быть скомпонован с файлом mainrf.obj при помощи компоновщика Тур-
бо-Си: 
     tlink mainrf имя_файла c0l,имя_файла,nul,reflib cl
     Здесь tlink.exe, c0l.obj и cl.lib - файлы Турбо-Си, которые  обычно
поставляются вместе с РЕФАЛ-системой. 
     Команда tlink создает исполняемый файл имя_файла.exe.
     Если вызвать этот исполняемый файл, то  начнет  работать  программа
mainrf,  которая  формирует  начальное поле зрения вида <GO> и запускает
РЕФАЛ-машину. 
     Допустим, что требуется запустить РЕФАЛ-машину, начиная  с  функции
JOB. Тогда в РЕФАЛ-программе должно быть предложение вида 
     GO  =  <JOB> 
     Команды  компиляции, компоновки и запуска собраны в командном файле
clg.bat: 
     @refal %1 (ns)
     @tlink/d mainrf %1 c0l,%1,nul,reflib cl
     @erase %1.obj
     @%1
     Имя файла, содержащего  РЕФАЛ-программу  (без  указания  расширения
".ref"), является параметром при вызове этого командного файла: 
     clg имя_файла
     Необходимые  изменения (например, если требуется задать другой спи-
сок опций или компоновать программу из нескольких  РЕФАЛ-модулей)  можно
внести в этот файл при помощи любого текстового редактора. 
     
                         4.5. Средства отладки

                   4.5.1. Вызов подпрограммы отладки

     Подпрограмма mainrf не содержит средств отладки. Ею следует пользо-
ваться для запуска уже отлаженных РЕФАЛ-программ. При  отладке  программ
следует  производить  компоновку  не  с  модулем mainrf.obj, а с модулем
rfdbg.obj, включая также библиотеку rfdbg.olb, т.е. исполняя команду 
     tlink/d rfdbg имя_файла c0l,имя_файла,nul,reflib rfdbg cl
     Команды компиляции, компоновки и запуска для отладки 
собраны в командном файле cld.bat : 
     @refal %1 (ns)
     @tlink/d rfdbg %1 c0l,%1,nul,reflib rfdbg cl
     @erase %1.obj
     @%1
     Здесь после вызова исполняемого файла начинает  работать  программа
rfdbg.  Она  выдает  приглашения, в ответ на которые пользователь должен
задать управляющую информацию. Затем rfdbg анализирует полученную инфор-
мацию.  Если при этом обнаруживаются ошибки, работа rfdbg заканчивается.
Если же ошибок нет, начинается исполнение РЕФАЛ-программы. 
     Выдается 11 приглашений:
     > (function list):
     >= (function list):
     = (function list):
     != (function list):
     < (function list):
     <= (function list):
     TRAP (function list):
     STOP (step number):
     FROM (step number):
     TO (step number):
     E1= (y/n):
     Управляющая информация, задаваемая в ответ на эти приглашения,  де-
лится на две группы: 
   - управление остановом, 
   - управление прокруткой.
     Вся она имеет один из двух форматов:
     N               - номер шага,
     F1 F2 ... FK    - список имен функций.
     Обратите внимание, что список имен функций задается через пробел, а
не через запятую. 
    
                      4.5.2. Управление остановом

     В отладчике РЕФАЛ-системы  имеются  средства  управления  остановом
двух  типов:  STOP-условия, которые позволяют задавать останов по номеру
шага, и TRAP-условия, которые позволяют задавать останов по имени  функ-
ции. 
     Если в ответ на приглашение:
     STOP (step number):
ввести  целое число N, то работа РЕФАЛ-программы прекратится, как только
будет выполнено N шагов. Например, если задано 
     STOP (step number):   30000
то РЕФАЛ-программа остановится перед началом выполнения шага 30001. 
     Эта возможность полезна в тех случаях, когда отлаживаемая программа
зацикливается. 
     Если в ответ на приглашение
     TRAP (function list):
ввести список имен функций
     F1 F2 ... Fn
то это будет означать, что когда ведущим станет функциональный терм вида
<F1  Ee> или <F2 Ee> и т.д., РЕФАЛ-программа остановится, не приступая к
выполнению очередного шага (здесь F1, F2 ... Fn -  функции,  объявленные
ловушками, а Ee - объектное выражение). 
     Эта  возможность полезна в тех случаях, когда требуется выдать сос-
тояние поля зрения, копилки и ящиков в момент обращения к одной из функ-
ций-ловушек. 
     Если TRAP-условие задано вместе со STOP-условием, останов  произой-
дет как только будет удовлетворено хотя бы одно из условий. 
     
                     4.5.3. Управление прокруткой

     Выдача протокола о ходе выполнения РЕФАЛ-программы (прокрутка) дает
возможность получать информацию о выполнении отдельных шагов РЕФАЛ-маши-
ны,  а также об обращениях к указанным функциям и о результатах этих об-
ращений. 
     При выдаче информации об отдельном шаге указываются 
   - номер шага, 
   - ведущий функциональный терм, 
   - результат выполнения шага.
     При выдаче информации об обращениях к заданным функциям указывается 
   - номер шага, на котором произошло обращение;
   - ведущий терм;
   - номер шага, на котором завершилось полное  вычисление  обращения  к
функции; 
   - окончательный  результат замены, т.е. то выражение, которое получа-
ется, когда в выражении, возникшем из обращения к функции,  не  осталось
ни одного функционального терма. 
     Задание на прокрутку может быть двух видов:
   - задание диапазона прокрутки;
   - задание условий прокрутки.
     Диапазон прокрутки задается с помощью приглашений
     FROM (step number):
     TO (step number):
в ответ на которые нужно ввести целые числа Nf и Nt.
     Задание  диапазона означает, что следует выдавать информацию только
о тех шагах, номера которых лежат в интервале от Nf до Nt. Выдача инфор-
мации о тех шагах, номера которых меньше Nf или больше Nt - запрещена. В
частности, если Nf>Nt, то никакая информация выдаваться не будет. 
     Если Nf не задавать, но задать Nt, или хотя бы одно  условие  прок-
рутки, то считается, что Nf=1. 
     Если  же  задание "TO" не установлено, но определено задание "FROM"
или хотя бы одно условие прокрутки,  то  считается,  что  Nt=2147483647,
т.е. практически "бесконечность". 
     Таким  образом, если диапазон прокрутки не задан, но задано хотя бы
одно условие прокрутки, то Nf=1 и Nt=2147483647. 
     Если диапазон прокрутки не пуст, и  не  задано  ни  одного  условия
прокрутки, то считается, что следует выдавать информацию обо всех шагах,
лежащих в этом диапазоне. 
     Приведем примеры заданий на прокрутку, состоящих только из указания
диапазона. 
     Пример 1.
     FROM (step number):  1
     Печатается информация обо всех шагах.
     Пример 2.
     FROM (step number):  1000
     Печатается информация обо всех шагах, начиная с шага 1000.
     Пример 3.
     TO (step number):  5000
     Печатается информация обо всех шагах, начиная с шага 1 до шага 5000
включительно. 
     Пример 4.
     FROM (step number):  500
     TO (step number):  600
     Печатается информация обо всех шагах, начиная с шага  500  до  шага
600 включительно. 
     Теперь рассмотрим, как задаются  условия прокрутки.
     В то время как диапазон прокрутки накладывает ограничения на номера
шагов, для которых должна выдаваться информация, условия прокрутки  ука-
зывают, какую именно информацию и о каких функциях следует выдавать. 
     Условия прокрутки задаются в ответ на приглашения
     > (function list):
     >= (function list):
     = (function list):
     != (function list):
     < (function list):
     <= (function list):
в виде списка функций F1 F2 ... Fn. 
     Список  функций, в частности, может быть пустым. Под именем функции
подразумевается то имя, которое она имеет внутри того модуля, в  котором
она описана, имена функций в списке функций разделяются пробелом. 
     Смысл управляющей информации:
   ">"  - выдавать информацию о каждом шаге, начиная с момента обращения
         к заданной функции и до полного завершения ее исполнения, вклю-
         чая  информацию об исполнении всех функций, которые она вызыва-
         ет; 
   ">=" - то же, что для ">", плюс информация о поле  зрения,  сформиро-
         ванном в результате работы заданной функции; 
   "=" - выдавать информацию о том шаге, на котором происходит обращение
         к заданной функции; 
   "!=" - не выдавать информацию о том шаге, на котором происходит обра-
         щение к заданной функции; 
   "<" - не выдавать информацию о работе заданной функции ; 
   "<="  -  информацию  о работе заданной функции не выдавать, но выдать
         обращение к этой функции и сформированное ею поле зрения. 
     Каждое условие может задаваться независимо от всех других,  но  при
этом  надо учитывать ситуации, которые возникают из-за перекрестного об-
ращения функций друг к другу. 
     Например: 
     > (function list): FUNC1 FUNC2
     >= (function list): FUNC
     = (function list): PSI FI
     != (function list): FI EPS
     < (function list): XXX
     <= (function list): YYY
     Если в приведенном примере FUNC1 вызывает XXX и YYY, то будет выда-
ваться информация о работе FUNC1 и обо всех вызываемых ею функцций, иск-
лючая XXX и YYY, причем об XXX информации не будет никакой,  а  для  YYY
будет выдан шаг обращения к ней и сформированное ею поле зрения. 
     В  общем случае условия прокрутки следующим образом истолковываются
в процессе исполнения РЕФАЛ-программы. 
     Управление прокруткой может находиться в одном из  трех  состояний:
S1, S2 или S3. Оно может переходить из состояния S1 в состояние S2 и об-
ратно, а также из состояния S2 в состояние S3 и обратно.  Непосредствен-
ный переход из S1 в S3 или из S3 в S1 - невозможен. 
     Переходами  между состояниями S1 и S2 управляют условия ">" и ">=".
Переходами между состояниями S2 и S3 управляют условия "<" и "<=". Усло-
вия  "=" и "!=" управляют выдачей информации в состоянии S2. Таким обра-
зом, получается следующая схема переходов: 

                              =,!=
          ------   >,>=      ------   <,<=     ------
          |    |  ------>    |    |  ------>   |    |
          | S1 |             | S2 |            | S3 |
          |    |  <------    |    |  <------   |    |
          ------             ------            ------

     В начале работы прокрутка находится в состоянии S1. 
     Находясь в состоянии S1, прокрутка выполняет РЕФАЛ-программу до тех
пор, пока не встретится обращение к функции, для которой было задано од-
но из условий ">" или ">=". Тогда прокрутка переходит  в  состояние  S2,
причем, если задано ">=", но не задано ">", то выдается обращение к этой
функции. 
     Возврат в состояние S1 происходит только после того, как  полностью
закончится вычисление обращения к функции, по которому произошел переход
из S1 в S2. При этом, если для этой функции было задано ">=", но не  за-
дано  ">", то при возврате в S1 выдается окончательный результат замены,
т.е. то выражение, которое возникло в результате полного вычисления  об-
ращения к функции. 
     Находясь в состоянии S2, прокрутка выполняет РЕФАЛ-программу до тех
пор, пока не встретится обращение к функции, для которой было задано ус-
ловие  "<"  или  "<=". Тогда прокрутка переходит в состояние S3, причем,
если задано "<=", то выдается обращение к этой функции. 
     Возврат в состояние S2 из состояния S3 происходит только после  то-
го, как полностью закончится вычисление обращения к функции, по которому
произошел переход в S3 из S2. При этом, если для этой функции было зада-
но  "<=",  но не задано "<", то при возврате в S2 выдается окончательный
результат замены, т.е. то выражение, которое возникло в результате  пол-
ного вычисления обращения к функции. 
     Если  прокрутка  находится в состоянии S2, и для текущей функции не
задано ни "<", ни "<=", то прокрутка выполняет один  шаг  и  остается  в
состоянии  S2. При этом, если для текущей функции задано условие "=", то
выдается обращение к функции и результат  непосредственной  замены  (ре-
зультат выполнения шага). 
     Например, если заданы условия
     >= X
     =  Y1 Y2 Y3
     <= Z1 Z2
то выдача будет начинаться при каждом обращении к функции X. Будет выда-
ваться обращение к X и результат ее полного вычисления. В  процессе  вы-
числения X будут выдаваться обращения к Y1, Y2, Y3 и непосредственно ре-
зультаты замены, а также обращения к Z1 и Z2 и результат полного  вычис-
ления этих обращений. 
     Иногда  требуется,  чтобы  выдавались  только обращения к указанным
функциям и окончательные результаты замены. Этого можно добиться,  задав
для них условия "=" и "<=". 
     Если  задать  только условие "<=", то будет выдаваться информация о
всей программе, а о заданных функциях - только обращение к ним и резуль-
тат их работы. 
     И,  наконец,  в тех случаях, когда требуется запустить прокрутку по
всем функциям, с первого шага до последнего, можно задать  условие  "!="
для несуществующей функции. 
     
             4.5.4. Перехват останова по неотождествлению

     Легкость  отладки РЕФАЛ-программ в значительной степени обусловлена
тем, что различные нарушения в структуре  обрабатываемых  объектов,  как
правило,  довольно быстро приводят к авосту "отождествление невозможно".
Однако это приятное свойство утрачивается, если какие-либо функции,  на-
писанные на Си, не проверяют правильность аргумента. Поэтому при отладке
функций, написанных на Си, необходимо тщательно тестировать как те  слу-
чаи,  когда  обращение  к функции имеет допустимый вид, так и те случаи,
когда аргумент функции задан неверно. Всегда, когда аргумент не  принад-
лежит  к  области  определения  функции, эта функция должна вырабатывать
авост "отождествление невозможно". 
     Таким образом, всякий тест, предназначенный для  проверки  функций,
написанных  на Си, должен включать как правильные, так и заведомо непра-
вильные обращения к этим функциям. 
     Для прогона таких тестов предусмотрен особый режим "E1=(y/n)". Если
РЕФАЛ-программа  исполняется в этом режиме, то при возникновении состоя-
ния "отождествление невозможно" выполнение РЕФАЛ-программы не  прекраща-
ется. Вместо этого выдается номер текущего шага, предупреждающее сообще-
ние и ведущий функциональный терм. Затем ведущий терм заменяется на пус-
тое выражение, и работа РЕФАЛ-программы продолжается. 
     Таким образом, РЕФАЛ-программа исполняется так, словно в конце каж-
дой функции добавлено предложение 
     E1 =  
     Этому обстоятельству режим "E1=" и обязан своим названием. 
     Для того, чтобы РЕФАЛ-программа исполнялась в режиме "E1=", необхо-
димо в ответ на приглашение 
     E1=(y/n):
ответить "y".
