r4 - 04 Jun 2005 - 02:31:09 - OrloVYou are here: TWiki >  Refaldevel Web > RefalPlus > RefalPlusBook > RefalPlusBookChapIII

Глава III. Библиотека функций

1. Использование библиотечных функций

Составной частью системы Рефал Плюс является библиотека функций, состоящая из нескольких модулей.

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

$use MMMM;

В результате этого в модуль пользователя будут импортированы объявления всех функций, входящих в библиотечный модуль MMMM.

В настоящее время библиотека функций состоит из следующих модулей:

ACCESS - функции прямого доступа к частям выражений.
APPLY - функция для вызова функций, переданных через параметры.
ARITHM - функции целочисленной арифметики.
BOX - функции для работы с ящиками.
CLASS - предикаты для проверки принадлежности символов к различным классам символов.
COMPARE - предикаты для сравнения выражений .
CONVERT - функции для выполнения преобразований между различными типами данных.
DOS - функции для связи с операционной системой.
STDIO - объявления стандартных каналов ввода-вывода и функции для стандартного ввода-вывода.
STRING - функции для работы со строками.
TABLE - функции для работы с таблицами.
VECTOR - функции для работы с векторами.

В дальнейшем в библиотеку могут быть добавлены и другие модули.

2. ACCESS: прямой доступ к выражениям

$func  LENGTH  e.Exp = s.ExpLen;
$func? LEFT    s.Left  s.Len e.Exp = e.SubExp;
$func? RIGHT   s.Right s.Len e.Exp = e.SubExp;
$func? MIDDLE  s.Left  s.Right e.Exp = e.SubExp;
$func? L       s.Left  e.Exp = t.SubExp;
$func? R       s.Right e.Exp = t.SubExp;

Эти функции используются для прямого доступа к частям выражений. Их аргументы s.Left, s.Right и s.Len должны быть неотрицательными целыми числами. e.Exp может быть произвольным объектным выражением.

Если s.Left, s.Right или s.Len не являются неотрицательными целыми числами, результатом функций является ошибка $error(Fname "Invalid argument"), где Fname - имя функции.

LENGTH выдает длину выражения e.Exp, измеренную в термах. А именно, если объектное выражение Oe имеет вид Ot1 Ot2 ... OtN, то N - его длина.

Например:

          <LENGTH >                =>   0
          <LENGTH A B C>           =>   3
          <LENGTH (A B) C (D E)>   =>   3

LEFT отбрасывает от e.Exp первые s.Left термов, а затем от того что останется берет первые s.Len термов и выдает полученное выражение в качестве результата.

RIGHT отбрасывает от e.Exp последние s.Right термов, а затем от того что останется берет последние s.Len термов и выдает полученное выражение в качестве результата.

MIDDLE отбрасывает от e.Exp первые s.Left и последние s.Right термов, и выдает полученное выражение в качестве результата.

L отбрасывает от e.Exp первые s.Left термов, и выдает первый терм полученного выражения в качестве результата.

R отбрасывает от e.Exp последние s.Right термов, и выдает последний терм полученного выражения в качестве результата.

Если e.Exp имеет недостаточно большую длину, чтобы можно было выполнить требуемую операцию, результатом работы любой из вышеперечисленных функций является $fail(0).

Например:

          <MIDDLE 2 3    A B C D E F>   =>   C 
          <MIDDLE 2 3    A B C D>       =>   $fail(0)
          <MIDDLE 0 0    A B C>         =>   A B C 
          <LEFT   2 3    A B C D E F>   =>   C D E 
          <LEFT   2 3    A B C D>       =>   $fail(0)
          <LEFT   0 0    A B C>         =>    
          <RIGHT  2 3    A B C D E F>   =>   B C D 
          <RIGHT  2 3    A B C D>       =>   $fail(0)
          <RIGHT  0 0    A B C>         =>   
          <L      2      A B C D E F>   =>   C
          <L      2      A B>           =>   $fail(0)
          <R      2      A B C D E F>   =>   D
          <R      2      A B>           =>   $fail(0)
