Back ] Up ] Next ]

БИБЛИОТЕЧНЫЕ ФУНКЦИИ

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

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

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

                  <Sfunc Args> == Result

где Sfunc - имя функции, а Args и Result - образцы, описывающие форматы аргумента и результата. Выходной формат Result иногда будет выражаться в виде объединения нескольких образцов:

                  P1 | P2 | ... | Pn

АРИФМЕТИКА

Сложение:
                     
  <ADD s1 s2> == s3

Вычитание: 
                        <SUB s1 s2> == s3

Умножение: 
                        <MUL s1 s2> == s3

Деление для получения частного:
                     
  <DIV s1 s2> == sQ

Деление для получения остатка:
                     
  <REM s1 s2> == sR

Деление для получения частного и остатка:
                      
<DIVREM s1 s2> == sQ sR

Функции этой группы оперируют с целыми или вещественными числами. Если оба аргумента целые, то результат - целый, в противном случае - вещественный. Разрядность целых не ограничена. Вещественные числа представляются в машинной форме с плавающей точкой. Во входном языке вещественные числа записываются либо с десятичной точкой, либо в форме чисел с порядком, например: 3.14159, 1e-6, -9.99e9. Ограничение на порядок и разрядность мантиссы определено реализацией.

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

делимое = ( частное * делитель ) + остаток (т.е. остаток имеет знак делимого). При делении целых функции DIV и REM в точности соответствуют первому и второму результатам функции DIVREM.

При делении вещественных DIV выдает результат обычного деления, а REM и DIVREM делят нацело с остатком. Частное, хотя и выражает целое число, но представляется в форме вещественного. Остаток дробный, имеет знак делимого.

При делении на нуль возникает ситуация "Unexpected FAIL".

Функции ADD, SUB, MUL, DIV, REM, DIVREM имеют синонимы: "+", "-", "*", "/", "%", которые могут записываться также без кавычек. Вот некоторые примеры:

         <ADD 3  5>     =>    8
         <"+" 3 -5>     =>    -2
         <* -3 2>       =>    -6
         </ 7 3>        =>    2
         <REM 7 3>      =>    1
         <DIVREM 7 -3>  =>    -2 1
         <DIVREM -7 3>  =>    -2 -1

Аргументами арифметических операций могут быть не только числа-значения, но и числа-переменные (см. Объекты и значения).

Математические функции:
                       <GCD sA sB> = sD
                       <ABS sX> == sY
                       <SIGN sX> == -1 | 0 | 1
                       <SQRT sX> == sY
                       <EXP  sX> == sY
                       <LOG  sX> == sY
                       <SIN  sX> == sY
                       <ASIN sX> == sY
                       <SINH sX> == sY
                       <COS  sX> == sY
                       <ACOS sX> == sY
                       <COSH sX> == sY
                       <TAN  sX> == sY
                       <ATAN sX> == sY
                       <TANH sX> == sY

Операция взятия наибольшего общего делителя GCD определена только для целых аргументов. Функция ABS (модуль числа) для целых аргументов выдает целый результат, для вещественных - вещественный. Функция SIGN выдает 1, 0 или -1 (целые) в зависимости от знака числа. Остальные математические функции требуют вещественного аргумента и выдает вещественный результат. Если аргумент целый, то происходит автоматическое преобразование его к виду вещественного.

ВВОД-ВЫВОД

Стандартные каналы ввода 
                       *STDIN *STDLOAD

Стандартные каналы вывода
                       *STDOUT *STDERR

Открыть файл
                       <OPEN s.Chan e.FileName s.Mode> == s.Chan | fail

Закрыть канал
                       <CLOSE s.Chan> ==

Стереть файл
                       <ERASE_FILE e.Filename> ==

Проверить конец файла
                       <EOF s.Chan> == T | F

Читать терм из канала
                       <READ! t.Chan> == t.Term | пусто

Читать выражение из канала
                       <READLN! t.Chan> == e.Expr

Читать литеру из канала
                       <READ_CHAR! s.Chan> == s.Char | пусто

Читать строку из канала
                       <READ_LINE! s.Chan> == e.Chars

Писать термы в канал
                       <WRITE! t.Chan e.Exp> ==

Писать выражение в канал
                       <WRITELN! t.Chan e.Exp> ==

Писать литеры в канал
                       <PRINT! t.Chan e.Exp> ==

Писать строку в канал
                       <PRINTLN! t.Chan e.Exp> ==

