2012/08/30 17:37:28

Функциональная потоковая ЭВМ. Потоки и их обработка в структуре выражения

Статья продолжает (начало – разделы 2 и 3) проект не фон_Неймановской структуры потоковой ЭВМ с параллельной обработкой потоков данных и выражений (программ) в виде динамически перестраиваемой структуры коллектива микропроцессоров (транспьюттеров) по структуре очередного выражения – суперпозиции функций. Здесь предлагаются примитивы организации структуры потоков данных, естественным образом решающие проблемы синхронизации потоков, их разделения по свойствам элементов, методы формирования и обработки (полный пересмотр к 15.08-2013 г.)

Содержание

Ссылки на все разделы проекта:

1. Функциональная Потоковая Машина с параллельными вычислениями. Введение (http://tadviser.ru/a/121275)
2. Единая структура данных и программ (http://tadviser.ru/a/149691)
3. Функционирование ФПМ. Выражения языка програмирования (http://tadviser.ru/a/149691)
4. Потоки и их обработка в структуре выражения (http://tadviser.ru/a/150588)
5. Микропрограммирование функций (http://tadviser.ru/a/153069)
6. Программа, как управляемый поток выражений (http://tadviser.ru/a/153069)
7. Макроопределения пользовательских функций(http://tadviser.ru/a/157631)

Известный писатель-фантаст Сергей Лукьяненко выступит на TAdviser SummIT 28 ноября. Регистрация 5.7 т

4. Потоки и их обработка в структуре выражения


Напомним, что выражение языка ФПМ до исполнения разворачивается в аналогичную СА, по структуре (дерево из связанных микро-ЭВМ) совпадающей со структурой выражения с точностью до макроопределений и определяемых примитивом _Out (п.4.2.3) дополнительных выходов функций. Потому говоря о потоках на входах и выходах функций выражения, подразумеваем потоки в соответствующей СА. К реализующим в СА функции микро-ЭВМ стандартным образом - подключается калькулятор _Calc (унифицированная микро-ЭВМ), выполняющий стандартным образом обработку параметров (п.3.4.1.2), входных и выходых потоков функций посредством операций _Calc (формулы, примитивы _If, операции _Break, _Skip и др.), вводимых пользователем в состав "прозрачных" аргументов (в любом месте среди основных аргументов) функции. Более того, сходным образом, однако с учетом характера конкретной функции непосредственно к ее операциям подключается все тот же _Calc, иногда выполняющий основные операции функции (например, $Sync) по умолчанию (отсутствию) операций _Calc среди ее аргументов

Наконец, обратим внимание на структуру потока (п.2.5), в котором каждый элемент может обладать собственными свойствами (п.2.4). Согласно этому в потоке движутся элементы - непосредственно атомы (%\%) или ссылки на структуры в Динамически Распределяемой (единой) Памяти (ДРП) в виде R-(%@%) или V- (%&%) значений вместе с их свойствами и свойствами указываемых ими структур данных и выражений в ДРП.

4.1. Генераторы потоков


Понятно, что в структуре выражения должны быть источники потоков - их генераторы. Значения аргументов генераторов могут быть литералами или вычисляться (за исключением *Lit). В случае если аргумент генератора формирует поток, то в качестве унарного (единственного) значения принимается первый элемент потока, который затем прерывается (_Break). Большая часть генераторов (кроме *Stream и *Lit) аргументы определяют как свои (функции) параметры с фиксированными именами, которые можно контролировать, обрабатывать и изменять согласно п.3.4.1.2. Так ничто не мешает в этом случае требуемый параметр All (количество) задать как слой и при обработке заменить его значение "слой" числом элементов в этом слое. Генерируемые потоки можно обрабатывать, как и выходные потоки любой функции и тем же средствами п.4.2. Более того, как и обычнвя функция генератор по завершении генерируемого потока сообщает его окончание без свойств (%%).

4.1.1. Простейшие генераторы потоков


1) *Stream(<аргумент>{<b,</b><аргумент>}) - вычисленные унарные (п.6.1) значения аргументов в порядке их очередности (слева направо) подаются на выход функции. При этом аргументы - литералы–атомы копируются (приводятся к виду %\%). В случае агументов литералов - слоев и узлов копируются их R-значения – ссылки УКА и УКС

Примеры генерации потоков:

  *Stream(1,2,3,#) 	-  1, 2, 3, (атомы %\.9+%, п.2.2.2) и
			# - неопределенное значение

  *Stream(1.,2.1,3.3,5(6))  - 1., 2.1, 3.3 (%./%) и 5(6) - 
				 - R-значение (%@.9+,%)

  *Stream(1,2,3,*Stream(4,5,6)) - 1, 2, 3 (%\.9+%), 4 (@.9+~,%)

2) *Lit(<аргумент>{,<аргумент>}) - Действие аналогично *Stream (см. выше) с той лишь разницей, что каждый аргумент НЕ вычисляется, а определяется как литерал, R-значение которого - ссылки УКА и УКС на значение аргумента в приведенном выражении *Lit копируются на выход генератора с дополнительным свойством '?' защиты.

Примеры генерации потоков:

  *Lit(1,2,3)		- 1,2,3 (R-значения атомов, %@.+?~,%)

  *Lit(1,2,3,5(6))  	- 1, 2, 3 (@%.+?~,%), 5(6) (%@.+?,?%)

  *Lit(1,2,3, *Stream(4,5)) -  1, 2, 3 (@%.+?~,%),*Stream(4,5) 
		  	   			   ( %@.*?,?%)

Внимание! – Сравните эти примеры с аналогичными в (1)

4.1.2. Настраиваемый генератор потока "Ряд"


_Row([From:]<выражение>,[All:]<Количество>[,<операции>])

Отличие "операций" от аналогичных по п.3.4.1.2 в следующем:

1) Вычисленное выражение (первый член потока и только!) и возможно скорректированное как параметр From (п.3.4.1.2) до выполнения операций помещается в регистр '!'

2) Операции повторяются над регистром '!': каждый раз этот регистр к началу операций содержит последнее вычисленное значение регистра '!', НЕ обязательно отправленное на выход из-за операции _Skip. В любом случае по завершению очередной операции счетчик $i увеличивается на 1

3) При каждой отправке нового элемента (значение '!') на выход автоматически на 1 увеличивается значение регистра $n (счетчик членов генерируемого ряда) и копия этого элемента (атом, R- или V-значение) сохраняется в регистре $e изначально без свойств (%%), доступном в операциях генерации следующего элемента. Регистры $iб $n и $e ведутся автоматически и их корректировка операциями НЕ допускается

4) В отсутствие _Break генерация возобновляется (повторяется), пока значение $n не достигнет значения All. В этом случае в регистре '!' поступает код окончания с отсуnствием свойств (%%) и операции повторяются последний раз над этим регистром, что позволяет сформировать в нем значение сумматора (регистра $S и не только).

4.1.2.1. Реализация генератора потока "Ряд" по умолчанию "операций"


Эта реализация исключительно в СА:

  *Row(From:<выражение>,All:<Количество>,
	_Par(All:{_If(%.9+~,%,`!%\.%->!`,_Go),`1->!`},
	     FROM:{_If(%&%,`!%&@%;.->!`)}
	    ),
	``
      )

1) Если All не является целым положительным, то операции по его преобразованию (примитив _Par) устанавливают его в 1. Иначе All приводится к виду Атом (%\.%). Эта реализация обработки параметра All вводится по его умолчанию и только в СА, иначе в это выражение помещаются операции пользователя по анализу и преобразованию All

2) В случае V-значения (%&%) параметра FROM (_If) в регистре '!' это V-значение копируют его в регистр '.' с требованием (%&@%) наличия указываемого им R-значения. В отсутствие последнего его создают неопределенным аналогично макро $Sel (п.4.3.2) и затем исходное V-значение, но уже имеющее указываемое им неопределенное R-значение,помещают (->) в регистр '!' - новое значение параметра FROM