Операции MIDDLE, LEFT и RIGHT можно изобразить в виде следующей схемы:

      s.Left          s.Right
     +-------+-------+-------+
     |       |XXXXXXX|       |    <MIDDLE s.Left s.Right e.Exp>
     +-------+-------+-------+

      s.Left  s.Len
     +-------+-------+-------+
     |       |XXXXXXX|       |    <LEFT   s.Left s.Len e.Exp>
     +-------+-------+-------+

              s.Len   s.Right
     +-------+-------+-------+
     |       |XXXXXXX|       |    <RIGHT  s.Right s.Len e.Exp>
     +-------+-------+-------+

3. APPLY: вызов функций переданных через параметры

$func? APPLY s.Name e.Exp = e.Exp;

APPLY применяет функцию, на которую указывает ссылка s.Name к выражению e.Exp и выдает результат этого вычисления.

4. ARITHM: целочисленная арифметика

$func "+"     s.Int1 s.Int2 = s.Int;
$func "-"     s.Int1 s.Int2 = s.Int;
$func "*"     s.Int1 s.Int2 = s.Int;
$func DIV-REM s.Int1 s.Int2 = s.Quo s.Rem;
$func DIV     s.Int1 s.Int2 = s.Quo;
$func REM     s.Int1 s.Int2 = s.Rem;
$func GCD     s.Int1 s.Int2 = s.Gcd;

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

Если хотя бы один из аргументов функций арифметики не является символом-числом, результатом является ошибка $error(Fname "Invalid argument"), где Fname - имя функции.

Если оба аргумента - числа, эти функции выдают следующие результаты.

"+" выдает сумму двух аргументов, "-" - разность первого и второго аргументов, "*" - произведение двух аргументов, DIV - результат деления нацело первого аргумента на второй, REM - остаток от деления нацело первого аргумента на второй, DIV-REM - результат деления нацело и остаток от деления нацело первого аргумента на второй, GCD - наибольший общий делитель двух аргументов.

Если результат одной из функций "+", "-" или "*" больше, чем допускается реализацией, результатом является ошибка $error(Fname "Size limit exceeded"), где Fname - имя функции.

Например:

          <"+" 3 5>      =>   8
          <"+" 3 -5>     =>   -2
          <"-" 3 -5>     =>   8
          <"*" -2 3>     =>   -6
          <DIV 5 2>      =>   2
          <REM 5 2>      =>   1
          <DIV-REM 5 2>  =>   2 1
          <DIV 6 2>      =>   3
          <REM 6 2>      =>   0
          <DIV-REM 6 2>  =>   3 0
Знаки частного и остатка определяются следующим образом. Если знаки делимого и делителя совпадают - частное положительно, если различны - отрицательно. Знак остатка совпадает со знаком делимого. Таким образом, всегда выполняется соотношение

     делимое = (частное * делитель) + остаток

Например:

          <DIV 5 3>      =>   1 
          <REM 5 3>      =>   2 
          <DIV 5 -3>     =>   -1 
          <REM 5 -3>     =>   2 
          <DIV -5 3>     =>   -1 
          <REM -5 3>     =>   -2 
          <DIV -5 -3>    =>   1 
          <REM -5 -3>    =>   -2 
Попытка делить на ноль приводит к выдаче ошибки $error(Fname "Divide by zero"), где Fname - имя функции. Например:

          <DIV 5 0>      =>   $error(DIV "Divide by zero")
          <REM 5 0>      =>   $error(REM "Divide by zero")
          <DIV-REM 5 0>  =>   $error(DIV-REM "Divide by zero")
Функция GCD, если ее оба аргумента не равны нулю одновременно, выдает положительное целое число, которое является наибольшим общим делителем аргументов. Если же оба аргумента равны нулю, результатом является ошибка $error(GCD "Zero arguments"). Например:

          <GCD 6 15>     =>   3 
          <GCD -6 15>    =>   3 
          <GCD 15 1>     =>   1 
          <GCD 15 0>     =>   15 
          <GCD 0 0>      =>   $error(GCD "Zero arguments")