Закодировать выражение цепочкой литер
                       <ENCODE s.Table e.Exp> == e.Chars

Декодировать выражение из цепочки литер
                       <DECODE s.Table e.Chars> == T e.Exp | F e.Rest

Преобразование выражения в цепочку литер
                       <TO_CHARS e.Exp> == e.Chars

Ввод/вывод через стандартные каналы (*STDIN и *STDOUT)
                       <READ> == t.Term | пусто
                       <READLN> == e.Expr
                       <READ_CHAR> == s.Char | пусто
                       <READ_LINE> == e.Chars
                       <WRITE e.Exp> ==
                       <WRITELN e.Exp> ==
                       <PRINT e.Exp> ==
                       <PRINTLN e.Exp> ==

*STDIN, *STDOUT *STDERR и *STDLOAD - стандартные каналы ввода-вывода. Они автоматически открываются перед началом работы программы и автоматически закрываются по окончании работы программы. Канал *STDLOAD используется системой как канал начальной загрузки исполняемого кода.

Для определения своих каналов можно воспользоваться директивой $CHANNEL (см. также Рефал-6. Определение объекта), например:

$CHANNEL IN,OUT;

после чего можно использовать в аргументах нижеследующих функций символы *IN и *OUT. При этом первое, что нужно сделать с ними - это открыть канал при помощи функции OPEN.

OPEN устанавливает канал s.Chan на файл с именем e.FileName. Канал s.Chan может быть любым символом-ссылкой. Имя должно быть построено так, чтобы в результате преобразования в цепочку литер посредством функции TO_CHARS получилось имя файла в соответствии с требованиями операционной системы. s.Mode - это слово, которое указывает режим, в котором будет происходить работа с файлом: "r" или "R" - чтение, "w" или "W" - запись, "a" или "A" добавление в конец файла. Если файла, открываемого на чтение, нет в текущем каталоге, то от ищется в каталоге, из которого был загружен интерпретатор ri.exe. В случае успеха результатом является открытый канал s.Chan, а в случае неупеха (в режимах A или R - файл не найден) имеет место fail.

CLOSE закрывает канал s.Chan.

EOF проверяет, что текущая позиция у файла, с которым связан канал s.Chan, находится в конце файла.

ERASE удаляет файл с указанным именем с диска.

READ! читает из канала s.Chan очередное изображение терма. Если не осталось ни одного терма -= выдает пустой результат.

READLN! читает из канала s.Chan выражение. Отличается от READ! тем, что READ! завершается после ввода одного полного терма, а READLN! завершается при одновременном выполнении двух условий:

завершен ввод целого числа строк;

завершен ввод полного выражения (т.е. для каждой введенной левой скобки введена и соответствующая ей правая).

READ_CHAR! читает из канала s.Chan очередную литеру. Если не осталось ни одной литеры - выдает пустой результат.

READ_LINE! читает из канала s.Chan все литеры до ближайшего конца строки (включительно) и выдает их в качестве результата (не включая литеру конец строки). Если не осталось ни одной литеры -= выдает пустой результат.

WRITE! пишет в канал s.Chan изображение выражения e.Exp (так, что его потом можно ввести обратно, терм за термом, с помощью функции READ).

WRITELN! делает то же, что и WRITE!, но в конце, добавляет литеру конца строки.

PRINT! преобразует выражение e.Exp в цепочку литер так же, как это делает функция TO_CHARS, и выводит его в канал s.Chan.

PRINTLN! делает то же, что и PRINT!, но в конце добавляет литеру конца строки.

ENCODE выполняет преобразование выражения e.Exp в строку литер e.Chars так, чтобы возможно было произвести обратное преобразование при помощи функции DECODE. При этом литеры берутся в кавычки, слова, за исключением буквенно-цифровых слов, начинающихся с заглавной буквы, берутся в двойные кавычки, скобки остаются скобками, между элементами вставляются пробелы. Символы-ссылки обрабатываются особым образом при помощи таблицы e.Table. Если в таблице имеется пара, содержащая данную ссылку, то ссылка преобразуется в соответствующее имя, к которому спереди приписывается литера '*'. Если ссылки в таблице нет, то генерируется новое имя, под которым ссылка заносится в таблицу и преобразуется. Для перевода статических символов-ссылок и ссылок, созданных функцией <NEW s.Name>, можно использовать системную таблицу *SYSID.