3) В силу п.4.1.2(1-2) по умолчанию операций *Row повторяет All раз пустую формулу `` (без операций _Calc), повторяя передачу содержимого регистра '!' с возможно скорректированным исходным значением (2) параметра FROM

4.1.2.2. Макроопределения на базе генератора потока "Ряд"


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

1) *Num([All:]<Количество>[,[Step:]<шаг>][,[From:]<Начало>]) – генерирует поток

  • ряд чисел от начального значения From, 0 - по умолчанию или не целого, с указанным Количеством (All) и заданным шагом Step

(по умолчанию 1): на выход выдается <Начало>, затем <Количество>-1 раз <шаг> добавляется к последнему генерированному значению. Реализуется следующим образом только в СА:

  *Row(From:<выражение>,All:<Количество>[,Step:<шаг>],
       _Par(All:{_If(%~.,%,<>!->!,_Go),_If(%.9+~,%,`!%\.%->!`,_Go),`1->!`},
	    From:{_If((%.9~,%,%./~,%),`!%\.%->!`,_Go),`0->!`},
	    Step:{_If((%.9~,%,%./~,%),`!%\.%->!`,_Go),`1->!`}
	   ),
	{_If(%%,_Go),`$n`,_if(%.9~0%,`!+=Step`),`$S+=!`} /При $n<>0 '!' растет на Step/ 
      )

Отметим лишь, что параметр All может задан слоем и в этом случае в качестве All используется размером слоя (к-во элементов).
Подсчитываемую сумму $S генерируемого ряда можно поместить в подпространство посредством примитива _Sum - прозрачного аргумента макро *Num (п.4.4).

Примеры генерации потоков:

  *Num(From:1,All:5)	- 1, 2, 3, 4, 5  (%\.9+%)
  *Num(5,-1,5) 		- 5, 4, 3, 2, 1  (%\.9+%)
  *Num(5,2)  		- 0, 2, 4, 6, 8  (%\.9+2%)

2) *Fact([All:]<Количество>) – генерирует поток из факториалов чисел натурального ряда:

  *Row(From:1,All:<Количество>,
       _Par(All:{_If(%.9+~,%,`!%\.%->!`,_Go),`1->!`}),
	{_If(%%,_Go),`$n`,_if(%.9~0%,`$n+1;*$e;->!`),`$S+=!`}
      )
Пример генерации потока факториалов:

  *Fact(5) - 1, 2, 6, 24, 120  

2) *Degree([Base:]<Основание,[All:]<Количество>) – генерирует поток из степеней 1, 2, ..., All основания:

   *Row(From:1,All:<Количество>,Base:<основание>,
	_Par(All:{_If(%.9+~,%,`!%\.%->!`,_Go),`1->!`},
	    Base:{_If((%.9~,%,%./~,%),`!%\.%->!`,_Go),_Break}
	   ),
	_If(%~%,`Base*!;->!;$S+=!`)
       )
Пример генерации потока степеней с основанием 2:

  *Degree(2,5)  - 2, 4, 8, 16, 32



4.1.3. Генерация V-значений слоя


*Sel([Struct:]<слой[R-значение]>[,_More]) – генерация V-значений элементов слоя по УКС обрабатываемого (Struct) R-значения при наличии _More в порядке возрастания указываемых этими V-значениями элементов (их атомов), иначе (опущено _More) в порядке следования в самом слое. Есть возможность управления сортировкой V-значений (точнее, указываемых ими R-значений слоя) использованием операций _If и формул _Calc. Эта возможность рассматривается вместе с функцией $Merge слияния генерируемых *Sel (и др. функциями) потоков (п.4.3.4). Там же подробнее и о генераторе *Sel

4.1.4. Обход дерева структуры по контуру


*Tree([Struct:]<Структура>[,[Deep:]</b><глубина>]) - генерация V-значений элементов (вершин) древовидной структуры (дерево) в процессе и порядке ее обхода по контуру сверху вниз по УКС и слева направо в слое с задаваемым ограничением по числу проходимых уровней структуры при движении вниз по УКС. В сущности это схема от классической "сверху вниз и слева направо" лишь тем, что V-значения вершин - элементов слоя формируются лишь один раз при первом достижении вершины. Deep является целым или приводится (округляется) до целого. Максимально допустимое значение Deep - 26. Любое иное значение этого параметра, возможно после преобразований операциями п.3.4.1.2, автоматически заменяется на 26. Минимальное значение Deep=1 и в этом случае действие *Tree идентично *Sel (п.4.1.1) в отсутствие параметра _More.

Рассмотрим подробнее действие генератора *Tree с использованием операций _Calc, позволяющих НЕ только получить V-значения вершин структуры в процессе ее обхода, но и обработать эти вершины с учетом их связи по уровням иерерахии структуры, например, выполнив определенные вычисления, но даже внести изменения в саму структуру в процессе ее обхода. Попутно понятнее станет и процесс реализации этого обхода:

1) Функция *Tree организует обход структуры, используя стек, который содержит маршрут - путь на структуре от некоторой вершины - V-значения элемента (дно стека) слоя по УКС исходной структуры (параметр Struct) до V-значения проходимой вершины - вершины стека. Первоначально в стек помещается один элемент - V-значение первого слева элемента слоя по УКС (УКС, индекс 0) исходной структуры (параметр Struct). Затем следующие действия:

  а) При наличии УКС на не пустой слой в R-значении, указываемом V-значением вершины стека, формируется V-значение <УКС, индекс 0> и это новое V-значение помещается в вершину стека (пополняет его): фактически это переход на один уровень вниз. Это действие блокируется и сразу к (б), если количество уровней (число V-значений в стеке) достигло значения Deep.

  б) В отсутствие УКС на НЕ пустой слой в R-значении, указываемом V-значением вершины стека, делается попытка в этом V-значении <УКС,индекс> увеличить значение индекса на 1 - перейти к следующему элементу слоя по УКС V-значения.

  в) Если попытка (б) неудачна - отсутствует следующий элемент слоя, то из вершины стека выталкивается - удаляется V-значение и возврат к действию (б), если, конечно, стек НЕ пуст. Иначе обход структуры завершается.

2) В стеке, начиная от его вершины и к его дну элементы именуются (идентифицируются) в формулах _Calc, как a, b, c, ... Как и в случае кортежа изменения этих элементов - V-значений НЕ допускаются, однако операции формул (р.5) допускают изменение указываемых ими (V-значения) атомов, а в случае находящегося в вершине стека a и слоя R-значения.

3) Как и в случае операций с кортежом (п.4.3.2) здесь допускаются все виды представления _If, включая (4-1)

4) Как и в случае операций с кортежом (п.4.3.2(4)) здесь формула _Calc (р.5) может содержать цикл (начинаться '*>' или '*<') - повторяться для каждого из элементов 'a'-'z' стека (как ранее кортежа)

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

6) К началу операций регистр '!' содержит копию V-значения вершины стека или код окончания операций без свойств (%%). Как обычно операция _Skip блокирует выдачу значения регистра '!' на выход функции и выполнение последующих за ней операций, вызывая дальнейшие действия функции в обходе структуры. Операция _Break, как обычно, прерывает все операции функции, включая обход структуры. До выдачи на выход функции операции могут скорректировать содержимое регистра '!'. С другой стороны отмена посредством _Skip значения регистра '!' на выход НЕ отменяет выполненных операциями (до _Skip) изменения в структуре Struct

7) При пополнении стека новым V-значением этот элемент в вершине стека приобретает динамическое свойство '>' (п.4.5). В случае успешной реализации (1б) это свойство удаляется и заменяется на динамическое свойство '='. Если этому предшествовали действия (1в), то дополнительно вершина стека приобретает свойство '<'.

8) Отсуствующие (указываемые именами) элементы в стеке лишены свойств (%%)

9) Операция a++ формулы _Calc вызывает действия (1б) со всеми вытекающими последствиями. При этом в любом случае последующие за этой операцией формулы и _Calc НЕ выполняются аналогично _Skip. Однако при этом естественно отсутствует переход вниз (по иерархии) по УКС R-значения, указываемого исходным V-значением (до операции a++) 'a', т.е. пропускается ветвь (поддерево) с корнем в 'a'

10) Аналогично *Row (п.4.1.2) используются регистры $S и $n. Дополнительно вводятся, как и $n автоматически формируемые регистры $l

  • число элементов в стеке (уровней) и $i - значение индекса V-значения вершины стека

4.2. Управление потоками вне функций


Собственно, это управление реализуется примитивами настройки _Out, _Chanal и др. (р.4), включаемыми в состав аргументов функции и вместе с тем стандартным образом вне зависимости от выполняемых операций (встроенной МП) этой функции.Эти примитивы являются "прозрачными" аргументами для функции: могут размещаться в любом порядке среди прочих ее аргументов

4.2.1. Контроль и преобразование входных потоков


Эти операции синтаксически определяются и организуется также, как и в случае параметров функции (п.3.4.1.2):

 <Имя входного потока>:<операции>,{<Имя входного потока>:<операции>}

Отличие состоит в следующем:

1) Примитив _Par НЕ используется: только его аргументы (2) в качестве прозрачных аргументов функции

2) Вместо имени параметра используется имя a, b, c, ... формирующего поток входа (аргумента) функции, определяемое в порядке их следования слева направо в слое аргументов

3) Дополнительно вводится "собственно операция" _Skip, организующая пропуск (игнорирование функцией) элемента входного потока (он НЕ принимается на обработку), и _End, прерывающая соответствующий поток с формированием признака завершения потока (элемент без свойств).

4) _If(<условие>) или _if(<условие>) вызывает операцию _Skip (по умолчанию) при НЕвыполнении условия: значение регистра '!' или '.' не отвечает ни одному из "Свойств" условия. Иначе выполняется операция _Go

5) Анализ и, возможно, операции (ряд операций) повторяются для каждого очередного элемента входного потока с указанным именем (имя-индекс аргумента с операциями). Значение этого элемента с его свойствами, включая совпадающее с именем входного потока дополнительное свойство, помещаются в регистр '!' к началу выполнения операций. Полученное в результате вычислений (возможно исходное без изменений) значение регистра '!' передается на обработку функции, если ранее не бала выполнена одна из операций _Skip, _End или _Break

6) По окончании потока признак завершения потока обрабатывается рассматриваемыми операциями как обычный элемент без свойств (%%).

7) В формулах качестве операнда может использоваться регистр $S (сумматор), $i к-во поступивших и $n - к-во принятых на обработку элементов потока, в отличие от прочих регистров сохраняющие свое значение при переходе от одного элемента входного потока к следующему (его обработке). Исходное его значение регистров равно 0 к началу поступления потока. Значение $S от элемента потока корректирует здесь (операции) сам пользователь, а значение $i и $n автоматически увеличивается на 1 для очередного, соотвественно, поступившего и принятого (переданного функции) на обработку элемента и НЕ может быть изменено. Значения этих регистров можно использовать как для формирования очередного значения (регистр '!'), передаваемого на обработку, так значение по завершению (5) обработки потока для выдачи дополнительно на выход функции итогов по входному потоку вместе (не обязательно) с дополнительным свойством '!' (Итог)