5. BOX: работа с ящиками

$func BOX     e.Exp = s.Box;
$func ?       s.Box = e.Exp;
$func STORE   s.Box e.Exp = ;

BOX создает новый ящик, помещает в него выражение e.Exp и выдает ссылку на этот ящик.

"?" выдает содержимое ящика, на который ссылается s.Box.

STORE заносит в ящик, на который ссылается s.Box, новое содержимое e.Box.

6. CLASS: предикаты для распознавания классов символов

$func? BOX?     e.Exp = ;
$func? CHANNEL? e.Exp = ;
$func? CHAR?    e.Exp = ;
$func? DIGIT?   e.Exp = ;
$func? FUNC?    e.Exp = ;
$func? INT?     e.Exp = ;
$func? LETTER?  e.Exp = ;
$func? STRING?  e.Exp = ;
$func? TABLE?   e.Exp = ;
$func? VECTOR?  e.Exp = ;
$func? WORD?    e.Exp = ;

Эти функции служат для проверки, что e.Exp является символом, принадлежащим к определенному множеству символов.

Если e.Exp - не символ, результатом является $fail(0).

Если e.Exp - символ, выполняется проверка, что этот символ принадлежащит к соответствующему множеству. Если принадлежит - результатом является пустое выражение, если же не принадлежит - результатом является $fail(0).

Соответствие между функциями-предикатами и множествами символов следующее:

BOX? - ссылки на ящики.
CHANNEL? - ссылки на каналы.
CHAR? - символы-литеры.
DIGIT? - символы-литеры, которые соответствуют десятичным цифрам.
FUNC? - ссылки на функции.
INT? - целые числа.
LETTER? - символы-литеры, которые соответствуют латинским прописным и строчным буквам.
STRING? - ссылки на строки.
TABLE? - ссылки на таблицы.
VECTOR? - ссылки на векторы.
WORD? - слова.

7. COMPARE: сравнение выражений

$func? "="  (e.Exp1)(e.Exp2) = ;
$func? "/=" (e.Exp1)(e.Exp2) = ;
$func? ">=" (e.Exp1)(e.Exp2) = ;
$func? ">"  (e.Exp1)(e.Exp2) = ;
$func? "<=" (e.Exp1)(e.Exp2) = ;
$func? "<"  (e.Exp1)(e.Exp2) = ;

Эти функции сравнивают два выражения e.Exp1 и e.Exp2 и проверяют, выполнено ли соответствующее отношение между ними: "=" - равно, "/=" - не равно, ">=" - больше или равно, ">" - больше чем, "<=" - меньше или равно, "<" - меньше чем.

Если условие выполнено, результат работы - пусто, иначе - $fail(0).

$func COMPARE (e.Exp1)(e.Exp2)  = s.Res;   /* '<', '>', '=' */

COMPARE сравнивает два выражения e.Exp1 и e.Exp2. Результатом является '<', если e.Exp1 меньше чем e.Exp2, '>' если e.Exp1 больше чем e.Exp2, и '=', если e.Exp1 равно e.Exp2.

Объектные выражения сравниваются в соответствии со следующим отношением линейного порядка <.

Для любых двух выражений Oe' и Oe'' всегда либо Oe'<Oe'', либо Oe'=Oe'', либо Oe''<Oe'.

Два выражения Oe' = Ot1' ... Otm' и Oe'' = Ot1'' ... Otn'' сравниваются лексикографически, т.е. составляющие их термы сравниваются попарно слева направо, пока не будет найдена пара неравных термов Otk' и Otk''. Если при этом Otk' < Otk'', то считается, что Oe' < Oe''.

Если окажется, что Oe' короче, чем Oe'' и все термы из Oe' равны соответствующим термам из Oe'', то считается, что Oe' < Oe''.