DECODE выполняет обратное преобразование выражения из цепочки литер, созданной функцией ENCODE. Слова обрабатываются через таблицу. Если в цепочке e.Chars встретится конструкция *Word, а слова Word в таблице нет, то будет создан новый ящик, ссылка на него будет занесена в таблицу под именем Word и помещена в результат e.Exp. Если DECODE обнаружит на входе синтаксическую ошибку, то вырабатывается результат F e.Rest, где e.Rest - остаток входной цепочки литер.

Если перед операцией ENCODE таблица s.Table не содержала дупликатов по имени или значению, то можно быть уверенным, что рабочее выражение

     <DECODE s.Table <ENCODE s.Table e.Exp>>

будет вычислено с результатом в точности равным T e.Exp .

Функции ENCODE и DECODE допускают в качестве пустой таблицы символ 0. При этом если DECODE обнаружит на входе имя со звездочкой, то эта ситуация будет квалифицирована как синтаксическа ошибка.

Функции ввода-вывода READ!, READLN!, WRITE!, WRITELN!, PRINT!, PRINTLN! допускают использование на месте аргумента t.Chan терма вида (s.Chan s.Table). В этом случае они работают как ранее, за исключением того, что символы-ссылки при выводе преобразуются по таблице s.Table в слова с добавлением знака * впереди, а при вводе функциями READ! и READLN! - преобразуются обратно в ссылки, так же как это делается при вычислении функций ENCODE и DECODE. Функции вывода WRITE! и WRITELN! по умолчанию используют для указанной цели встроенную таблицу *SYSID, в которой хранятся имена всех объектов, созданных посредством <NEW Name> или введенных из файла в форме *Name.

Функции READ!, READLN! DECODE допускают во входном потоке выражение с угловыми скобками, обозначающими активные подвыражения (как в результатных выражениях Рефала). При этом имя функции препарируется по правилам ввода символа-ссылки при помощи таблицы s.Table.

TO_CHARS преобразует произвольное выражение в цепочку литер. При этом символы-литеры переходят сами в себя, структурные скобки становятся литерами '(' и ')', слова и числа заменяются на их изображения в виде цепочек литер, ссылки на строки заменяются на содержимое строк, все прочие ссылки переходят в некоторые цепочки литер, которые зависят от реализации.

Функции ввода-вывода READ, READLN, READ_CHAR, READ_LINE, WRITE, WRITELN, PRINT, PRINTLN отличаются от своих двойников с "!" на конце тем, что работают с каналом по умолчанию: ввод из канала *STDIN, вывод в канал *STDOUT.

ПРЕОБРАЗОВАНИЕ СИМВОЛОВ

Число в строку:
                       <SYMB sN> == eT

Строка в число:
                       <NUMB eT> == sN

Слово в строку:
                       <EXPLODE sW> == eT

Строка в слово:
                       <IMPLODE eT> == sW

Литера в число:
                       <ORD sC> == sN

Число в литеру:
                       <CHR sN> == sC

Буквы - в заглавные буквы:
                       <UPPER eA> == eR

Буквы - в строчные буквы:
                       <LOWER eA> == eR

Функции SYMB и NUMB преобразуют символ-число в его изображение и обратно.

Функции EXPLODE и IMPLODE преобразуют слово в его изображение и обратно. Аргумент функции IMPLODE - произвольная последовательность символов-литер.

Функции ORD и CHR преобразуют литеру в число, равное ее коду ASCII, и обратно. Аргумент sN функции CHR - символ число в диапазоне от 0 до 255.

Функции UPPER и LOWER в произвольном выражении заменяют все латинские буквы (только символы-литеры) на их, соответственно, заглавные или строчные эквиваленты.

АНАЛИЗ СИМВОЛОВ И ВЫРАЖЕНИЙ

Тип первого терма:
                       <TYPE eX> == sT eX

Сравнение термов:
                       <COMPARE tA tB> == '<' | '=' | '>'

Длина выражения:
                       <LENGTH eX> == sL

Первые L термов:
                       <FIRST sL eX> == (e1) e2

Последние L термов:
                       <LAST sL eX> == (e1) e2

Функция TYPE проверяет тип первого терма выражения eX, в зависимости от которого формирует символ sT согласно таблице:

Символ sT

Первый терм выражения eX

'B'
'F'
'N'
'R'
'L'
'l'
'D'
'O'
'*'

   выражение в скобках
   символ-слово
   символ-число
   символ-ссылка
   заглавная литера-буква
   строчная литера-буква
   литера-цифра
   литера не буква и не цифра
    выражение eX - пусто    