8) Принятый на обработку элемент (копия атома, R-или V-значения) сохраняется и может быть использован в в качестве операнда $e в формулах обработки следующего элемента потока. Исходное (до принятия первого элемента) значение $e нет имеет свойств (%%). Корректировка $e, как и $i и $n НЕ допускается

9) Как и ранее (п.3.4.1.2) в качестве операнда в формулах можно использовать имена параметров функции.

Согласно (5) операции могут подменить принятый элемент потока - регистр '!' (включая код завершения) вычисленным из него или без него другим значением, например:

  a:{_If(%*0%,`0->$S`),_If(%~%,`$S++`,_Skip),`$S(%.9!%)->!`}

В этом примере для начального элемента потока в регистр $S потока помещается 0: в этой операции вообще говоря нет смысла, ибо Регистр $S к началу поступления потока по умолчанию всегда устанавливается в 0. Если это НЕ окончание потока (%~% - есть какие-то свойства), то значение регистра $S увеличивается на 1 ($S++) и операция _Skip организует пропуск принятого элемента в потоке. Иначе (завершение потока

  • элемент без свойств - %%) выполняется последняя операция (формула), замещающая этот элемент '!' (код завершения) значением $S -

числом элементов в потоке, пополняя его свойством %!% (итог по потоку).

4.2.2. Обработка элементов выходного потока функции

Синтаксис:

	Out:<операции>						(4-1)

Обработка элементов формируемых функцией на ее синтаксически определяемом (главном) выходе выполняется идентично дополнительным ее выходам, устанавливаемым примитивом _Out (п.4.2.4). Более того, эту обработку можно объединить с обработкой по дополнительным выходам, включив (4-1) в состав параметров примитива _Out (п.4.2.3). Понятно, что имя_индекс Out нельзя использовать в качестве имени параметра функции или канала

  И в заключение еще простейшие примеры с обработкой выхода генератора *Sel по п 4.1.1:

  Выборка из слоя подпространства с именем X V-значений элементов
  с атомами - целыми положительными: 

   *Sel(X,Out:{_If(%.9+%,_Go),_Skip}	– с полным определением условия
				  выбора и операций

   *Sel(X,Out:_If(%.9+%) – то же, но короче согласно (4)
 
   *Sel(X,Out:%.9+%)	 – то же, но еще короче согласно п.3.4.1.2(5)

   *Sel(X,Out:%V|.9+%)   – выбрать V-значения элементов с 
			   именами-индексами



4.2.3 Дополнительные выходы функции

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

  Синтаксис:
   _Out(<Имя выхода>:<операции>,{<Имя выхода>:<операции>})	(4-2)

Отличие состоит лишь в том, что:

1) Обрабатывается (регистр '!' в формулах) элемент не входного потока, а очередной элемент, формируемый функцией и отправляемый (копии атома, R- или V-значения) на все выходы, включая главный. И точно также используются собственный регистры $S, $i и $n для потока формируемых на каждом выходе (главный и дополнительный) данных. Аналогично $e определяет предыдущий переданный на выход функции элемент

2) По окончании работы функции на выходы поступает признак завершения - элемент без свойств (%%) собственно так, как и случае обработки входного потока

3) _Out:(Out:<Операции>) эквивалентно Out:<Операции>, что короче и понятнее (см. примеры п.4.2.2).

Внимание! В силу п.4.2.2 имя Out определяет обработку элементов главного выхода функции и потому НЕ может быть использовано в качестве имени канала(п.4.2.4) или параметра функции

4.2.4 Канал на входе функции

 <Имя[-индекс] канала>:_Сhanal>
   %.|%

– в качестве аргумента любой функции объявляет ее вход, связываемый с одноименными дополнительными выходами (п.4.2.3) других функций в том же выражении, объявленными примитивом _Out. – С этих выходов поступают элементы на вход с _Chanal (слияние потоков). – Примитив _Chanal определяется только на входах функций, допускающих обрабатываемые ими потоки. При этом _Chanal и связываемые с ним выходы _Out должны находится (а) в одной ветке дерева выражения (СА), исполняемого функцией $Eval (б) в отсутствие нахождения _Chanal и одноименного _Out на маршруте от корня (основания) этой ветки вниз по уровням иерархии.
  В слое аргументов функции может быть несколько каналов и понятно с уникальными в пределах слоя именами, ибо это имена-индексы. Эти имена уникальны в пределах выражения, исполняемого $Eval, и могут быть практически любыми и даже совпадающие с именами функций, определяемых пользователем и даже с параметрами встроенных функций того же выражения

P.S. Нетрудно догадаться, что средства п.4.2.2 - п.4.2.4 позволяют организовать разделение одного потока на несколько других, например, по составу свойств их элементов - фактически реализовать сепаратор

4.2.5 Делитель главного выхода функции