Более формально: для любых объектных выражений Oe, Oe', Oe'' и любых объектных термов Ot, Ot', Ot'' имеет место

  • Если Oe' < Oe'', то Ot Oe' < Ot Oe''.
  • Если Ot' < Ot'', то Ot' Oe' < Ot'' Oe''.
  • [] < Ot Oe.
где через [] обозначено пустое объектное выражение.

Для объектных термов отношение порядка определяется следующим образом.

Все символы предшествуют термам вида (Oe), т.е. всегда

  • Os < (Oe)

Сравнение термов вида (Oe) сводится к сравнению их содержимого, т.е.

  • Если Oe' < Oe'', то (Oe') < (Oe'').

Каждый символ принадлежит одному и только одному из следующих множеств:

  • символы-литеры
  • символы-слова
  • символы-числа
  • ссылки на ящики
  • ссылки на векторы
  • ссылки на строки
  • ссылки на таблицы

Эти множества мы будем называть типами символов. Если два символа принадлежат одному и тому же типу, они называются однотипными, в противном случае - разнотипными. Мы считаем что на множестве типов определено отношение порядка, и что типы были перечислены выше в порядке возрастания, т.е. множество символов-литер предшествует множеству символов-слов и т.д.

Если два символа Os' и Os'' принадлежат двум различным типам Type' и Type'', и при этом Type' < Type'', то считается, что Os' < Os''.

Однотипные символы сравниваются следующим образом.

Символы-литеры упорядочены в соответствии с их кодами ASCII.

Символы-слова преобразуются в цепочки символов-литер, соответствующие изображениям слов, а эти цепочки сравниваются как описано выше.

Символы-числа сравниваются в соответствии с естественным порядком на множестве чисел.

Отношение порядка на множествах ссылок на ящики, векторы, строки и таблицы зависит от реализации.

8. CONVERT: преобразования между различными типами данных

$func  TO-LOWER  e.Char = e.Char;
$func  TO-UPPER  e.Char = e.Char;
$func  CHARS-TO-BYTES  e.Char = e.Int;
$func  BYTES-TO-CHARS  e.Int = e.Char;
$func  TO-CHARS  e.Exp  = e.Char;
$func  TO-WORD   e.Exp  = s.Word;
$func? TO-INT    e.Exp  = s.Int;

TO-LOWER преобразует цепочку символов-литер в цепочку литер, в которой все прописные латинские буквы заменены на соответствующие строчные буквы.

TO-UPPER преобразует цепочку символов-литер в цепочку литер, в которой все строчные латинские буквы заменены на соответствующие прописные буквы.

CHARS-TO-BYTES преобразует цепочку символов-литер в последовательность чисел, являющихся их кодами ASCII.

Если аргумент этих функций не является цепочкой символов-литер, результатом является $error(Fname "Invalid argument"), где Fname - имя функции.

Например:

          <TO-LOWER 'AbCd+'>       =>   'abcd+'
          <TO-LOWER 25>            =>   $error(TO-LOWER "Invalid argument")
          <TO-UPPER 'AbCd+'>       =>   'ABCD+'
          <TO-UPPER 25>            =>   $error(TO-UPPER "Invalid argument")
          <CHARS-TO-BYTES 'ABC'>   =>   65 66 67

BYTES-TO-CHARS преобразует цепочку целых чисел, каждое из которых лежит в диапазоне от 0 до 255, в цепочку символов-литер, имеющих соответствующие коды ASCII.

Например:

          <BYTES-TO-CHARS 65 66 67>     =>   'ABC'

Функции TO-CHARS, TO-WORD и TO-INT получают на входе произвольное объектное выражение и начинают свою работу с того, что преобразуют его в цепочку литер. Это преобразование выполняется следующим образом. Символы-литеры переходят сами в себя, круглые скобки заменяются на литеры '(' и ')', слова заменяются на цепочки литер, соответствующие их печатным именам, числа заменяются на их изображения в виде цепочек литер, ссылки на строки заменяются на содержимое строк, все прочие ссылки заменяются на некоторые цепочки литер, которые зависят от реализации.