Функция COMPARE сравнивает два произвольных терма tA и tB. Если tA меньше tB, то результат - '<', если больше, то - '>', если же tA и tB равны, то результат - '='.

Сравнение термов производится согласно следующим правилам:

Любой символ меньше всякого выражения в скобках.

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

Если термы - символы, то каждый из них входит в один из следующих классов:

  • символы-литеры
  • символы-слова
  • символы-числа
  • прочие символы

Классы перечислены в порядке возрастания. Соответственно сравниваются и символы, если они входят в разные классы.

Внутри одного класса символы сравниваются следующим образом:

  • Символы литеры упорядочены как их коды ASCII.
  • Символы-слова преобразуются в свои изображения, которые сравниваются по правилам сравнения выражений, описанным выше.
  • Символы-числа сравниваются как их числовые величины.
  • Результат сравнения прочих символов (символов ссылок и т.п.) зависит от реализации.

Функция LENGTH вычисляет длину выражения в термах. Она могла бы иметь следующее определение на Рефале:

LENGTH {
        t1 e2 = <ADD <LENGTH e2> 1>;
        = 0;
        };

Функции FIRST и LAST делят выражение eX на две части e1 и e2 (т.е. eX равно e1 e2), так что

для FIRST: e1 имеет наибольшую длину, не превосходящую L;

для LAST: e2 имеет наибольшую длину, не превосходящую L;

где L - величина символа-числа sL.

ОПЕРАЦИИ С ТАБЛИЦАМИ

Создать/очистить таблицу
                       <MAKE TABLE [s.tab]> == s.tab

Взять в таблице значение по имени
                       <TABLE_VALUE s.tab s.mode s.name> == s.value

Взять в таблице имя по значению
                       <TABLE_NAME s.tab s.mode s.value> == s.name

Читать всю таблицу
                       <TABLE_LIST s.tab> == e.list

Добавить к таблице новые связи: имя - значение
                       <TABLE_LINK s.tab e.list> ==

Таблица - это разновидность ящика, в котором хранится набор пар: имя - значение. Именем может быть только символ-слово. Значением может быть только символ-ссылка. Логически содержимое таблицы можно представить в форме выражения:

             N1 V1  N2 V2 ...

где Ni - имя, а Vi - соответствующее значение. (В этой же форме представляется форматная переменная e.list функций TABLE_LIST и TABLE_LINK.) Реальное внутреннее представление таблицы может быть другим.

Функция MAKE TABLE позволяет создать новую таблицу. Если аргумент s.tab отсутствует, то создается новый объект - таблица, и вырабатывается ссылка на него. Если аргумент s.tab есть и является ссылкой на объект, то он преобразуется в пустую таблицу, а в качестве значения выдается старая ссылка.

Функция TABLE_VALUE извлекает значение из текущего содержимого таблицы по имени. Детали выполнения этой операции зависят от значения параметра s.mode. Его значение - символ-литера: 'O', 'N', 'U' или 'D'. Мнемоника: Old, New, Update, Delete. Выполнение операции разбивается на 4 последовательные фазы:

  1. Подготовительная фаза: в таблице ищется имя s.name.
  2. Фаза удаления (только в модификациях 'N' и 'D'): если имя найдено, то оно и соответствующее ему значение удаляются из таблицы.
  3. Фаза вставки (только в модификациях 'N' и 'U'): если имени в таблице нет, то создается новый пустой ящик и ссылка на него s.ref помещается в таблицу с данным именем.
  4. Заключительная фаза: если имя в таблице есть, то выдается его значение s.value, иначе выдается символ-число 0.

Таким образом, в модификации 'O' (Old) выдается только старое значение или 0; в модификации 'N' (New) - только новое значение, в модификации 'U' (Update) - старое значение или новое, если старого не было; в модификации 'D' (Delete) - старое значение (если оно было) удаляется из таблицы, а выдается всегда 0.

Функция TABLE_NAME выдает по таблице имя объекта по заданной ссылке (т.е. значению). Параметр s.mode интерпретируется так же как и для функции TABLE_VALUE (с тем отличием что понятия имени и значения меняются местами).

Функция TABLE_LIST выдает в качестве значения целиком всю таблицу в форме списка пар e.list. Упорядоченность пар в списке не определена.

Функция TABLE_LINK добавляет к таблице новые пары, заданные списком e.list. В результате этой операции в таблице могут появиться дупликаты имен или значений. (При наличии в таблице дупликатов по аргументу s.name или s.value результат функции, соответственно, TABLE_VALUE или TABLE_NAME не определен.)

