Язык программирования Т2СР


Содержание


Введение

Язык программирования T2CP предназначен для написания программ, реализованных с использованием Т-системы-Т-программ, и является входным языком программирования для Т-системы. Данный язык программирования построен как расширение языка Си базовыми языковыми конструкциями, ориентированными на использование парадигм концепции автоматического динамического распараллеливания программ (данная концепция реализуется ядром Т-системы-Т-ядром).

Текущая реализация языка T2CP выполнена с использованием средств контекстного препроцессирования, что определило следующие черты реализации:

Помимо собственно контекстного препроцессирования в компиляторе языка t2cp имеется поддержка языковых понятий, которые более свойственны языкам программирования, чем препроцессорам-ограничение зоны действия имен переменных телом функции, в корой они определены, разграничение имен по классам-имена функций, входов, выходов,-и, как следствие, достаточно серьезная работа с таблицами имен. Все это обосновывает уместность использования обоих терминов: "компилятор T2CPСи" и "препроцессор T2CPСи".

Синтаксис языка T2CP

Средства описания синтаксиса

При описании синтаксиса языка программирования T2CP в данном тексте будут использоваться следующие обозначения-метасимволы:
метасимволзначение и/или описание
"::"разделяет в синтаксическом определении левую часть определения-определяемое понятие или конструкцию-и правую часть-тело определения
"|"разделяет в теле определения различные варианты выбора-альтернативы. Каждая альтернатива обычно располагается на отдельной строке, и поэтому данный метасимвол обычно является первым в строке альтернативы
" "любое количество (0,1,...) пробелов или табуляций
"^"начало строки
<id>синтаксическое понятие (в данном случае идентификатор-буква и следующее за ней любое количество букв, цифр и знаков "_" (подчерков)
<xx,...>ноль, один, или несколько "<xx>", разделенных последовательностью
" , ":

<пусто> | <xx> | <xx> , <xx> | и так далее

<xx ...>ноль, один, или несколько "<xx>", разделенных ненулевым (положительным) количеством пробелов и/или табуляций:

<пусто> | <xx> | <xx> <xx> | и так далее

<int>выражение языка программирования Си, имеющее целый тип (см. ниже ограничения реализации)
<C-type> корректный-в соответствие с правилами языка программирования Си-спецификатор типа (см. ниже ограничения реализации)

Ограничения реализации 1. Как строка символов, фрагмент <int> должен удовлетворять следующим требованиям:

Таким образом, в качестве <int> не допускаются следующие выражения целого типа:
x`int+6
(int)('(')
(int)(']')+5
(int)('`')

Ограничения реализации 2. Как строка символов, фрагмент <C-type> должен удовлетворять тем же требованиям, что и <int> (см. Ограничения реализации 1).

Основные положения и понятия

Язык T2CP построен как расширение языка программирования Си средствами работы с Т-процессами и звеньями. Единицей компиляции программ, написанных на языке T2CP является, как и в случае языка Си, файл с текстом программы-текст программного модуля. На верхнем структурном уровне текст программного модуля состоит из описаний и определений типов, структур данных и функций на языке программирования Си, а также определений Т-функций.

Текст определения Т-функции является тем фрагментом текста программного модуля, внутри которого разрешается описывать звеньевые переменные и использовать различные операции со звеньями.

Звеньевым значением может являться либо значение аргумента или рабочей переменной Т-функции, либо значение звеньевого выражения, вычисляемое с использованием значения аргумента или рабочей переменной Т-функции. Для спецификации звеньевых значений используется следующий синтаксис:
<cell>:: <id>
| <cell>`head
| <cell>`tail
| <cell>`list [ <int> ]
| ( <cell> )

Краткое описание структур данных

Звено

Звено является минимальной Т-структурой данных Т-системы. В звене может быть размещено скалярное Си-значение (например типа int, float, double, char и т.д.) или специальный указатель на другую Т-структуру (держатель Т-структуры).

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

Рисунок 1. Примеры звеньев со скалярными значениями

Звено-держатель содержит указатель на начало удерживаемой Т-структуры (несколько расположенных подряд звеньев), длину (в звеньях) удерживаемой Т-структуры и признак (тэг) звена-держателя.

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

У каждого потребителя обязательно имеется ровно один поставщик, а у поставщика может быть произвольное количество потребителей (в том числе и ни одного).

Ниже перечислены конструкции языка T2CP специализированные для работы с одиночными звеньями:

   <cell>`mkInt ( <int> )
   <cell>`int
   <cell>`drop
   <cell>`wait

Т-список

Т-списком является звено-держатель, удерживающей несколько (или не одного) подряд расположенных звеньев (см. Рисунок 2). Конструкции языка T2CP, предназначенные для работы с Т-списками:

    <cell>`newList ( <int> )
    <cell>`list [ <int> ]
    <cell>`length
    <cell>`altlist

Рисунок 2. Т-список

Поток (лисп-список)

Потоком (или лисп-списком) будем называть звено, которое:

Конструкции языка T2CP, предназначенные для работы с потоками:

    <cell>`head
    <cell>`tail
    <cell>`mkNil
    <cell>`isNil
    <cell>`mkCons ( <cell> , <cell> )
    <cell>`altseq

Рисунок 3. Лисп-список

Мультизвено

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

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

Мультизвено состоит из L+1 расположенных подряд звена. Первое звено содержит признак (тэг) мультизвена и является заголовком бестэговой области. Непосредственно за данным звеном расположена непрерывная область памяти для хранения произвольных данных (например, для хранения массива целых чисел, строки символов и т.п. см. Рисунок 4).

Рисунок 4. Пример мультизвена

Размер данной непрерывной области памяти-бестэговой области-кратен размеру обычного звена. Размер бестэговой области в звеньях (частное L от деления размера бестэговой области в байтах на размер звена в байтах) называется длиной бестэговой области и размещается в заголовке бестэговой области (см. Рисунок 4).

Держатель мультизвена (рюкзак, держатель области упакованных данных).

Держателем мультизвена (рюкзаком) называется одиночное звено-держатель удерживающее мультизвено (см. Рисунок 5). Конструкции языка T2CP, специализированные для работы с держателями мультизвеньев:

    <cell>`newPackedHolder ( <int> )
    <cell>`packed_ptr ( <C-type> )

Рисунок 5. Пример держателя мультизвена

Деревья данных

Определение дерева данных:

Рисунок 6. Пример дерева

Конструкции языка T2CP специализированные для работы с деревьями:

    <cell>`mark_as_branch
    <cell>`is_branch

Режимы AUTOWAIT и DATACHECK

В текущей реализации контекстного препроцессора t2cp поддержаны два специальных режима препроцессирования, а именно:

Режим AUTOWAIT

Зона действия режима AUTOWAIT в тексте Т-программы устанавливается при помощи конструкций "#define AUTOWAIT 1" и "#define AUTOWAIT 0":

    #define AUTOWAIT 1 /* Начало зоны действия режима AUTOWAIT */
                       /* Зона     */
                       /* действия */
                       /* AUTOWAIT */
    #define AUTOWAIT 0 /* Конец зоны действия режима AUTOWAIT */

Некоторые конструкции языка T2CP (такие, как <cell>`int, <cell>`length, <cell>`head, <cell>`tail, <cell>`list[<int>] и др.) могут быть выполнены только над готовыми звеньями-назовем их конструкциями обработки готовых значений.