Если размер цепочки литер, полученной в результате вышеописанного преобразования, больше, чем допускается реализацией, результатом работы функций является $error(Fname "Argument too large for conversion").

Дальнейшая работа функций TO-CHARS, TO-WORD и TO-INT происходит следующим образом.

TO-CHARS выдает полученную цепочку литер в качестве результата.

          <TO-CHARS "John">   =>   'John'
          <TO-CHARS 'John'>   =>   'John'
          <TO-CHARS 326>      =>   '326'
          <TO-CHARS -326>     =>   '-326'
          <TO-CHARS (-326) "John">   =>   '(-326)John'
TO-WORD преобразует полученную цепочку литер в слово с соответствующим печатным именем.

          <TO-WORD "John">    =>   "John"
          <TO-WORD 'John'>    =>   "John"
          <TO-WORD 326>       =>   "326"
          <TO-WORD -326>      =>   "-326"
          <TO-WORD (-326) "John">   =>   "(-326)John"
TO-INT преобразует полученную цепочку литер в целое число s.Int. Если эта цепочка литер не является правильным изображением целого числа, результатом является $fail(0).

Например:

          <TO-INT '326'>      =>   326
          <TO-INT '+326'>     =>   326
          <TO-INT "-3" '26'>  =>   -326
          <TO-INT -32 006>    =>   -326
          <TO-INT 'John'>     =>   $fail(0)

9. DOS: связь с операционной системой

$func ARG    s.Int = e.Arg;
$func GETENV e.VarName = e.Value;
$func TIME   = e.String;
$func EXIT   s.ReturnCode = ;

Эти функции служат для связи с операционной системой.

Аргументы функций должны удовлетворять следующим ограничениям. s.Int должно быть целым неотрицательным числом, e.VarName - цепочкой литер и слов, s.ReturnCode - целым числом из интервала от 0 до 255. Если хотя бы одно из этих условий не выполнено, функции выдают результат $error(Fname "Invalid argument"), где Fname - имя функции.

ARG выдает аргумент командной строки с номером s.Int. Если он отсутствует, выдается пустая строка.

GETENV извлекает из среды (в смысле MSDOS) значение переменной с именем e.VarName и выдает его.

TIME выдает текущую дату и время в виде объектного выражения вида

          DD MMM YYYY HH:MM:SS.SS

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

EXIT завершает выполнение программы, при этом устанавливается код завершения равный s.ReturnCode. Если программа завершается обычным способом, т.е. вычисление вызова главной функции

завершается, то код завершения зависит от результата, выданного функцией Main. Если этот результат - объектное выражение, то код завершения равен 0, если же результат имеет вид $error(Oe), код завершения равен 100.

10. STDIO: стандартный ввод-вывод

$channel STDIN STDOUT STDERR;

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

$func CHANNEL = s.Channel;

CHANNEL создает новый канал s.Channel.

$func? OPEN-FILE      s.Channel e.FileName s.Mode = ;
$func  CLOSE-CHANNEL  s.Channel = ;

OPEN-FILE открывает канал s.Channel и связывает его с файлом с именем e.FileName. s.Mode - это литера, которая указывает режим, в котором будет происходить работа с файлом: "r" или "R" - чтение, "w" или "W" - запись, "a" или "A" добавление в конец файла. Если файл открыть не удается, результатом работы OPEN-FILE является неуспех $fail(0).

CLOSE-CHANNEL закрывает канал s.Channel.

$func? EOF?        s.Channel = ;

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

$func? READ       = t.Term;
$func? READ-CHAR  = s.Char;
$func? READ-LINE  = e.Char;
$func  WRITE      e.Exp = ;
$func  WRITELN    e.Exp = ;
$func  PRINT      e.Exp = ;
$func  PRINTLN    e.Exp = ;

READ читает из канала &STDIN очередное изображение терма. Если не осталось ни одного терма - выдает $fail(0).

READ-CHAR читает из канала &STDIN очередную литеру. Если не осталось ни одной литеры - выдает $fail(0).