Выходной поток функции можно распределять по различным каналам (п.4.2.4), включив в слой ее аргументов примитив ("прозрачный" аргумент):

	_Del(<Направление>{,<Направление>})

	<Направление>::= <Имя канала> | Out | <Неопределенный элемент [#]> 

Элементы выходного потока функции будут в порядке их очередности направляться на эти Направления в порядке их определения слева направо среди аргументов _Del и затем циклически снова в том же поряде от 1-го слева до последнего справа. В отсутствие указанных именами каналов (п.4.2.4) или неопределенных (#) "Направлений" соответствующие элементы потока попросту теряются. В случае направления Out элемент как обычно поступает на главный Выход функции

	*Num(5,From:1,_Del(Out,) - генерирует 1, 3, 5 (нечетные)
	*Num(5,From:1,_Del(#,Out) - генерирует 2, 4   (четные)
	*Num(9,From:1,_Del(#,,Out) - генерирует 3, 6, 9   (каждый 3-й от 1 до 9)

4.3. Методы Обработки потоков функциями

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

4.3.1. Никакой обработки

Это единственная функция $NoOut, которая игнорирует входные потоки в любом количестве, как и любые собственные параметры, ничего не выдает на собственный главный (синтаксический определяемый) выход, блокирует определение средства по п.4.2.1-3. При этом эта ничего эта не делающая функция создает следующие выгоды:

1) Все ее аргументы (выражения) функционируют совершенно независимо друг от друга, если, конечно, не связываются между собой каналами (Out->Chanal)

2) $NoOut может использоваться в качестве (и не одного) прозрачного аргумента любой функции, работающего независимо от прочих аргументов той же функции и не влияющего на результат ее вычислений, опять-таки если непрозрачные аргументы функции НЕ связаны каналами с аргументами самих прозрачных $NoOut.

3) Более того, в этом случае прозрачный аргумент $NoOut НЕ влияет и на время вычислений функции с таким аргументом: по завершении вычислений ветка СА с вершиной (основание) $NoOut выделяется в автономную часть СА и продолжает (аргументы самой $NoOut) вычисления, а выражение с функцией, содержащей аргумент $NoOut, завершает вычисление и удаляется из СА

4.3.2. Синхронная обработка нескольких потоков данных

Эта обработка производится единственной функцией $Sync посредством рассматриваемых здесь средств ее настройки, позволяющих ввести встроенные макроопределения, а также пользователю собственные макроопределения, реализуемые в СА через посредство $Sync (и $Eval, р.10). Центральным понятием здесь является "кортеж" - набор очередных элементов, поступивших по одному из всех входных потоков (входов) функции. Элементы кортежа идентифицируются идентично соответствующим входам функции слева направо: a, b, c,..., z, т.е. максимальное количество таких входов функции и, соответственно, размера кортежа - 26. По исчерпании (окончании) одного из потоков значение его одноименного элемента в очередном кортеже сохраняется из предыдущего кортежа, т.е. это последний элемент завершенного потока. По завершению всех входных потоков завершается и работа функции с удалением соответствующей ей ветки (поддерева) СА.

Обработка кортежей производится средствами, сходными с уже рассмотренными для входных (п.4.2.1) и выходных (п.4.2.3) потоков. Отличие состоит в следующем:

1) Операции или их ряд (в {}) вводятся непосредственно, как "прозрачные" аргументы функции. При этом помимо обычного вида _If с условием

  • свойствами регистра '!' этот примитив может иметь и более сложный вид:

  _If(<Имя входного потока>:<условие>{,<Имя входного потока>:<условие>}	(4-1)
					[,<операция>])
  <условие>::= <Свойства> | (<Свойства>{,<Свойства>})

Согласно синтаксису структуры "имя входного потока" (a-z) является именем-индексом и потому уникально в пределах слоя аргументов примитива _If. Помещаемый в кортеж элемент этого потока должен соответствовать - иметь свойства, указанные в одном из атомов "Свойства", указанных для этого элемента. Напомним, что такую проверку вне зависимости от значений элементов прочих входных потоков можно выполнить при обработке входного потока (п.4.2.1). Однако дополнительная версия _If требует одновременного соответствия элементов различных потоков (кортежа) определенным условиям (наличию определенных свойств), при котором по умолчанию "собственно операции" понимается _Go.

2) Исходное значение регистра '!' (результат вычислений - обработки очередного кортежа) к началу обработки кортежа устанавливается равным копии значения параметра From функции, по умолчанию пустой слой () %~.,0%.

3) В качестве операндов операций в формуле дополнительно используются имена (a,b, c,...) элементов кортежа (входов функции), а также '^' - ссылка на элемент кортежа, определяющая значение этого элемента и его свойства так же, как и при обращении к нему по имени. В начале обработки кортежа эта ссылка устанаваливается на элемент 'a' кортежа. НЕ допускается изменение значений и свойств элементов кортежа непосредственно или через посредство ссылки '^'. Существуют (р.5) операции _Calc (р.5) по изменению - перемещению этой ссылки по элементам кортежа

4) Описание свойств элемента кортежа предшествует в списке "Свойства"прочим его общим свойствам - атом(%\%), V- или R-значение: сначала в качестве свойства указывается имя (3) элемента в кортеже, которое может сопровождаться свойством '^', если этот элемент повторяется из предыдущего обрабатываемого кортежа (завершен соответствующий входной поток)

5) Формула здесь имеет внутреннюю (внутри ограничивающих ее символов ``) структуру:

  [<цикл>]<операция _Calc,[п.5.2]>{,<операция _Calc>}
  <цикл>::= <По элементам кортежа от 'a' к 'z'>
			[ *> ]
  <цикл>::= <По элементам кортежа от 'z' к 'a'>
			[ *< ]

Начинающаяся '*' формула повторяется поочередно (цикл) для каждого элемента кортежа поочередно выбираемых слева направо (*>

  • от 'a' к 'z'), либо справа налево (*> - от 'z' к 'a') налево с автоматической установкой в начале очередного цикла ссылки '^'

на этот элемент

6) Регистр $S определяется как сумматор по результатам вычислений каждого принятого кортежа и его исходное значение определяется стандартным параметром Sum функции (0 - по умолчанию)

7) По умолчанию (в отсутствие) формул при наличии или в отсутствие аргументов _If функция $Sync фактически в СА реализуется как:

   $Sync(<входной поток>{,<входной поток>},_If(%~%,`*>!+=^%@%`))

Расшифруем действие этого примитива:

а) В силу (2) в начале обработки каждого кортежа в регистр '!' помещается пустой слой ().

8) При наличии у значения регистра '!' каких-либо (любых) свойств (%~%) формула организует в цикле '*>' по элементам a, b, ... кортежа слева направо по входам функции) языком АЛГОЛа выполнение следующей за ней операции (+=)

  ! := ! + <текущий элемент кортежа[ - ссылка '^' _Calc]>

Согласно р.5 эта операция (+=) пополняет слой '!' очередным элементом (по ссылке '^') кортежа, при необходимости приводимым к R-значению (требуемое свойство %@% справа от второго операнда '^'). Это свойство может уточнять и часть используемого элемента: атом (%.%) или слой (%,%) или оба вместе (%.,%).

Примечание: В данном случае в результате обработки каждого кортежа формируется слой из R-значений его элементов в порядке их следования - потоковых входов функции за вычетом определяемых _Scale (см. далее).

9) Завершение операций функции $Sync определяется исходным значением регистра '!' без свойств (%%) и аналогичными значениями элементов кортежа. Досрочно это действие с закрытием всех входов функции (прерыванием входных потоков) может быть вызвано и операцией _End. При этом операции обработки фактически отсутствующего кортежа повторяются и здесь может быть передано на выход (регистр '!') итоговое, возможно, скорректированное значение итогов в $S или вычисленное из $S и др.регистров

10) Аналогично входным и выходным потокам вводятся автоматически ведущиеся счетчики $i и $n -, соответственно, число поступивших и принятых к обработке кортежей