Если данные конструкция языка T2CP находятся вне зоны действия режима AUTOWAIT, то программист должен сам гарантировать, что звено над которым производится операция в момент исполнения операции готово (имеет признак готовности). Для этого, при необходимости, можно, например, использовать конструкцию <cell>`wait.

Если конструкциями обработки готовых значений языка T2CP находятся в зоне действия режима AUTOWAIT, то в начале исполнения данных конструкций будет произведена проверка звена <cell> на готовность и в случае неготовности значения будет автоматически выполнено ожидание готовности (аналогично конструкции <cell>`wait), а затем уже будет произведена необходимая операция над готовым звеном. Таким образом широкое (на весь текст программы) использование режима AUTOWAIT полностью избавляет программиста от необходимости реализовывать проверки на готовность и ожидания готовности при работе со звеньями.

Режим DATACHECK

Зона действия режима DATACHECK в тексте Т-программы устанавливается при помощи конструкций "#define DATACHECK 1" и "#define DATACHECK 0":

    #define DATACHECK 1 /* Начало зоны действия режима DATACHECK */
                        /* Зона      */
                        /* действия  */
                        /* DATACHECK */
    #define DATACHECK 0 /* Конец зоны действия режима DATACHECK  */

Часть конструкций языка T2CP предусматривают поддержку режима DATACHECK (см. Таблица 1). При использовании таких конструкций в зоне действия режима DATACHECK перед началом исполнения конструкции производится некоторая проверка условий, позволяющих гарантировать, что данная конструкция применяется корректно. Состав выполняемой проверки для разных конструкций различен. В случае, если проверка не будет пройдена успешно, выдается детальное сообщение об ошибке и производится аварийное завершение всех Т-процессов текущей Т-задачи (на всех соисполнителях).