READ-LINE читает из канала &STDIN все литеры до ближайшего конца строки (включительно) и выдает их в качестве результата (не включая литеру конец строки). Если не осталось ни одной литеры - выдает $fail(0).

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

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

PRINT преобразует выражение e.Exp в цепочку литер так же, как это делает функция TO-CHARS, и выводит его в канал &STDOUT.

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

$func? READ!       s.Channel = t.Term;
$func? READ-CHAR!  s.Channel = s.Char;
$func? READ-LINE!  s.Channel = e.Char;
$func  WRITE!      s.Channel e.Exp = ;
$func  WRITELN!    s.Channel e.Exp = ;
$func  PRINT!      s.Channel e.Exp = ;
$func  PRINTLN!    s.Channel e.Exp = ;

Эти функции отличаются от соответствующих функций без восклицательного знака тем, что операции выполняются над каналом s.Channel.

11. STRING: работа со строками

$func  STRING         e.Source = s.String;
$func  STRING-INIT    s.String s.Len s.Fill = ;
$func  STRING-FILL    s.String s.Fill = ;
$func  STRING-LENGTH  s.String = s.Len;
$func  STRING-REF     s.String s.Index = s.Char;
$func  STRING-SET     s.String s.Index s.Char = ;
$func  STRING-REPLACE s.String e.Source = ;
$func  SUBSTRING      s.String s.Index s.Len = s.NewString;
$func  SUBSTRING-FILL s.String s.Index s.Len s.Fill = ;

Эти функции используются для создания строк, изменения их содержимого и доступа к их содержимому. Их аргументы должны удовлетворять следующим требованиям. s.String должен быть ссылкой на строку. s.Index и s.Len должны быть неотрицательными целыми числами. s.Fill может быть произвольным символом-литерой. e.Source должен быть последовательностью ссылок на строки, символов-слов и символов-литер.

Если хотя бы одно из этих условий не выполнено, результатом функций является $error(Fname "Invalid argument"), где Fname - имя функции.

В каждый момент времени строка содержит конечную (может быть пустую) последовательность символов-литер, которую мы будем называть содержимым строки. Если строка содержит последовательность из N+1 символов-литер Oc0, Oc1, ..., OcN, мы будем говорить, что строка имеет длину N+1, а содержимое строки будем изображать в виде

          Oc0 Oc1 ... OcN

Таким образом, компоненты строки Oc0, Oc2, ..., OcN нумеруются начиная с нуля.

STRING создает новую строку и выдает ссылку на нее в качестве результата. При этом содержимое создаваемой строки формируется из e.Source следующим образом.

Пусть значение параметра e.Source имеет следующий вид: Os1 Os2 ... OsM, где каждый из символов Osj является либо символом-литерой, либо символом-словом, либо ссылкой на строку. Тогда каждый из Osj преобразуется следующим образом.

Если Osj является символом-литерой Oc, он остается без изменения.

Если Osj является символом-словом, он заменяется на цепочку литер, которая является печатным именем этого символа.

Если Osj является ссылкой на какую-то строку, он заменяется на содержимое этой строки (при этом состояние самой строки не изменяется).

Преобразованное таким образом значение параметра e.Source становится содержимым новой строки.

STRING-INIT изменяет содержимое строки, на которую указывает s.String. Старое содержимое уничтожается и вместо него создается новое содержимое длины s.Len, причем каждая компонента строки принимает значение s.Fill.

STRING-FILL изменяет содержимое строки, на которую указывает s.String. При этом длина строки не меняется, а каждая компонента строки принимает значение s.Fill.

STRING-LENGTH выдает длину строки, на которую указывает s.String.

STRING-REF извлекает из строки, на который указывает s.String, содержимое ее компоненты с номером s.Index, которое и выдается в качестве результата.

STRING-SET изменяет содержимое строки, на которую указывает s.String. При этом длина строки не меняется, а компонента строки с номером s.Index принимает значение s.Char.