11) В качестве единственного аргумента и помимо рассматриваемых операций в состав аргументов может быть введена версия _Scale примитива _If в форме (4-1) без "операции", причем в качестве единственного аргумента функции. Вне зависимости от размещения этого аргумента и операций, включая _If, при получении очередного кортежа вначале аналогично (4-1) проверяется соответствие его элементов соответствующим условиям в _Scale. И лишь при соответствии этих условий из кортежа удаляются перечисленные в _Scale элементы и отсчет оставшихся в кортеже элементов начинается заново слева направо последовательно, как 'a', 'b', 'c', ... . Таким образом организуется своеобразная логическая шкала или синхропотоки, отбирающие данные - кортежи для обработки, но непосредственно не входящие в обрабатываемые кортежи.

  Внимание! По исчерпании какого-либо входного потока в последующих кортежах используется его элемент, принятый последним по требованиям _If и/или _Scale.

Примечание: _Scale и _If с операциями _Go, _Skip и _Break можно использовать при синхронной обработке потоков выражений и данных функцией $Eval (р.6)

4.3.2.1. Встроенные макроопределения наcтройкой синхронной обработки

Отметим заранее, что в приводимые здесь макроопределения - синтаксически идентичные функциям можно ввести (в состав их аргументов) дополнительные выходы, каналы, преобразование и обработку входных (п.4.2.1) и выходных (п.4.2.3) потоков и даже _Scale с дополнительными входными потоками (синхропотоками), если конечно _Scale отсутствует в реализации макроопределения. При этом эти аргументы (средства) будут перенесены в том же виде в структуру функции _Sync, разворачиваемую вместе с операциями (1) в СА. Более того в них можно вводить и операции по п.4.3.2(1-9), которые в реализации макроопределения (СА) включаются в конец уже определенного там ряда операций. Потому ниже эти аргументы опускаются:

   $Trans(<[обрабатываемый ]поток>,<поток[ Свойств]>)

В СА фактически реализует следующую функцию:

  $Sync(<обрабатываемый поток>,<поток Свойств>,_If(%~%,`a<=b%:%;.->!`))

Если '!' НЕ содержит код завершения операции - есть какие-либо свойства (%~%), то операция <= калькулятора _Calc приводит элемент a кортежа к виду , определяемого значением (Свойства </b>%:%</b>) элемента b и результат приведения (регистр '.') помещает (->) в регистр ! (выход функции).

   $Move(<поток R_значений>,<поток V-значений>,)

В СА фактически реализует следующую функцию:

  $Sync(<поток R_значений>,<поток V-значений>,
	{_If(b:%&%,`a%@%=>b;b->!`),_Skip})

Аргумент _If пропускает (_Skip) кортеж, если элемент 'b' НЕ является V-значением, иначе операция '=>' (п.5.3) калькулятора _Calc по этому V-значению производит запись R-значения элемента 'a' кортежа, при необходимости приводя его к этому R-значению (свойство %@% справа от 'a'). Следующая операция '->'помещает b (V-значение) в регистр ! (результат операции)

   $Copy(<поток R-значений>)

В СА фактически реализуется следующим выражением:

  $Sync(<поток R_значений>,{_If(a:%\%,`a->!`,_Go),`!<-a%@%`})

Аргумент _If в случае Атома - элемента 'a' (%\%) помещает его в регистр '!' (результат операции) и завершает (_Go) операции. Иначе операция '<-' приведенный к R-значению элемент 'a' (a%@%) - структуру операция (<-, р.5) копирует по всем уровням ее иерархии, получая копию той же структуры в Блоках Памяти (БП) с уникальными ссылками УКА и УКС на всех уровнях иерархии. УКА и УКС корня полученной копии структуры помещаются в регистр '!'.

   $ToLay(<поток слоев>,<поток значений>,)

В СА реализуется как:

  $Sync(<поток слоев>,<поток значений>,_If(%~%,`a%&~.,%->!;!+=b%@%`))

Здесь каждый слой R-значения элемента a кортежа (слой по УКС) пополняется (формула) R-значением элемента b. Вначале (1-я операция ->) в регистр '!' помещает R-значение слоя с УКА=0 и не УКС<>0. В отсутствие исходного слоя он формируется автоматическим выделением свободного и пустого БП. Понятно, что по исходному V-значению a определяется его R-значение. Следующая операция '+=' слой '!' (выход функции) пополняет R-значением b.

 Пример:
   $ToLay(*Stream("A"("B"),"C"("D")),*Num(3)) формирует на выходе
 	поток "A"("B",0),"C"("D",1,2)

   $Sel(<поток слоев>,<поток индексов>,)

В СА реализуется как:

  $Sync(<поток слоев>,<поток индексов>,
	{_If(a:%,%,b:(%.9+~,%,%.|~,%),`a%&~.,%&b;.%&@%->!`,_Go),_Skip})

Операции (формула и _Go) выполняются лишь (_If), если элемент 'a' имеет УКС<>0 (слой), а элемент 'b' является индексом целым или именем-индексом. Иначе кортеж пропускается (_Skip). Операции формулы:

1) Из УКС слоя - элемента a и индекса b (индекса - целого или имени-индекса) операция '&' формирует V-значение '.'.

2) V-значение регистра '!' (выход для обрабатываемого кортежа) приводится к виду безусловно имеющему R-значение, если такое отсутствует: слой по УКС R-значения пополняется достаточным количеством неопределенных элементов (УКА=0, УКС=0)

 Пример:

	 $Sel(*Sel(< R-значение[слоя(%~.,%)]>,Out:`!%@%->!`),0) 

*Sel генерирует V-значения исходного R-значения слоя (п.4.1.3) и операция '->' на главном выходе Out *Sel выделяет для каждого этого V-значения указываемое им R-значение. Наконец, функция $Sel из УКС этих R-значений и 0 создает 1-й (0-й) столбец матрицы, возможно, и с неопределенными элементами, если такие отсутствуют. Меняя в выражении 0 на 1, 2 и т.д., получим 2-й, 3-й столбец и т.д.

4.3.3. Асинхронная обработка потоков

Эту обработку выполняет функция $Async, переправляющая любой поступивший на ее вход элемент потока на выход (результат). Есть возможность обработки поступающего к функции (до передачи на выход) очередного с любого ее входа элемента дополнительно вводимыми операциями, причем практически идентично каждому из этих входных потоков (п.4.2.1), включая операции с _If и формулами _Calc. Различие состоит лишь в следующем:

1) Последовательности операций (<операции>, п.3.4.1.2 и п.4.2.1) НЕ предшествует имя входного потока как имя_индекс: операции _Go, _Trans, _If и др., включая ряд операций в скобках {} являются непосредственными аргументами функции $Sync

2) Как и в случае входного потока регистр '!' содержит элемент входного, но теперь любого потока и потому сопровождается дополнительным свойством - именем этого потока (a-z)

3) Регистр $S сохраняется и ведется единым по всем входным потокам функции $Sync и исходным определяется как стандартный параметр Sum - по умолчанию является тем же 0

4) Регистры $n (число уже принятых и обработанных элементов) и $e (последний из них) ведутся по поступающим элементам со всех входов

5) Свойство %*0% определяет вообще первым поступивший элемент (по всем входам)

6) По окончании всех входных потоков на "обработку" поступает признак завершения потока без свойств (%%). Этот признак может быть сформирован собственно операцией _End или _Break и обработан средствами (1)-(4), как и прочие элементы

7) Результат обработки '!' поступает на выход функции, если операции (1) НЕ блокируют (_Skip, _End, _Break) это действие.

4.3.3.1. Обработка структуры потоком индексов. Индексирование структуры

Эту обработку производит встроенное в ФПМ макроопределение:

 
  $In([Struct:]<структура>,<Поток индексов>[,Deep:<глубина>])

$In обрабатывает поток индексов и на его основе формирует соответствующий путь (поток V-значений проходимых вершин - узлов) на структуре Struct от ее корня вглубь по иерархии с числом уровней , НЕ превышающей значение параметра Deep (26 по умолчанию), при этом возможно автоматически расширяет структуру аналогично языку Perl для матриц. Это макроопределение в СА фактически реализуется функцией $Async с использованием рассмотренных выше средств _Calc:

$Async(Struct:<структура>,<Поток индексов>,Deep:<глубина>,
	_Par(Deep:{_If(%~.9+~,%,_Break),`26-!`,_if(%~.9+%,`26->!`),_If(%.90%,`!++`),_Break}
	     Struct:`!%@%->Sum`),
	a:{_If(%%,_Break;),`Deep-$n;--`,_if(%.9~+%,_End);_If((%.9+%,%.9|%),_Go),_End)}
	`$S%~.,%&!;.%&@%->!;!%@%->$S`)

1) Примитив _Par анализирует параметр Deep: Если он не является атомом - положительным целым, то работа функции прерывается (_Break). Иначе если его значение превышает 26, то он принимается равным 26. При равенстве Deep=0 он увеличивается на 1 (!++). Здесь же (второй аргумент примитива _Par) приводит аргумент Struct (регистр '!') к R-значению и определяет его в качестве параметра Sum


2) Вслед за аргументом _Par следуют операции обработки очередного поступающего индекса (элемента 'a') из потока: При окончании (%%) потока выполнение функции прерывается (_Break). Иначе в случае достижения $n (числа принятых индексов из потока) значения Deep или если принятый по входу 'a' элемент НЕ является целым (%.9+%) или именем-индексом (%.9|%), то поток прерывается и формируется признак окончания потока с отутствующими свойствами (%%), который также обрабатывается здесь же рассматриваемыми операциями обработки элемента 'a'

Примечание: При подаче на функции (регистр '!') элемента без свойств (%% - конец потока) действие аналогично операции _End с тем отличием, что рассматриваемые операции НЕ будут повторно запущены для этого "элемента"

3) Единственной операцией обработки является формула _Calc - последний аргумент функции $Async:

  • Вначале из слоя (%~.,%) сумматора (регистра) $S (поначалу с исходным параметром Sum ввиду (1)) и очередного индекса (регистр '!')

потока индексов операция '&' формирует V-значение в регистре '.'.

  • Следующая операция '->' это V-значение приводит к безусловно указывающему R-значение (%&@%), при необходимости (УКС=0) открывая

пустой слой - БП с УКС<>0 и пополняя слой необходимым мимнимальным числом неопределенных элементов в отсутствие в слое элемента с указываемым индексом 'a' (теперь в V-значении). Уточненное (необязательно) V-значение помещается в регистр '!' - на выход функции

  • Следующая операция '->' R-значение, указываемое V-значением выхода функции, помещает в регистр $S

Операции (3) повторяются пока не будет исчерпан поток индексов или не прерван операциями (2) при его обработке

4.3.4. Слияние потоков

$Merge(<поток>{,<поток>})

  • функция принимает параллельно по одному элементу каждого входного незавершенного потока. Получив все такие элементы (по одному)

сравнивает между собой: минимальные (и равные) по значению элементы этого набора (кортежа) в порядке (!) их поступления по одному отправляет на свои выходы, одновременно открывая входы, с которых они поступили для приема следующих элементов по одному. Затем операция сравнения элементов вновь образованного кортежа и отправка минимальных на выход повторяется.

Внимание! Понятно, что в такой операции предполагается упорядочение каждого из входных потоков в порядке возрастания значений их элементов. Напомним (п.4.1.1), что генератор *Sel формирует такие потоки и аналогично $Merge выполняет упорядочение элементов сравнением атомов, задаваемых (элемент) непосредственно в потоке или по УКА R-значения, возможно, в свою очередь определяемого (указываемого) V-значением. Сравнение атомов соответствует операции '=' калькулятора _Calc (р.5), согласно которой числа - атомы сравниваются их значениями с учетом знака (+ или -), строки и имена лексикографически и т.д.

Используемую по умолчанию обеими функциями *Sel и $Merge операцию '=' сравнения двух элементов и выбор "минимального" из них (а точнее, предпочтительного) можно изменить посредством все тех же операций _If (_if) и прочих, включая формулы _Calc, рассмотренных ранее при обработке кортежей. В этом случае обе эти функции (*Sel и $Merge) сравнение очередных двух элементов (слоя или кортежа из элементов потоков) передают операциям в виде кортежа из элементов 'a' и 'b', возможно и совпадающих. Задача операций: выбрать один из элементов или оба, как предпочтительные в порядке реализуемой каждой из функций (*Sel или $Merge) сортировки. При выборе обоих эти два элемента считаются равными. Еще раз обратим внимание, что каждая из функций *Sel и $Merge, реализуя операции сортировки, соответственно, слоя и кортежа (см. выше) многократно обращаются к вводимым ниже в качестве их "прозрачных" аргументам операциям

Особенности операций _Calc в реализации сравнения двух элементов (V-значений слоя операции *Sel) или по одному из двух любых входных потоков $Merge:

1) Допускается форма (4-1) _If, в которой (аргументы) вместо имен входных потоков используются имена 'a' и 'b' сравниваемых элементов

2) Регистр '!' в исходном (до операций) состоянии содержит неопределенное значение (#) и его значение к концу выполнения операций никак НЕ влияет на их результат

3) Регистр $S к началу вычислений функции, как обычно, принимает значение стандартного параметра Sum функции (0 - по умолчанию) и сохраняет свое значение при каждом переходе от очередного цикла операций (сравнения элементов 'a' и 'b') к следующему.

4) Региcтры $n определяет число уже завершенных циклов операций сравнения 'a' и 'b'.

5) Регистр $l здесь НЕ формируется и содержит неопределенное (#) значение

6) Выбор предпочтительного ("минимального") среди двух 'a' и 'b' или обоих производится установкой свойства '^' формулами _Calc, например, операцией a%^% (b%^%). В от отсутствие такого выбора, как и при выборе обоих, оба элемента считаются равными вне зависимости от их фактических значений.

4.4. ФПМ как суммирующая машина

Напомним, что по умолчанию или посредством операций калькулятора _Calc, в процессе обработки функцией (п.4.3), а также на каждом ее выходе ведется отдельный регистр $S - "Сумматор", содержимое которого, вообще говоря, является произвольной иерархической структурой, определяемой этими операциями. По окончании обработки (п.4.3) исходных данных функции или потока на любом из выходов функции значение $S, дополненное свойством '!' (итог) можно отправить на общий с выходным потоком или отдельный выход (п.4.2.3), где, используя _Chanal (п.4.2.4), организовать его перемещение в слой подпространства (сохранить). Однако эту процедуру можно упростить, включив в операции _Calc еще одну:

   _Sum(<имя подпространства[п.2.6]>)

Особенность этой операции состоит в том, что ее выполнение откладывается до завершения работы функции (п.4.3) или выходного потока (п.4.2.3) и операция состоит в том, что содержимое соотвеnствующего (операций функции или выходного потока) регистра $S замещает значение указанного именем подпространства, в отсутствие которого это подпространство автоматически создается

Примечание: В случае операций вычисления функции примитив _Sum можно ввести непосредственно в состав "прозрачных" аргументов функции вместо предложенного выше введения в состав операций. Это позволяет использовать _Sum для той же цели к качестве аргумента встроенного макроопределения (п.4.1.2.2, п.4.3.3.1), если, конечно, реализация которого в СА ведет подсчет $S, например:

	*Num(5,_Sum(X)) генерирует 0, 1, 2, 3, 4

В этом случае подпространство X получит значение $S=0+1+2+3+4, т.е 10

4.5. Статические и Динамические свойства элементов данных


1) Напомним (р.2), что статические свойства элемента определяют:

  а) Отношение элемента к потоку (%[~]*%, %*0%) или положению в кортеже (%<Имя элемента>[^]%)
  б) Код элемента - атом явно значением вне структуры (%\%), V-(%&%, %&@%) или R-(%@%) - значение, неопределенное значение (%#%)
  в) Наличие и характеристики атома (%[~].[<тип>]%) заданного явно или по ссылке УКА в R-значении
  г) Наличие и характеристики слоя (%[~],<тип>%) по ссылке УКС в R-значении

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

2) Наряду со статическими свойствами определяются динамические свойства, которые можно изменять без изменения структуры элемента и его отношения к потоку или кортежу. Собственно сюда входят все символы, включая спецсимволы (<,=,>) и даже код защиты '?' и рекомендованный в примерах код '!'(свойство 'Итог'), цифры от 3 до 8, а также симолы A - Z латинского алфавита. Значение этих свойств определяется самим пользователем и они, определенные для элемента в произвольном порядке, рассматриваются как множество из не повторяющихся кодов (символов), указываемое отдельно или вместе с (1а) - (1б) и в последнем случае указываются ранее в атоме "Свойства", причем в любом порядке. Как и любому статическому свойству динамическому может предшествовать код '~', точно также отрицающий наличие этого свойства при отборе элемента в потоке или кортеже. Однако теперь без изменения физических характеристик элемента ему можно присвоить одно или более динамических свойств или удалить их, если, конечно, они там есть:

Примеры в формулах:

1) `!%!%` - содержимое регистр '!' пополняется свойством '!', 
	    если ранее оно там отсутствует

2) `!%!.~,%;->!` - аналогично (1) и дополнительно из К-значения '!'  
		   удаляется слой, если он там есть (УКС<>0)

3) `!%~!%` 	 - у содержимого регистра '!' удаляется свойство '!', 
		   если ранее оно там было

Непосредственно у операндов операций _Calc, кроме '.', можно изменить динамические свойства только в отсутствие рядом с ним статических свойств - примеры (1) и (3). Иначе результат приведения операнда к требуемым свойствам помещается в регистр '.'. Более того, динамические свойства способом (1) и (3) можно вводить и изменять даже у операндов, НЕ допускающих изменения их структуры и статических свойств</b>

Внимание! Исключение составляет свойство '?' защиты атома или слоя, устанавливаемое отдельно для каждого из них и размещаемое справа от определения атома (%.?%) и/или слоя (%,?%)

Примечание! В приведенных примерах (1)-(3) первая (возможно, единственная) операция состоит из одного операнда (нет кода операции) и только в случае (2) это вызывает операцию помещения ее результата в регистр '.'. При наличии кода операции ее операнды могут сопровождаться справа свойствами, к которым предварительно должен быть предварительно приведен операнд. В этом случае сам операнд физически НЕ приводится к этому свойству, а готовится лишь его временная копия (аналогично регистру '.'), отвечающая этим свойствам.

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




Приложение 1. Используемые сокращения:

ФПМ	- Функциональная Потоковая Машина
р.4	- раздел 4 проекта ФПМ
п.2.3	- пункт 3 раздела 2

СА	- Структура Активаций – реализующий выражение языка (суперпозицию
 	  функций) коллектив соответствующим образом связанных микро-ЭВМ, 
 	  каждая из которых  реализует отдельную функцию или калькулятор
	  _Calc

ДРП	- динамически распределяемая память, над которой функуционируют 
 	  микро-ЭВМ СА

БП	- блок ДРП, выделяемый под атом или слой структуры
УКА	- указатель (ссылка на БП) атома (п.2.3)
УКС	- указатель (ссылка на БП)  слоя (р.2)