Препроцессируемые строки

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

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

Заголовок Т-функции

Заголовок определения Т-функции имеет следующий синтаксис:

^ `func <fid> ( <id,..> ) -> ( <id,...> ) <option ...> ;<comment>
<vars-строка>
.....
<vars-строка>

Здесь:

Фрагмент <option> имеет следующий синтаксис:
<option>:: stack ( <int> )
| stream
| lazy


За "`func"-строкой может идти несколько (или ни одной) "`vars"-строк с описаниями имен рабочих звеньев (переменных). Описанные таким образом звеньевые переменные могут быть использованы в теле Т-функции. Синтаксис "`vars"-строк:

^ `vars <id,..> ;<comment>

Пример заголовка описания Т-функции:

`func nats(n,npMax) -> (nps) stack (512) lazy stream;
`vars pp; /* локальный L-пакет простых */
`vars np; /* первый элемент (L-пакет) из потока nps */
`vars p;  /* очередное простое */
`vars pp1, np1, p1;

Заголовок определения Т-функции должен удовлетворять следующим требованиям:

Опции <option ...> задают определенные особенности Т-функции:

  1. stack ( <int> )-устанавливает нестандартный размер стека необходимый для вызова из данной Т-функции других (Т- или С-) функий. По умолчанию размер стека равен 16 Кб.
  2. stream-"возможны потоковые результаты"-определяет возможность использования в функции конструкции streamsend;
  3. lazy-"ленивая функция" (см. разделы 2.5.4 и 2.6.21 стр. 25).

Конец описания Т-функции

Конструкция конца описания Т-функции имеет следующий синтаксис:

^ `end_func <comment>

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

Конструкции scope, end_scope

Синтаксис:
<scope>:: ^ `scope <fname> ;<comment>
<end_scope>:: ^ `end_scope ;<comment>

Здесь <fname>-идентификатор Т-функции, определенной в Т-программе (см. раздел 2.5.1):

<fname> :: <id>

Описание. Конструкции scope и end_scope используются для обозначения в Си-коде зоны действия Т-переменных и выходов функции <fname>:

Иллюстрация использования:

`scope f1;    /* Начало зоны "область действия"         */
............. /* Область Си-кода, которая               */
............. /* включается в зону действия             */
............. /* Т-переменных и выходов Т-функции f1.   */
              /* Здесь в Cи-коде можно использовать     */
              /* любые T2CP-конструкции с Т-переменными */
              /* и выходами Т-функции f1                */
 
<определения Си-функций>
 
`end_scope;   /* Завершение зоны "область действия"     */

Конструкция scope дает программисту возможность использования в тексте Си-функции T2CP-конструкций с Т-переменными и выходами Т-функции <fname>. Программист в свою очередь должен сам гарантировать, что данный участок Си-кода будет исполнятся только на фоне Т-процесса <fname>.

Например, если в scope-фрагменте Т-функции f1 описана некоторая Си-функция g работающая с Т-переменными и/или выходами Т-функции f1, то эта Си-функция g должна вызываться только из Т-функции f1.

Конструкция abort

Синтаксис

^ `abort;<comment>

Назначение. Данная конструкция приводит к завершению всех Т-процессов данной Т-задачи во всех соисполнителях.

  1. Конструкция assign

Синтаксис

^ ` <cell_1> = <cell_2> ;<comment>

Назначение. Данная конструкция выполняет копирование значения из звена <cell_2> в звено <cell_1> (См. Рисунок 7).

Выполнение конструкции:

Рисунок 7. Различные примеры выполнения операции assign

Конструкция send

Синтаксис

^ ` <id> <== <cell> ;<comment>

Назначение. Данная конструкция передает значение звена <cell> всем потребителям выхода <id> текущего процесса.

В результате выполнения конструкции send может быть передано как готовое, так и неготовое значение, находящееся в звене <cell>. При рассылке неготового значения, потребители поставщика <id> становятся потребителями того же поставщика, что и у звена <cell>.

В любом случае, в результате выполнения данной конструкции все потребители поставщика <id> получают то значение, которое имеет звено <cell> (см. Рисунок 8).

Рисунок 8. Пример конструкции send