STRING-REPLACE изменяет содержимое строки, на которую указывает s.String. Старое содержимое уничтожается, а новое содержимое формируется из значения параметра e.Source точно таким же способом, как и в случае функции STRING.

SUBSTRING создает новую строку и выдает ссылку на нее в качестве результата. При этом содержимое создаваемой строки формируется следующим образом. Рассматривается содержимое исходной строки, т.е. строки, на которую указывает s.String. Пусть оно имеет вид Oc0 Oc1 ... OcN. Тогда от него отбрасываются первые s.Index символов, а первые s.Len из оставшихся символов считаются содержимым новой строки.

В любом случае, в результате работы функции SUBSTRING состояние исходной строки не изменяется.

SUBSTRING-FILL изменяет содержимое строки, на которую указывает s.String. При этом длина строки не меняется, а s.Len последовательно расположенных компонент строки, начиная с компоненты с номером s.Index, принимают значение s.Char.

Если размер исходной строки недостаточен для выполнения одной из вышеуказанных операций, в качестве результата выдается $error(Fname "Index out of range"), где Fname - имя функции, а состояние строки не меняется.

Если при выполнении одной из вышеуказанных операций возникает необходимость создать содержимое строки, длина которого больше, чем допускается реализацией, в качестве результата выдается $error(Fname "Size limit exceeded"), где Fname - имя функции, а состояние строки не меняется.

12. TABLE: работа с таблицами

$func  TABLE         = s.Tab;
$func  BIND          s.Tab (e.Key) (e.Val) = ;
$func  UNBIND        s.Tab e.Key = ;
$func? LOOKUP        s.Tab e.Key = e.Val;
$func? IN-TABLE?     s.Tab e.Key = ;
$func  DOMAIN        s.Tab = e.Domain ;
$func  TABLE-COPY    s.Tab = s.TabCopy;
$func  REPLACE-TABLE s.TargetTable s.SourceTable = ;

TABLE создает новую пустую таблицу и выдает символ-ссылку на эту таблицу.

BIND связывает ключ e.Key со значением e.Val в таблице, на которую ссылается s.Tab.

UNBIND удаляет из таблицы, на которую ссылается s.Tab, ключ e.Key и связанное с ним значение, если такой ключ был в таблице.

LOOKUP находит в таблице, на которую ссылается s.Tab, значение, связанное с ключом e.Key и выдает его. Если такого ключа в таблице нет - результатом является $fail(0).

IN-TABLE? проверяет, что ключ e.Key находится в таблице, на которую ссылается s.Tab.

DOMAIN выдает список ключей, содержащихся в таблице, на которую ссылается s.Tab. А именно, если таблица содержит множество ключей {Oe1, Oe2, ..., Oen}, e.Domain имеет вид

          (Oe1)(Oe2) ... (Oen)
где порядок расположения ключей описанием языка не определен.

TABLE-COPY создает новую таблицу, копирует в него содержимое таблицы, на которую ссылается s.Tab, и выдает в качестве результата ссылку на новую таблицу.

REPLACE-TABLE уничтожает прежнее содержимое таблицы, на которую ссылается s.TargetTable, и заменяет его на копию содержимого таблицы, на которую ссылается s.Source

13. VECTOR: работа с векторами

$func  VECTOR         e.Source = s.Vector;
$func  VECTOR-TO-EXP  s.Vector = e.Exp;
$func  VECTOR-INIT    s.Vector s.Len e.Fill = ;
$func  VECTOR-FILL    s.Vector e.Fill = ;
$func  VECTOR-LENGTH  s.Vector = s.Len;
$func  VECTOR-REF     s.Vector s.Index = e.Exp;
$func  VECTOR-SET     s.Vector s.Index e.Exp = ;
$func  VECTOR-REPLACE s.Vector e.Source = ;
$func  SUBVECTOR      s.Vector s.Index s.Len = s.NewVector;
$func  SUBVECTOR-FILL s.Vector s.Index s.Len e.Fill = ;