В системе имеются две предопределенные таблицы: SYSTABLE и SYSID. Первая (SYSTABLE) содержит имена глобальных объектов, доступных из любого модуля. Это имена, объявленные при помощи описателей $ENTRY и $EXTBOX, а также имена всех встроенных функций и других  предопределенных объектов (например, SYSTABLE и SYSID). Вторая таблица (SYSID) аккумулирует имена всех возникающих в системе именованных объектов. В ней возможны дупликаты по именам. Она позволяет узнать имя по объекту и потому используется для вывода символов ссылок в системных операциях вывода (в трассировке, аварийной выдаче и т.п.).

СИСТЕМНЫЕ ФУНКЦИИ

Текущее время:
                       <TIME> == e.time
                       <TIME_ELAPSED> == s.time

Текущий шаг (только Рефал-6):
                       <STEP> == s.step

Выйти из программы:
                       <EXIT [s.code]> ==

Читать аргумент команды:
                       <ARG sN> == e.arg

Взять значение переменной окружения:
                       <GETENV e.name> == e.value

Вызвать функцию по имени-ссылке:
                       <APPLY s.fref eA> == e.res

Вызвать функцию по имени-слову (только Рефал-6):
                       <MU s.fname eA> == e.res

Загрузить модуль:
                       <LOAD e.modname>

Удалить модуль из поля программы (только Рефал-6):
                       <DELETE e.modname>

Вызвать командную строку (только Refal-J):
                    <COMMAND t.cmdline [s.in [(e.envp)]]> == s.out s.err

TIME выдает текущую дату и время в виде строки литер:

DD MMM YYYY HH:MM:SS:CC

где 

  • DD - день месяца, 
  • MMM - сокращенное название месяца ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
  • YYYY - номер года, 
  • HH:MM:SS.CC - часы, минуты, секунды и сотые доли секунды.

TIME_ELAPSED выдает время, истекшее с начала работы программы в сотых долях секунды в виде символа-числа.

STEP выдает текущий номер шага.

EXIT завершает выполнение программы, при этом устанавливается код завершения равный s.code (по умолчанию - 0).

ARG выдает аргумент командной строки с номером sN. Если он отсутствует - выдается пустой результат. ARG(0) - начальная часть командной строки, содержащая имя выполняемой программы; ARG(1), ARG(2), ... - аргументы пользователя.

GETENV извлекает из среды (в смысле MS DOS) значение параметра с именем e.name и выдает его. Аргумент - произвольное выражение. Оно преобразуется в строку (как при выводе), которая используется в качестве имени. Длина имени - не более 60 символов. Если параметра с заданным именем нет, результат пуст.

APPLY применяет функцию. на которую указывает символ-ссылка s.fref к выражению eA и выдает результат этого вычисления. Ссылка на функцию в программе может быть записана как *Fname, где Fname - имя функции. Соответствующая функция выбирается из того модуля, в котором записана ссылка.

MU применяет функцию с именем s.fname к выражению eA и выдает результат этого вычисления. Имя функции задается словом. Соответствующая функция выбирается из модуля, в котором записан вызов функции MU.

LOAD загружает модуль e.modname в поле программы. Модуль считывается из одноименного файла. Расширение имени файла по умолчанию - стандартно используемое рефал-системой лдя файлов программ, скомпилированных на промежуточный язык сборки: REX (Рефал-6). При динамической загрузке разрешаются не разрешенные ранее имена внешних функций. Функции загружаемых модулей доступны только через механизм разрешения внешних имен.

DELETE удаляет все функции модуля e.modname из поля программы. Удаленным может быть модуль, загруженный как динамически функцией LOAD, так и статически из командной строки. Имена удаляемых функций становятся неразрешенными в иcпользующих модулях. Они могут снова стать разрешенными в результате загрузки нового модуля функцией LOAD.

COMMAND вызывает командную строку t.cmdline, передавая ей слово s.in как входной поток stdin и список слов e.envp, содержащий строки вида: "name=value". Указанные имена принимают указанные значения как системные переменные и в этом окружении исполняется указанная команда. Команда t.cmdline задается либо целиком одним символом-словом, либо списком слов в скобках, где первое слово - имя команды (программы), остальные слова - параметры. По завершении в качестве результата выдается пара строк (слов), представляющих, соответственно, содержимое потоков stdout и stderr.