Вызов Т-функции

Конструкция вызова Т-функции имеет следующий синтаксис:

^ ` [ <cell,...> ] = <fname> ( <cell,...> ) ;<comment>

Должны выполняться следующие условия:

Выполнение вызова Т-функции включает следующие действия:

  1. Организация нового Т-процесса, с необходимым (в соответствии с описанием функции <fname>) числом аргументов, результатов, рабочих переменных и рабочих выходов.
  2. Копирование значений) звеньев-аргументов, перечисленных в списке ( <cell,...> ), в соответствующие аргументы нового процесса.
  3. Присваивание всем звеньям из списка [ <cell,...> ] соответствующих неготовых значений-эти звенья становятся потребителями соответствующих выходов функции <fname>.
  4. Инициализация нулевыми звеньями всех рабочих переменных нового процесса. Инициализация пустым множеством потребителей всех рабочих выходов нового процесса.
  5. Установка новому процессу признака готовности:
    1. "готов к исполнению"-если функция <fname> не имеет описателя "lazy";
    2. "не готов к исполнению"-если функция <fname> имеет описатель "lazy".

Поддержка функций с признаком "lazy". В Т-системе имеется поддержка ленивых (lazy) функций. В отличии от случая обычных функций, Т-процессы вычисления функций с признаком lazy:

Препроцессируемые фрагменты

Ниже (Таблица 1) приведено описание синтаксиса препроцессируемых фрагментов языка T2CP, описан тип возвращаемого фрагментом значения, способ его реализации и признак (+) поддержки в данном фрагменте режимов AUTOWAIT и DATACHECK.

Таблица 1. Препроцессируемые фрагменты языка T2CP
Синтаксис
результат
способ реализации
autowait
datacheck
<fragment> ::
    <cell>`head
cell
macro
+
+
  | <cell>`tail
cell
macro
+
+
  | <cell>`isNil
int
macro
+
+
  | <cell>`mkNil
void
inline
  | <cell>`mkCons ( <cell> , <cell> )
void
macro
  | <cell>`mkInt ( <int> )
int
inline
  | <cell>`int
int
macro, Lvalue
+
+
  | <cell>`list [ <int> ]
cell
macro
+
+
  | <cell>`newList ( <int> )
void
macro
  | <cell>`length
int
macro, Lvalue
+
+
  | <cell>`newPackedHolder ( <int> )
void
macro
  | <cell>`packed_ptr ( <c-type> )
(c-type)*
macro
+
+
  | <cell>`mark_as_branch
void
+
+
  | <cell>`is_branch
int
+
+
  | <cell>`wait
int
macro
  | <cell>`ready
int
  | <cell>`altseq
int
  | <cell>`altlist
int
  | <cell>`alt ( <cell,...> )
int
  | <cell>`drop
void
inline
  | <cell>`streamsend ( <out> )
void

Конструкция head.

Синтаксис

<cell>`head

Назначение. Данная конструкция применима только для работы с лисп-списками. Конструкция используется для доступа к первому элементу лисп-списка, удерживаемого звеном <cell>.

Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что <cell> содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.

Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции происходит проверка является ли <cell> правильным готовым лисп-списком, отличным от NIL. А именно, проверяется, что:

Результатом конструкции является звено, являющиеся первым элементом лисп-списка, удерживаемого звеном <cell> (см. Рисунок 9).

Конструкция tail

Синтаксис

<cell>`tail

Назначение Данная конструкция применима только для работы с лисп-списками и используется для доступа ко второму элементу лисп-списка, удерживаемого звеном <cell>, которое является держателем лисп-списка.

Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что <cell> содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.

Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции происходит проверка является ли <cell> правильным готовым лисп-списком, отличным от NIL. А именно, проверяется, что:

  1. звено <cell> готово;
  2. звено <cell> является держателем Т-списка;
  3. длина удерживаемой звеном <cell> Т-списка равна 2.

Результатом конструкции является звено, являющиеся вторым элементом лисп-списка, удерживаемого звеном <cell> (см. Рисунок 9).

Рисунок 9. Пример конструкций head и tail

Конструкция mkNil

Синтаксис

<cell>`mkNil

Назначение. Данная конструкция предназначена для создания в звене <cell> значения NIL ("пустой лисп-список").

Выполнение конструкции <cell>`mkNil:

  1. Производятся действия по очистке звена <cell> (См. Конструкция drop, 2.6.20)
  2. Звено <cell> преобразуется в звено-держатель с нулевой длиной удерживаемой конструкции и нулевым указателем.

Конструкция isNil

Синтаксис

<cell>`isNil

Назначение. Данная конструкция предназначена для проверки является ли данное звено <cell> пустым лисп-списком.

Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что <cell> содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.

Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции проверяются следующие условия:

  1. звено <cell>-готово;
  2. звено <cell>-звено-держатель;
  3. <cell> является лисп-списком:
    1. непустым лисп-списком-длина удерживаемой Т-конструкции равна 2,-или
    2. пустым лисп-списком-длина удерживаемой Т-конструкции равна 0 и указатель удерживаемой Т-конструкции-нулевой.

Результат конструкции. Конструкция возвращает (int) 1 (TRUE) в случае если <cell>-пустой лисп-список, (int) 0 (FALSE) если это не так.

Конструкция mkCons

Синтаксис:

<cell>`mkCons( <cell_car>, <cell_cdr>)

Назначение. Конструкция предназначена для построения лисп-списка <cell> с использованием звеньевого значения, содержащегося в звене <cell_car>, и лисп-списка, удерживаемого звеном <cell_cdr>. Данная конструкция рекомендуется для работы с лисп-списками.

Выполнение конструкции:

  1. захватываются два (расположенных рядом) звена;
  2. в первое из захваченных на предыдущем шаге звеньев копируется значение, содержащиеся в звене <cell_car>;
  3. во второе звено копируется значение звена-держателя <cell_cdr>;
  4. в звене <cell> формируется держатель пары звеньев, захваченных на первом шаге (естественно, прежнее значение звена <cell>-теряется).

Таким образом, в результате выполнения операции mkCons значением звена <cell> становится новый лисп-список, содержащий звено <cell_car> в качестве "головы" и лисп-список <cell_cdr> в качестве "хвоста".

Замечание. При выполнении данной конструкции не требуется, что бы звено <cell_car> (или звено <cell_cdr>) содержало готовое значение.

Рисунок 10. Пример использования операции mkCons

Конструкция list

Синтаксис:

<cell>`list [ <int> ]

Назначение. Данная конструкция используется для доступа к элементу Т-списка <cell> с порядковым номером <int> (звенья в Т-списках нумеруются начиная с 0).

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Результатом выполнения данной операции является звено, входящее в удерживаемый звеном <cell> Т-список. Порядковый номер звена-результата в данном Т-списке равен <int> (звенья в Т-списках нумеруются начиная с 0).

Конструкция newList

Синтаксис:

<cell>`newList( <int> )

Назначение. Данная конструкция предназначена для создания нового Т-списка длиной <int> (размер указывается в звеньях).

Выполнение конструкции:

  1. Выполняется захват расположенных подряд <int> звеньев свободной памяти. Захваченные звенья обнуляются.
  2. В звено <cell> помещается держатель, удерживающий захваченные на предыдущем шаге звенья. Прежнее значение звена <cell> теряется.

Конструкция length

Синтаксис