Эти функции используются для создания векторов, изменения их содержимого и доступа к их содержимому. Их аргументы должны удовлетворять следующим требованиям. s.Vector должен быть ссылкой на вектор. s.Index и s.Len должны быть неотрицательными целыми числами. e.Fill может быть произвольным объектным выражением. e.Source должен быть последовательностью ссылок на векторы и термов вида (Oe).

Если хотя бы одно из этих условий не выполнено, результатом функций является $error(Fname "Invalid argument"), где Fname - имя функции.

В каждый момент времени вектор содержит конечную (может быть пустую) последовательность объектных выражений, которую мы будем называть содержимым вектора. Если вектор содержит последовательность из N+1 объектных выражений Oe0, Oe1, ..., OeN, мы будем говорить, что вектор имеет длину N+1, а содержимое вектора будем изображать в виде

          (Oe0)(Oe1) ... (OeN)

Таким образом, компоненты вектора Oe0, Oe2, ..., OeN нумеруются начиная с нуля.

VECTOR создает новый вектор и выдает ссылку на него в качестве результата. При этом содержимое создаваемого вектора формируется из e.Source следующим образом.

Пусть значение параметра e.Source имеет следующий вид: Ot1 Ot2 ... OtM, где каждый из объектных термов Otj либо имеет вид (Oe), либо является ссылкой на вектор. Тогда каждый из Otj преобразуется следующим образом.

Если Otj имеет вид (Oe), он остается без изменения.

Если Otj является ссылкой на какой-то вектор, он заменяется на содержимое этого вектора (при этом состояние самого вектора не изменяется).

Преобразованное таким образом значение параметра e.Source становится содержимым нового вектора.

VECTOR-TO-EXP выдает в виде объектного выражения содержимое вектора, на который указывает s.Vector.

VECTOR-INIT изменяет содержимое вектора, на который указывает s.Vector. Старое содержимое уничтожается и вместо него создается новое содержимое длины s.Len, причем каждая компонента вектора принимает значение e.Fill.

VECTOR-FILL изменяет содержимое вектора, на который указывает s.Vector. При этом длина вектора не меняется, а каждая компонента вектора принимает значение e.Fill.

VECTOR-LENGTH выдает длину вектора, на который указывает s.Vector.

VECTOR-REF извлекает из вектора, на который указывает s.Vector, содержимое его компоненты с номером s.Index, которое и выдается в качестве результата.

VECTOR-SET изменяет содержимое вектора, на который указывает s.Vector. При этом длина вектора не меняется, а компонента вектора с номером s.Index принимает значение e.Exp.

VECTOR-REPLACE изменяет содержимое вектора, на который указывает s.Vector. Старое содержимое уничтожается, а новое содержимое формируется из значения параметра e.Source точно таким же способом, как и в случае функции VECTOR.

SUBVECTOR создает новый вектор и выдает ссылку на него в качестве результата. При этом содержимое создаваемого вектора формируется следующим образом. Рассматривается содержимое исходного вектора, т.е. вектора, на который указывает s.Vector. Пусть оно имеет вид (Oe0)(Oe1) ... (OeN). Тогда от него отбрасываются первые s.Index термов, а первые s.Len из оставшихся термов считаются содержимым нового вектора.

Состояние исходного вектора при этом не меняется.

SUBVECTOR-FILL изменяет содержимое вектора, на который указывает s.Vector. При этом длина вектора не меняется, а s.Len последовательно расположенных компонент вектора, начиная с компоненты с номером s.Index, принимают значение e.Exp.

Если размер исходного вектора недостаточен для выполнения одной из вышеуказанных операций, в качестве результата выдается $error(Fname "Index out of range"), где Fname - имя функции, а состояние вектора не меняется.

Если при выполнении одной из вышеуказанных операций возникает необходимость создать содержимое вектора, длина которого больше, чем допускается реализацией, в качестве результата выдается $error(Fname "Size limit exceeded"), где Fname - имя функции, а состояние вектора не меняется.

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r4 < r3 < r2 < r1 | More topic actions
 
R+

This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback