Язык программирования Т2СР
Содержание
- Введение
- Синтаксис языка T2CP
- Препроцессируемые строки
- Препроцессируемые фрагменты
- Конструкция head.
- Конструкция tail
- Конструкция mkNil
- Конструкция isNil
- Конструкция mkCons
- Конструкция list
- Конструкция newList
- Конструкция length
- Конструкция int
- Конструкция mkInt
- Конструкция newPackedHolder
- Конструкция packed_ptr
- Конструкция mark_as_branch
- Конструкция is_branch
- Конструкция wait
- Конструкция ready
- Конструкция altseq
- Конструкция altlist
- Конструкция alt
- Конструкция drop
- Конструкция streamsend
- Использование компилятора t2cp
Язык программирования T2CP предназначен для написания программ, реализованных с использованием Т-системы-Т-программ, и является входным языком программирования для Т-системы. Данный язык программирования построен как расширение языка Си базовыми языковыми конструкциями, ориентированными на использование парадигм концепции автоматического динамического распараллеливания программ (данная концепция реализуется ядром Т-системы-Т-ядром).
Текущая реализация языка T2CP выполнена с использованием средств контекстного препроцессирования, что определило следующие черты реализации:
- Компилятор языка t2cp по сути является препроцессором:
- Компилятор языка t2cp преобразует входной текст, написанного на языке программирования T2CP, в программу на языке программирования Си. Дальнейшая компиляция полученной Си-программы и сборка исполняемой (под управлением Т-системы) Т- программы производится штатными средствами ОС Linux.
- Преобразование T2CP-текста в Си-текст компилятор языка T2CP реализует за счет обнаружения во входном файле фрагментов, подлежащих обработке-р-фрагментов,-и замене их на соответствующие им конструкции языка программирования Си.
- Текст, расположенный во входном T2CP-файле вне р-фрагментов помещается в выходной файл без каких-либо изменений.
- Используемый компилятором языка t2cp метод обнаружения р-фрагментов сильно отличается от методов, используемых классическими современными препроцессорами.
- Классически препроцессоры обычно для данной цели используют полный лексический и частичный синтаксический анализ исходного файла.
- Компилятор языка t2cp определяет р-фрагмент как контекст опорного символа "
`
" (обратный апостроф, штрих). А именно, t2cp считает фрагмент входного файла р-фрагментом в том случае, если этот фрагмент (последовательность литер исходного текста):
- расположен возле (несколько символов влево и вправо) символа "
`
";- удовлетворяет синтаксическим правилам, приведенным ниже в разделах 2.5 и 2.6 (препроцессируемые фрагменты-обрабатываемые фрагменты строк).
Помимо собственно контекстного препроцессирования в компиляторе языка t2cp имеется поддержка языковых понятий, которые более свойственны языкам программирования, чем препроцессорам-ограничение зоны действия имен переменных телом функции, в корой они определены, разграничение имен по классам-имена функций, входов, выходов,-и, как следствие, достаточно серьезная работа с таблицами имен. Все это обосновывает уместность использования обоих терминов: "компилятор T2CPСи" и "препроцессор T2CPСи".
При описании синтаксиса языка программирования T2CP в данном тексте будут использоваться следующие обозначения-метасимволы:
метасимвол
значение и/или описание " ::
"разделяет в синтаксическом определении левую часть определения-определяемое понятие или конструкцию-и правую часть-тело определения " |
"разделяет в теле определения различные варианты выбора-альтернативы. Каждая альтернатива обычно располагается на отдельной строке, и поэтому данный метасимвол обычно является первым в строке альтернативы " "
любое количество (0,1,...) пробелов или табуляций " ^
"начало строки <id>
синтаксическое понятие (в данном случае идентификатор-буква и следующее за ней любое количество букв, цифр и знаков " _
" (подчерков)<xx,...>
ноль, один, или несколько " <xx>
", разделенных последовательностью
",
":
<пусто> | <xx> | <xx> , <xx> |
и так далее<xx ...>
ноль, один, или несколько " <xx>
", разделенных ненулевым (положительным) количеством пробелов и/или табуляций:
<пусто> | <xx> | <xx> <xx> |
и так далее<int>
выражение языка программирования Си, имеющее целый тип (см. ниже ограничения реализации) <C-type>
корректный-в соответствие с правилами языка программирования Си-спецификатор типа (см. ниже ограничения реализации) Ограничения реализации 1. Как строка символов, фрагмент
<int>
должен удовлетворять следующим требованиям:
- все символы "
(
" ,")
", "[
", "]
", входящие в состав данного фрагмента должны образовывать сбалансированную скобочную структуру;- во фрагменте
<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. Т-список
Потоком (или лисп-списком) будем называть звено, которое:
- либо является звеном-держателем с нулевой длиной удерживаемой конструкции и с нулевым указателем (так называемый пустой лисп-список,
NIL
);- либо является звеном-держателем, удерживающим Т-структуру, состоящую из ровно двух одиночных звеньев, причем второе из данных звеньев является потоком (лисп-списком).
Конструкции языка 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. Пример держателя мультизвена
Определение дерева данных:
- Деревом является либо звено-развилка, либо звено-лист.
- Звеном-развилкой является звено-держатель имеющее особую отметку "развилка", которая устанавливается у звена-держателя при помощи специальной конструкции языка T2CP-
<cell>`mark_as_branch
.- Любое другое одиночное звено является листом дерева (в том числе-звенья-держатели, не имеющие отметки "развилка" см. Рисунок 6).
Рисунок 6. Пример дерева
Конструкции языка T2CP специализированные для работы с деревьями:
<cell>`mark_as_branch <cell>`is_branchВ текущей реализации контекстного препроцессора t2cp поддержаны два специальных режима препроцессирования, а именно:
- режим AUTOWAIT;
- режим DATACHECK.
Зона действия режима 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 в тексте Т-программы устанавливается при помощи конструкций "
#define DATACHECK 1
" и "#define DATACHECK 0
":#define DATACHECK 1 /* Начало зоны действия режима DATACHECK */ /* Зона */ /* действия */ /* DATACHECK */ #define DATACHECK 0 /* Конец зоны действия режима DATACHECK */Часть конструкций языка T2CP предусматривают поддержку режима DATACHECK (см. Таблица 1). При использовании таких конструкций в зоне действия режима DATACHECK перед началом исполнения конструкции производится некоторая проверка условий, позволяющих гарантировать, что данная конструкция применяется корректно. Состав выполняемой проверки для разных конструкций различен. В случае, если проверка не будет пройдена успешно, выдается детальное сообщение об ошибке и производится аварийное завершение всех Т-процессов текущей Т-задачи (на всех соисполнителях).
Препроцессируемые строки-строки входного файла, обрабатываемые целиком-имеют символ "
`
" (обратный апостроф) в качестве первого символа, отличного от пробела и табуляции.Препроцессируемая строка занимает ровно одну строку входного файла-целиком (с начала и до конца) и без переносов на другую строку. Результатом обработки таких строк является оформление одной из следующих конструкций:
- заголовок Т-функции
- завершение тела Т-функции;
- начало и конец области действия-
scope
иend_scope
-имен (аргументов, Т-переменных и выходов) Т-функции;- конструкция SEND-выдача одного из результатов Т-функции;
- конструкция ABORT-аварийное завершение Т-задачи;
- конструкция CALL-сетевой вызов Т-функции;
- конструкция ASSIGN-присваивание одному звену значения другого звена.
Заголовок определения Т-функции имеет следующий синтаксис:
^ `func<fid>
(<id,..>
) -> (<id,...>
)<option ...>
;<comment>
<vars-строка> ..... <vars-строка>
Здесь:
<fid>
-идентификатор (<fid> :: <id>
)-"имя" функции;- последовательность "
( <id,..> )
" слева от терминала "->
"-список имен звеньев-аргументов;- последовательность "
( <id,..> )
" справа от терминала "->
"-список имен выходов (результатов) функции.Фрагмент
<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 ...>
задают определенные особенности Т-функции:
stack ( <int> )
-устанавливает нестандартный размер стека необходимый для вызова из данной Т-функции других (Т- или С-) функий. По умолчанию размер стека равен 16 Кб.stream
-"возможны потоковые результаты"-определяет возможность использования в функции конструкцииstreamsend
;lazy
-"ленивая функция" (см. разделы 2.5.4 и 2.6.21 стр. 25).Конструкция конца описания Т-функции имеет следующий синтаксис:
^ `end_func <comment>
Данная конструкция ограничивает область действия аргументов, результатов и переменных Т-функции: обнаружив конец описания Т-функции, компилятор удаляет из таблицы действующих имен определенные в заголовке Т-функции имена аргументов, результатов и переменных Т-функции. Кроме того, завершая определение Т-функции, данная конструкция позволяет начать определение очередной Т-функции: вложенные определения Т-функций запрещены.
Синтаксис:
<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;<comment>Назначение. Данная конструкция приводит к завершению всех Т-процессов данной Т-задачи во всех соисполнителях.
Синтаксис
^ ` <cell_1> = <cell_2> ;<comment>Назначение. Данная конструкция выполняет копирование значения из звена
<cell_2>
в звено<cell_1>
(См. Рисунок 7).Выполнение конструкции:
- Звено
<cell_1>
теряет свое прежнее значение. В том случае, если звено<cell_1>
имело невычисленное значение, то связь между звеном<cell_1>
и поставщиком данного невычисленного разрушается.- Значение звена
<cell_2>
копируется в звено<cell_1>
. В том случае, если звено<cell_2>
имеет невычисленное значение, то звено<cell_1>
становится потребителем того же звена-поставщика, что и звено<cell_2>
.
Рисунок 7. Различные примеры выполнения операции assign
Синтаксис
^ ` <id> <== <cell> ;<comment>Назначение. Данная конструкция передает значение звена
<cell>
всем потребителям выхода<id>
текущего процесса.В результате выполнения конструкции
send
может быть передано как готовое, так и неготовое значение, находящееся в звене<cell>
. При рассылке неготового значения, потребители поставщика<id>
становятся потребителями того же поставщика, что и у звена<cell>
.В любом случае, в результате выполнения данной конструкции все потребители поставщика
<id>
получают то значение, которое имеет звено<cell>
(см. Рисунок 8).
Рисунок 8. Пример конструкции send
Конструкция вызова Т-функции имеет следующий синтаксис:
^ ` [ <cell,...> ] = <fname> ( <cell,...> ) ;<comment>Должны выполняться следующие условия:
<fname>
-имя одной из Т-функций, описанной в Т-программе;[ <cell,...> ]
-список звеньев-получателей результатов вычисления функции<fname>
. Каждая конструкция<cell>
из данного списка, должна быть синтаксически правильным определением звена, учитывающим в том числе определенные звеньевые-переменные того контекста, в котором используется конструкция вызова Т-функции. Длина данного списка должна в точности быть равной числу выходов функции<fname>
.( <cell,...> )
-список звеньев-аргументов для вычисления функции<fname>
. Каждая конструкция<cell>
из данного списка, должна быть синтаксически правильным определением звена, учитывающим в том числе определенные звеньевые переменные того контекста, в котором используется данная конструкция вызова Т-функции. Длина данного списка должна в точности быть равной числу аргументов функции<fname>
.
Выполнение вызова Т-функции включает следующие действия:
- Организация нового Т-процесса, с необходимым (в соответствии с описанием функции
<fname>
) числом аргументов, результатов, рабочих переменных и рабочих выходов.- Копирование значений) звеньев-аргументов, перечисленных в списке (
<cell,...>
), в соответствующие аргументы нового процесса.- Присваивание всем звеньям из списка [
<cell,...>
] соответствующих неготовых значений-эти звенья становятся потребителями соответствующих выходов функции<fname>
.- Инициализация нулевыми звеньями всех рабочих переменных нового процесса. Инициализация пустым множеством потребителей всех рабочих выходов нового процесса.
- Установка новому процессу признака готовности:
- "готов к исполнению"-если функция
<fname>
не имеет описателя "lazy
";- "не готов к исполнению"-если функция
<fname>
имеет описатель "lazy
".Поддержка функций с признаком "lazy". В Т-системе имеется поддержка ленивых (lazy) функций. В отличии от случая обычных функций, Т-процессы вычисления функций с признаком
lazy
:
- создаются в состоянии "не готов к исполнению";
- переходят в состояние "готов к исполнению"-в том случае, если имеется реальная потребность в их результате-имеется "заснувший" по неготовности их выхода процесс-потребитель;
- переходят в состояние "не готов к исполнению" в момент передачи значения по выходу-в том случае, если в данный момент отсутствуют процессы-потребители, запросившие заснувшие по неготовности других выходов данного Т-процесса.
Ниже (Таблица 1) приведено описание синтаксиса препроцессируемых фрагментов языка T2CP, описан тип возвращаемого фрагментом значения, способ его реализации и признак (
+
) поддержки в данном фрагменте режимов AUTOWAIT и DATACHECK.Таблица 1. Препроцессируемые фрагменты языка T2CP
Синтаксис результат способ реализации autowait
datacheck <fragment> :: <cell>`headcell macro +
+ | <cell>`tailcell macro +
+ | <cell>`isNilint macro +
+ | <cell>`mkNilvoid inline | <cell>`mkCons ( <cell> , <cell> )void macro | <cell>`mkInt ( <int> )int inline | <cell>`intint macro, Lvalue +
+ | <cell>`list [ <int> ]cell macro +
+ | <cell>`newList ( <int> )void macro | <cell>`lengthint macro, Lvalue +
+ | <cell>`newPackedHolder ( <int> )void macro | <cell>`packed_ptr ( <c-type> )(c-type)* macro +
+ | <cell>`mark_as_branchvoid +
+ | <cell>`is_branchint +
+ | <cell>`waitint macro | <cell>`readyint | <cell>`altseqint | <cell>`altlistint | <cell>`alt ( <cell,...> )int | <cell>`dropvoid inline | <cell>`streamsend ( <out> )void Синтаксис
<cell>`headНазначение. Данная конструкция применима только для работы с лисп-списками. Конструкция используется для доступа к первому элементу лисп-списка, удерживаемого звеном
<cell>
.Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что
<cell>
содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции происходит проверка является ли
<cell>
правильным готовым лисп-списком, отличным отNIL
. А именно, проверяется, что:
- звено
<cell>
готово;- звено
<cell>
является держателем Т-списка;- длина удерживаемой звеном
<cell>
Т-списка равна 2.Результатом конструкции является звено, являющиеся первым элементом лисп-списка, удерживаемого звеном
<cell>
(см. Рисунок 9).Синтаксис
<cell>`tailНазначение Данная конструкция применима только для работы с лисп-списками и используется для доступа ко второму элементу лисп-списка, удерживаемого звеном
<cell>
, которое является держателем лисп-списка.Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что
<cell>
содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции происходит проверка является ли
<cell>
правильным готовым лисп-списком, отличным отNIL
. А именно, проверяется, что:
- звено
<cell>
готово;- звено
<cell>
является держателем Т-списка;- длина удерживаемой звеном
<cell>
Т-списка равна 2.Результатом конструкции является звено, являющиеся вторым элементом лисп-списка, удерживаемого звеном
<cell>
(см. Рисунок 9).
Рисунок 9. Пример конструкций head и tail
Синтаксис
<cell>`mkNilНазначение. Данная конструкция предназначена для создания в звене
<cell>
значенияNIL
("пустой лисп-список").Выполнение конструкции
<cell>`mkNil
:
- Производятся действия по очистке звена
<cell>
(См. Конструкция drop, 2.6.20)- Звено
<cell>
преобразуется в звено-держатель с нулевой длиной удерживаемой конструкции и нулевым указателем.Синтаксис
<cell>`isNilНазначение. Данная конструкция предназначена для проверки является ли данное звено
<cell>
пустым лисп-списком.Поддержка AUTOWAIT. Если конструкция используется в зоне установленного режима AUTOWAIT, то перед выполнением конструкции проверяется, что
<cell>
содержит готовое значение, и если это не так, выполняется ожидание готовности этого значения.Поддержка DATACHECK. Если конструкция используется в зоне установленного режима DATACHECK, то перед выполнением конструкции проверяются следующие условия:
- звено
<cell>
-готово;- звено
<cell>
-звено-держатель;<cell>
является лисп-списком:
- непустым лисп-списком-длина удерживаемой Т-конструкции равна 2,-или
- пустым лисп-списком-длина удерживаемой Т-конструкции равна 0 и указатель удерживаемой Т-конструкции-нулевой.
Результат конструкции. Конструкция возвращает
(int) 1
(TRUE) в случае если<cell>
-пустой лисп-список,(int) 0
(FALSE) если это не так.Синтаксис:
<cell>`mkCons( <cell_car>, <cell_cdr>)Назначение. Конструкция предназначена для построения лисп-списка
<cell>
с использованием звеньевого значения, содержащегося в звене<cell_car>
, и лисп-списка, удерживаемого звеном<cell_cdr>
. Данная конструкция рекомендуется для работы с лисп-списками.Выполнение конструкции:
- захватываются два (расположенных рядом) звена;
- в первое из захваченных на предыдущем шаге звеньев копируется значение, содержащиеся в звене
<cell_car>
;- во второе звено копируется значение звена-держателя
<cell_cdr>
;- в звене
<cell>
формируется держатель пары звеньев, захваченных на первом шаге (естественно, прежнее значение звена<cell>
-теряется).Таким образом, в результате выполнения операции
mkCons
значением звена<cell>
становится новый лисп-список, содержащий звено<cell_car>
в качестве "головы" и лисп-список<cell_cdr>
в качестве "хвоста".Замечание. При выполнении данной конструкции не требуется, что бы звено
<cell_car>
(или звено<cell_cdr>
) содержало готовое значение.
Рисунок 10. Пример использования операции
mkCons
Синтаксис:
<cell>`list [ <int> ]Назначение. Данная конструкция используется для доступа к элементу Т-списка
<cell>
с порядковым номером<int>
(звенья в Т-списках нумеруются начиная с 0).Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
-готово;<cell>
содержит держатель, удерживающий Т-список (обозначим длину данного спискаL
);0 <= <int> < L
Результатом выполнения данной операции является звено, входящее в удерживаемый звеном
<cell>
Т-список. Порядковый номер звена-результата в данном Т-списке равен<int>
(звенья в Т-списках нумеруются начиная с 0).Синтаксис:
<cell>`newList( <int> )Назначение. Данная конструкция предназначена для создания нового Т-списка длиной
<int>
(размер указывается в звеньях).Выполнение конструкции:
- Выполняется захват расположенных подряд
<int>
звеньев свободной памяти. Захваченные звенья обнуляются.- В звено
<cell>
помещается держатель, удерживающий захваченные на предыдущем шаге звенья. Прежнее значение звена<cell>
теряется.Синтаксис
<cell>`lengthНазначение. Данная конструкция предназначена для извлечения длины (в звеньях) Т-структуры удерживаемой звеном-держателем
<cell>
.Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
-готово;- звено
<cell>
является держателем Т-структуры;- специфицированное в звене
<cell>
значение длины удерживаемой Т-структуры неотрицательно.Результатом выполнения данной операции является целое число-длина (в звеньях) Т-структуры, удерживаемой держателем
<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Синтаксис
<cell>`intНазначение. Данная конструкция предназначена для доступа к целому значению, хранящемуся в звене
<cell>
.Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
содержит готовое значение;- звено
<cell>
имеет признак скалярного значения.Результатом выполнения данной операции является целое число-значение байтов 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Синтаксис
<cell>`mkInt ( <int> )Назначение операции. Сохранение целого Си-значения
<int>
в качестве значения звена<cell>
.Выполнение конструкции. В звено
<cell>
помещается целое Си-значение<int>
и соответствующий тэг. Естественно, прежнее значение звена<cell>
теряется.Результат конструкции: конструкция возвращает целое Си-значение-
<int>
.Синтаксис
<cell>`newPackedHolder ( <int> )Назначение. Данная конструкция предназначена для построения мультизвена, содержащего бестэговую область размера
<int>
байт и помещения в<cell>
держателя данного мультизвена (держателя упакованных данных).Выполнение конструкции:
- Происходит захват участка звеньевой памяти размером достаточным для оформления мультизвена с бестэговой областью размера
<int>
байт, предназначенной для хранения упакованных данных. Захваченная бестэговая область обнуляется.- В звено
<cell>
помещается держатель (с корректным тэгом и звеном), удерживающий построенное мультизвено. Естественно, прежнее значение звена<cell>
теряется.Синтаксис
<cell>`packed_ptr ( <C-type> )Назначение. Данная конструкция предназначена для доступа к структуре данных, имеющую корректный в смысле языка программирование Си тип
<C-type>
, упакованной в бестэговую область мультизвена, удерживаемого звеном-держателем<cell>
.Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
-готово;- звено
<cell>
-звено-держатель мультизвена;- специфицированное в звене
<cell>
значение длины удерживаемой Т-структуры (мультизвена) неотрицательно.Результатом выполнения данной операции является Си-указатель (
<C-type>*
) на структуру данных типа<C-type>
, размещенных в мультизвене, удерживаемом звеном-держателем<cell>
.Синтаксис
<cell>`mark_as_branchНазначение. Данная конструкция позволяет преобразовать звено-держатель Т-списка в звено-развилку дерева данных-см. раздел 2.3.6 стр. 9 и Рисунок 6. А именно: конструкция предназначена для пометки собственного готового держателя
<cell>
Т-списка специальным дополнительным признаком "развилка дерева данных".Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
-готово;- звено
<cell>
-является держателем Т-структуры;- специфицированное в звене
<cell>
значение длины удерживаемой Т-структуры неотрицательно.Выполнение: Звено
<cell>
помечается специальным дополнительным признаком (дополнительным тэгом) "развилка дерева данных".Синтаксис
<cell>`is_branchНазначение. Данная конструкция предназначена для проверки, является ли звено
<cell>
звеном-развилкой дерева данных (то есть, является ли оно звеном-держателем, имеющим особую отметку "развилка")-см. раздел 2.3.6 стр. 9 и Рисунок 6.Поддержка AUTOWAIT. Если конструкция используется в области действия режима AUTOWAIT, то перед выполнением данной операции производится проверка готовности звена
<cell>
, и если оно не готово, то выполняется операция ожидания готовности значения данного звена.Поддержка DATACHECK. Если конструкция используется в области действия режима DATACHECK, то перед выполнением данной операции проверяются следующие условия:
- звено
<cell>
-готово;- если звено
<cell>
является держателем Т-списка, имеющим дополнительную пометку "развилка", то длина удерживаемой области неотрицательная.Результатом выполнения данной операции является целое значение равное:
1
(TRUE), в случае если<cell>
-звено-развилка дерева данных (то есть, звено-держатель, имеющим особую отметку "развилка");0
(FALSE)-в противном случае:<cell>
-звено-лист дерева данных.Синтаксис
<cell>`waitНазначение. Данная конструкция предназначена для ожидания готовности звена
<cell>.
Выполнение:
- происходит проверка звена
<cell>
на готовность;- в случае, если звено
<cell>
содержит готовое значение, выполнение операции завершается;- в случае неготовности звена
<cell>
(звено является звеном-потребителем-имеет признак неготового значения), происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению";- в момент наступления события "ожидаемое звено готово" процесс "просыпается"-переходит в состояние "готов к выполнению".
Возвращаемое данной операцией значение имеет целый тип и всегда равно 1.
Синтаксис
<cell>`readyНазначение. Данная конструкция предназначена для проверки готовности значения, содержащегося в звене
<cell>
(имеет ли данное звено признак готового значения).Результатом выполнения данной операции является целое значение равное:
1
(TRUE), в случае если значение звена<cell>
имеет признак готовности звена;0
(FALSE)-в противном случае.Синтаксис
<cell>`altseqТерминология, используемая в описании конструкции.
Элементами лисп-списка
<cell>
будем называть все первые звенья из каждой пары одиночных звеньев (cons-пары), образующих лисп-список<cell>.
То есть, элементами непустого лисп-списка<cell>
являются:
<cell>`head
;(<cell>`tail)`head
-если!(<cell>`tail)`isNil
;((<cell>`tail)`tail)`head
-если!(<cell>`tail)`isNil &&
;
!((<cell>`tail)`tail)`isNil- и т.д.
Ниже (см. Рисунок 11) на первом фрагменте рисунка изображен лисп-список
x
, в котором три элемента и все они имеют неготовое значение.Суффиксами лисп-списка
<cell>
будем называть все вторые звенья из каждой пары одиночных звеньев (cons-пары), образующих лисп-список<cell>.
То есть, суффиксами непустого лисп-списка<cell>
являются:
<cell>`tail
;(<cell>`tail)`tail
-если!(<cell>`tail)`isNil
;((<cell>`tail)`tail)`tail
-если!(<cell>`tail)`isNil &&
;
!((<cell>`tail)`tail)`isNil- и т.д.
Ниже (см. Рисунок 11) на первом фрагменте рисунка изображен лисп-список
x
, в котором три суффикса и все они имеют готовое значение.Назначение. Конструкция
<cell>`altseq
предназначена для ожидания готовности хотя бы одного из элементов непустого лисп-списка<cell>
(см. Рисунок 11).Выполнение:
- Конструкция
<cell>`altseq
реализована в предположении, что выполнены следующие условие:<cell>
-готовый держатель непустого лисп-списка все суффиксы которого являются готовыми звеньями. В начале выполнения конструкции проверяется это условие, и если оно не выполнено, вся текущая Т-задача завершается аварийно (см. описание конструкцииabort
, раздел 2.5.4 стр. 12).- Происходит проверка на готовность всех элементов лисп-списка
<cell>
.- В случае, если один из элементов лисп-списка
<cell>
готов, то выполнение операции завершается.- В случае неготовности всех элементов лисп-списка
<cell>
, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".- В момент наступления события "по крайней мере один элемент лисп-списка
<cell>
содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.Таким образом, в любом случае в момент завершения операции по крайней мере один элемент лисп-списка
<cell>
содержит готовое значение.Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру элемента лисп-списка
<cell>
, который на момент завершения операции содержал готовое значение. Элементы в лисп-списке нумеруются с 0.
Рисунок 11. Пример выполнения операции <cell>`altseq
Синтаксис
<cell>`altlistНазначение. Конструкция
<cell>`altlist
предназначена для ожидания готовности хотя бы одного из элементов (<cell>`list[0]
,...<cell>`list[L-1]
, гдеL=<cell>`length
) непустого Т-списка<cell>
.Выполнение:
- Конструкция
<cell>`altlist
реализована в предположении, что выполнены следующие условие:<cell>
-готовый держатель непустого Т-списка ((<cell>`ready) && (<cell>`length>0)
). В начале выполнения конструкции проверяется это условие, и если оно не выполнено, вся текущая Т-задача завершается аварийно (см. описание конструкцииabort
, раздел 2.5.4 стр. 12).- Происходит проверка на готовность всех элементов Т-списка
<cell>
.- В случае, если один из элементов Т-списка
<cell>
готов, то выполнение операции завершается.- В случае неготовности всех элементов Т-списка
<cell>
, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".- В момент наступления события "по крайней мере один элемент Т-списка
<cell>
содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.Таким образом, в любом случае в момент завершения операции по крайней мере один элемент Т-списка
<cell>
содержит готовое значение.Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру
i
элемента Т-списка<cell>
, который на момент завершения операции содержал готовое значение:<cell>`list[i]`ready
. Элементы в Т-списке нумеруются с 0.Синтаксис
<cell_1>`alt ( <cell,...> )Назначение. Конструкция
<cell>`alt
предназначена для ожидания готовности хотя бы одного из элементов непустого перечисления звеньев:
(<cell_1>, <cell,...>)
.Выполнение:
- Происходит проверка на готовность всех элементов из непустого перечисления звеньев
(<cell_1>, <cell,...>)
.- В случае, если один из элементов перечисления звеньев готов, то выполнение операции завершается.
- В случае неготовности всех элементов перечисления звеньев, происходит "засыпание" процесса, выполняющего данную операцию-он переходит в состояние "не готов к выполнению".
- В момент наступления события "по крайней мере один элемент перечисления звеньев
(<cell_1>, <cell,...>)
содержит готовое значение" процесс "просыпается"-переходит в состояние "готов к выполнению,"-и операция завершается.Таким образом, в любом случае в момент завершения операции по крайней мере один элемент перечисления звеньев
(<cell_1>, <cell,...>)
содержит готовое значение.Возвращаемое данной операцией значение имеет целый тип и равно порядковому номеру
i
элемента перечисления звеньев(<cell_1>, <cell,...>)
, который на момент завершения операции содержал готовое значение. Элементы в перечисления звеньев нумеруются с 0.Синтаксис
<cell>`dropНазначение. Данная конструкция производит очистку (обнуление) звена
<cell>
. При этом, в случае если звено<cell>
имеет неготовое значение, происходит корректное разрушение связи поставщик-потребитель между звеном<cell>
и поставщиком данного звена.Синтаксис
<cell>`streamsend ( <out> )
Рисунок 12. Пример конструкции streamsend
Назначение. Конструкция
<cell>`streamsend(<out>)
рассылает всем потребителям выхода<out>
текущего процесса держатель структурыCons
(Т-список из двух звеньев) в котором:
- первое звено содержит копию значения звена
<cell>
;- второе звено содержит неготовое значение, поставщиком которого является тот же самый выход
out
текущего процесса.Таким образом, в отличии от обычной конструкции
send
, данная конструкция сохраняет за текущим процессом обязанность вычисления значения выходаout
.Замечание 1. Конструкция
<cell>`streamsend(<out>)
допустима только в теле Т-функции-или в так называемой области (scope-зоне) действия переменных данной Т-функции,- в описании заголовка которой указана опцияstream
.Реализация конструкции использует вспомогательные (и не доступные пользователю) выход и переменную функции.
Замечание2. Многократное (итеративное) выполнение (см. Рисунок 8) конструкции
<cell>`streamsend(<out>)
позволяет эффективно реализовать порождение результата-потока (лисп-списка).В случае использования конструкции для порождения больших (или бесконечных) потоков может возникнуть ситуация, при которой функция порождающая поток (генератор) работает "слишком быстро" по сравнению с потребителями этого потока (функцией обработки потока). Понятно, что в этом случае построенный но еще необработанный фрагмент потока может потребовать для своего хранения слишком большого объема памяти. В таких ситуациях можно регулировать скорость порождения потока и скорость его потребления за счет использования в описании функции-генераторa опции
lazy
.Использование компилятора t2cp
Процесс компиляции программы, написанной на языке программирования T2CP разбит на два шага:
- на первом шаге компиляции-контекстном препроцессировании-текст программного модуля, написанный на языке T2CP преобразуется в программу на языке программирования Си;
- на втором шаге с использованием компилятора языка Си полученная Си-программа преобразуется в исполняемый файл Т-приложения, содержащий исполняемый код Т-задачи.
Общие требования оформления файла с T2CP-текстом
Файл с исходным текстом Т-программы на языке T2CP должен иметь расширение "
.tlc
". Этот файл должен содержать:
- директиву Си-препроцессора
#include "t2cp.h"
- определение Т-функции
tmain
`func tmain (arg) -> (out); ... `end_func
- определение Си-функции
_ut_app_init_step
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
в качестве первого параметра, в два Си-модуля:
- текстовый модуль на языке Си, полученный как результат контекстного препроцессирования. Имя данного модуля является совпадает с именем исходного Т-модуля без расширения, а расширение заменяется на-"
.c
"-стандартное расширение имен файлов, содержащих текст программ на языке программирования Си;- текстовый модуль на языке Си, построенный компилятором
t2cp
, содержащий дескриптор Т-задачи-определение (на языке программирования Си) структуры данных, необходимой для корректного функционирования Т-ядра. Имя данного модуля может быть задано в качестве второго параметра программыt2cp
. По умолчанию компилятор помещает определение дескриптора Т-задачи в файл с именем "tmds.c
".Примеры первого шага препроцессирования:
$ t2cp foo.tlc
На выходе
t2cp
получаем два Си-модуля-foo.c
иtmds.c
.
$ t2cp foo.tlc boo.c
На выходе
t2cp
получаем два Си-модуля-foo.c
иboo.c
.Второй шаг компиляции - создание исполняемого файла Т-приложения
Поскольку результатом контекстного препроцессирования являются два Си-модуля, и кроме них Т-приложение может включать в свой состав модули, изначально написанные на языке программирования Си, то наиболее рациональным методом сборки исполняемого файла Т-приложения является использование возможностей, предоставляемых утилитой
make
.Использование утилиты
make
подразумевает разработку файла, описывающего процесс сборки исполняемого файла Т-приложения (обычно имеющего имяMakefile
и располагающемся в том же каталоге, что и Си-модули, используемые на данном шаге компиляции). Разработка данного файла опирается на правила, определяемые утилитойmake
с учетом следующих условий:
- в состав исполняемого файла Т-приложения должны быть явно включены модули, содержащие исполняемый код ядра Т-системы;
- при определении флагов, используемых Си-компилятором на этапе генерации объектных файлов, необходимо в их состав включить опцию компилятора, специфицирующую каталог, в котором расположен файл "
t2cp.h
" в качестве одного из каталогов, в которых Си-компилятор производит поиск "#include
"-файлов.
1999 © T-System | © ИЦМС ИПС РАН |