<cell>`length

Назначение. Данная конструкция предназначена для извлечения длины (в звеньях) Т-структуры удерживаемой звеном-держателем <cell>.

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Результатом выполнения данной операции является целое число-длина (в звеньях) Т-структуры, удерживаемой держателем <cell>.

Замечание. Конструкция <cell>`length реализована как Lvalue языка Си. Последнее означает, что если заведомо известно, что собственное для процесса звено <cell> хранит готовый держатель) Т-списка, то можно применить операторы присваивания ("=", "-=", "--" и др.) к конструкции <cell>`length для коррекции длины удерживаемого Т-списка.

Данной возможностью следует пользоваться очень осторожно. Как правило она применяется для "укорачивания захваченного с запасом" Т-списка. Например:

`func fs() -> (y) ; // y--Т-список чисел Фибоначчи меньших 100
`vars f;
   int f1, f2, f3, i;
   // Чисел Фибоначчи меньших 100 -- заведомо МЕНЬШЕ 100:
   f`newList(100);
   for(f1=1, f2=1, i=0;   f1<100;  f3=f1+f2, f1=f2, f2=f3, i++) {
      (f`list[i])`mkInt(f);
   }
   // Мы захватили под Т-список 100 звеньев.
   // Реально заполнили в нем i<100 звеньев. Укорачиваем...
   f`length = i;
  `y <== f;
`end_func

Конструкция int

Синтаксис

<cell>`int

Назначение. Данная конструкция предназначена для доступа к целому значению, хранящемуся в звене <cell>.

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Результатом выполнения данной операции является целое число-значение байтов 0-3 звена <cell> (см. Рисунок 1, стр. 6).

Замечание. Конструкция <cell>`int реализована как Lvalue языка Си. Последнее означает, что если заведомо известно, что собственное для процесса звено <cell> хранит готовое целое значение) (имеет соответствующий тэг), то можно использовать операторы присваивания ("=", "+=", "++" и др.) к конструкции <cell>`int. Пример:

`func f10(x) -> (y) ;  // y = f(9,...f(2, f(1, f(0,x))...)
`vars i;
  for( i`mkInt(0); i`int<10; i`int++) {
   `[x] = f(i, x);
  }
 `y <== x;
`end_func

Конструкция mkInt

Синтаксис

<cell>`mkInt ( <int> )

Назначение операции. Сохранение целого Си-значения <int> в качестве значения звена <cell>.

Выполнение конструкции. В звено <cell> помещается целое Си-значение <int> и соответствующий тэг. Естественно, прежнее значение звена <cell> теряется.

Результат конструкции: конструкция возвращает целое Си-значение-<int>.

Конструкция newPackedHolder

Синтаксис

<cell>`newPackedHolder ( <int> )

Назначение. Данная конструкция предназначена для построения мультизвена, содержащего бестэговую область размера <int> байт и помещения в <cell> держателя данного мультизвена (держателя упакованных данных).

Выполнение конструкции:

  1. Происходит захват участка звеньевой памяти размером достаточным для оформления мультизвена с бестэговой областью размера <int> байт, предназначенной для хранения упакованных данных. Захваченная бестэговая область обнуляется.
  2. В звено <cell> помещается держатель (с корректным тэгом и звеном), удерживающий построенное мультизвено. Естественно, прежнее значение звена <cell> теряется.

Конструкция packed_ptr

Синтаксис

<cell>`packed_ptr ( <C-type> )

Назначение. Данная конструкция предназначена для доступа к структуре данных, имеющую корректный в смысле языка программирование Си тип <C-type>, упакованной в бестэговую область мультизвена, удерживаемого звеном-держателем <cell>.

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Результатом выполнения данной операции является Си-указатель (<C-type>*) на структуру данных типа <C-type>, размещенных в мультизвене, удерживаемом звеном-держателем <cell>.

Конструкция mark_as_branch

Синтаксис

<cell>`mark_as_branch

Назначение. Данная конструкция позволяет преобразовать звено-держатель Т-списка в звено-развилку дерева данных-см. раздел 2.3.6 стр. 9 и Рисунок 6. А именно: конструкция предназначена для пометки собственного готового держателя <cell> Т-списка специальным дополнительным признаком "развилка дерева данных".

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Выполнение: Звено <cell> помечается специальным дополнительным признаком (дополнительным тэгом) "развилка дерева данных".

Конструкция is_branch

Синтаксис

<cell>`is_branch

Назначение. Данная конструкция предназначена для проверки, является ли звено <cell> звеном-развилкой дерева данных (то есть, является ли оно звеном-держателем, имеющим особую отметку "развилка")-см. раздел 2.3.6 стр. 9 и Рисунок 6.

Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена <cell>, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.

Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:

Результатом выполнения данной операции является целое значение равное:

Конструкция wait

Синтаксис

<cell>`wait

Назначение. Данная конструкция предназначена для ожидания готовности звена <cell>.

Выполнение:

  1. происходит проверка звена <cell> на готовность;
  2. в случае, если звено <cell> содержит готовое значение, выполнение операции завершается;
  3. в случае неготовности звена <cell> (звено является звеном-потребителем-имеет признак неготового значения), происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению";
  4. в момент наступления события "ожидаемое звено готово" процесс "просыпается"-переходит в состояние "готов к выполнению".

Возвращаемое данной операцией значение имеет целый тип и всегда равно 1.

Конструкция ready

Синтаксис

<cell>`ready

Назначение. Данная конструкция предназначена для проверки готовности значения, содержащегося в звене <cell> (имеет ли данное звено признак готового значения).

Результатом выполнения данной операции является целое значение равное:

Конструкция altseq

Синтаксис

<cell>`altseq

Терминология, используемая в описании конструкции.

Элементами лисп-списка <cell> будем называть все первые звенья из каждой пары одиночных звеньев (cons-пары), образующих лисп-список <cell>. То есть, элементами непустого лисп-списка <cell> являются:

Ниже (см. Рисунок 11) на первом фрагменте рисунка изображен лисп-список x, в котором три элемента и все они имеют неготовое значение.

Суффиксами лисп-списка <cell> будем называть все вторые звенья из каждой пары одиночных звеньев (cons-пары), образующих лисп-список <cell>. То есть, суффиксами непустого лисп-списка <cell> являются:

Ниже (см. Рисунок 11) на первом фрагменте рисунка изображен лисп-список x, в котором три суффикса и все они имеют готовое значение.

Назначение. Конструкция <cell>`altseq предназначена для ожидания готовности хотя бы одного из элементов непустого лисп-списка <cell> (см. Рисунок 11).

Выполнение:

  1. Конструкция <cell>`altseq реализована в предположении, что выполнены следующие условие: <cell>-готовый держатель непустого лисп-списка все суффиксы которого являются готовыми звеньями. В начале выполнения конструкции проверяется это условие, и если оно не выполнено, вся текущая Т-задача завершается аварийно (см. описание конструкции abort, раздел 2.5.4 стр. 12).
  2. Происходит проверка на готовность всех элементов лисп-списка <cell>.
  3. В случае, если один из элементов лисп-списка <cell> готов, то выполнение операции завершается.
  4. В случае неготовности всех элементов лисп-списка <cell>, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".
  5. В момент наступления события "по крайней мере один элемент лисп-списка <cell> содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.

Таким образом, в любом случае в момент завершения операции по крайней мере один элемент лисп-списка <cell> содержит готовое значение.

Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру элемента лисп-списка <cell>, который на момент завершения операции содержал готовое значение. Элементы в лисп-списке нумеруются с 0.

Рисунок 11. Пример выполнения операции <cell>`altseq

Конструкция altlist

Синтаксис

<cell>`altlist

Назначение. Конструкция <cell>`altlist предназначена для ожидания готовности хотя бы одного из элементов (<cell>`list[0],... <cell>`list[L-1], где L=<cell>`length) непустого Т-списка <cell>.

Выполнение:

  1. Конструкция <cell>`altlist реализована в предположении, что выполнены следующие условие: <cell>-готовый держатель непустого Т-списка ((<cell>`ready) && (<cell>`length>0)). В начале выполнения конструкции проверяется это условие, и если оно не выполнено, вся текущая Т-задача завершается аварийно (см. описание конструкции abort, раздел 2.5.4 стр. 12).
  2. Происходит проверка на готовность всех элементов Т-списка <cell>.
  3. В случае, если один из элементов Т-списка <cell> готов, то выполнение операции завершается.
  4. В случае неготовности всех элементов Т-списка <cell>, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".
  5. В момент наступления события "по крайней мере один элемент Т-списка <cell> содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.

Таким образом, в любом случае в момент завершения операции по крайней мере один элемент Т-списка <cell> содержит готовое значение.

Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру i элемента Т-списка <cell>, который на момент завершения операции содержал готовое значение: <cell>`list[i]`ready. Элементы в Т-списке нумеруются с 0.

Конструкция alt

Синтаксис

<cell_1>`alt ( <cell,...> )

Назначение. Конструкция <cell>`alt предназначена для ожидания готовности хотя бы одного из элементов непустого перечисления звеньев:

(<cell_1>, <cell,...>).

Выполнение:

  1. Происходит проверка на готовность всех элементов из непустого перечисления звеньев (<cell_1>, <cell,...>).
  2. В случае, если один из элементов перечисления звеньев готов, то выполнение операции завершается.
  3. В случае неготовности всех элементов перечисления звеньев, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".
  4. В момент наступления события "по крайней мере один элемент перечисления звеньев (<cell_1>, <cell,...>) содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.

Таким образом, в любом случае в момент завершения операции по крайней мере один элемент перечисления звеньев (<cell_1>, <cell,...>) содержит готовое значение.

Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру i элемента перечисления звеньев (<cell_1>, <cell,...>), который на момент завершения операции содержал готовое значение. Элементы в перечисления звеньев нумеруются с 0.

Конструкция drop

Синтаксис

<cell>`drop

Назначение. Данная конструкция производит очистку (обнуление) звена <cell>. При этом, в случае если звено <cell> имеет неготовое значение, происходит корректное разрушение связи поставщик-потребитель между звеном <cell> и поставщиком данного звена.

Конструкция streamsend

Синтаксис

<cell>`streamsend ( <out> )

Рисунок 12. Пример конструкции streamsend

Назначение. Конструкция <cell>`streamsend(<out>) рассылает всем потребителям выхода <out> текущего процесса держатель структуры Cons (Т-список из двух звеньев) в котором:

Таким образом, в отличии от обычной конструкции send, данная конструкция сохраняет за текущим процессом обязанность вычисления значения выхода out.

Замечание 1. Конструкция <cell>`streamsend(<out>) допустима только в теле Т-функции-или в так называемой области (scope-зоне) действия переменных данной Т-функции,- в описании заголовка которой указана опция stream.

Реализация конструкции использует вспомогательные (и не доступные пользователю) выход и переменную функции.

Замечание2. Многократное (итеративное) выполнение (см. Рисунок 8) конструкции <cell>`streamsend(<out>) позволяет эффективно реализовать порождение результата-потока (лисп-списка).

В случае использования конструкции для порождения больших (или бесконечных) потоков может возникнуть ситуация, при которой функция порождающая поток (генератор) работает "слишком быстро" по сравнению с потребителями этого потока (функцией обработки потока). Понятно, что в этом случае построенный но еще необработанный фрагмент потока может потребовать для своего хранения слишком большого объема памяти. В таких ситуациях можно регулировать скорость порождения потока и скорость его потребления за счет использования в описании функции-генераторa опции lazy.

Использование компилятора t2cp

Процесс компиляции программы, написанной на языке программирования T2CP разбит на два шага:

Общие требования оформления файла с T2CP-текстом

Файл с исходным текстом Т-программы на языке T2CP должен иметь расширение ".tlc". Этот файл должен содержать:

#include "t2cp.h"

`func tmain (arg) -> (out);
...
`end_func

int _ut_app_init_step (int argc, char * argv []) {
...
}

Таким образом, текст Т-модуля имеет следующую структуру:

#include "t2cp.h"

..............описание Т-функций и Си-функций...

`func tmain (arg) -> (out);
...
`end_func
...
..............описание Т-функций и Си-функций...
...
int _ut_app_init_step (int argc, char * argv []) {
...
}
..............описание Т-функций и Си-функций...

Файл "t2cp.h" содержит описание всех Т-конструкций, реализованных на языке Си.

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

(arg`list [i])`paked_ptr (char)

Т-функция tmain должна определяться как имеющая один результат. Данный результат интерпретируется Т-системой как код завершения Т-задачи. В момент выполнения функцией tmain операции send по ее единственному выходу Т-система осуществляет завершение Т-задачи.

Ограничения реализации 3. Заголовок определения Т-функции tmain не может содержать опций stream и lazy.

Си-функция _ut_app_init_step выполняется до начала распределения вычислений по вычислительным узлам мультикомпьютера. В теле данной функции программист может разместить проверки различных условий, необходимых для корректной работы приложения, реализованного с использованием Т-системы-например, наличие того или иного необходимого файла, корректность параметров, переданных пользователем приложению в командной строке и т. п. В качестве первого аргумента данной функции передается количество параметров приложения; в качестве второго-строчное представление параметров приложения в стандартном для языка Си виде.

Первый шаг компиляции - генерация файлов на языке программирования Си

Т-программа включает в себя модуль, написанный на языке T2CP и несколько (возможно-ни одного) Си-модулей. Имя файла, содержащего текст программного модуля, написанного на языке T2CP, должно иметь расширение ".tlc".

Модуль, содержащий конструкции языка T2CP, будем называть Т-модулем. Контекстное препроцессирование текста Т-модуля производится с использованием исполняемой программы (компилятора, контекстного препроцессора) t2cp.

Компилятор t2cp преобразует Т-модуль, имя которого передается t2cp в качестве первого параметра, в два Си-модуля:

Примеры первого шага препроцессирования:

$ t2cp foo.tlc

На выходе t2cp получаем два Си-модуля-foo.c и tmds.c.

$ t2cp foo.tlc boo.c

На выходе t2cp получаем два Си-модуля-foo.c и boo.c.

Второй шаг компиляции - создание исполняемого файла Т-приложения

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

Использование утилиты make подразумевает разработку файла, описывающего процесс сборки исполняемого файла Т-приложения (обычно имеющего имя Makefile и располагающемся в том же каталоге, что и Си-модули, используемые на данном шаге компиляции). Разработка данного файла опирается на правила, определяемые утилитой make с учетом следующих условий:

 


1999 © T-System© ИЦМС ИПС РАН