lecture12.ppt
- Количество слайдов: 39
04. 12. 13 Лекция 12 Предикатное программирование 8. Язык, технология и методы верификации других классов программ (прод. ) Класс реактивных систем (прод. ) Алгоритм Петерсона взаимного исключения доступа Темпоральная логика Спецификация скелета радиус-сервера Сеанс исходящего звонка Свойства спецификации сеанса Реализация скелета радиус-сервера Реализация для ненадежных каналов Процессорная спецификация языка исчисления вычислимых предикатов
Протокол рукопожатия s u a S b M 1 M 2 c R r d Передатчик S Приемник R Ненадежные каналы потеря сообщений Медиумы M 1, M 2 process GS { S || M 1 || R || M 2 } spec GS = s? r! u! Протокол
Протокол рукопожатия message a, b bool sa, sb Указатели текущего исполняемого действия: pc. S=s, pc. R=r list ({a}) qa = nil; list ({b}) qb = nil; process S(: #exit) { s: if (b) #exit if (sa) send a; #s } process R() { r: receive(a); if (sb) send b; #r } process Hand. Shake(: #exit) { S(: #exit) || R(: ) } состояние: ( qa, qb, sa, sb) начальное состояние qa=nil; qb=nil
process S(: #exit) { process R() { s: if (b) #exit r: receive(a); if (sa) send a; #s if (sb) send b; #r } } process SR() { //qa = [a+] эквивалентно qa != nil a 0: inv (qa, qb) = (nil, nil); s(sa: #a 1: sa #a 0) a 1: inv ([a+], nil); s #a 1 | r (sb & qa’=nil #a 2: sb & qa’!=nil #a 3 : sb & qa’=nil #a 0: sb & qa’!=nil #a 1) a 2: inv (nil, [b+]); s #exit | r (qa’=nil #a 2: qa’!=nil #a 3) a 3: inv ([a+], [b+]); s #exit | r (qa’=nil #a 2: qa’!=nil #a 3) } Учитывая, что действия a 2 и a 3 одинаковые, их можно объединить в одно: a 2: inv qb != nil; s #exit | r # a 2
[nil, nil] [a+, nil] [a*, b+] exit
Алгоритм Петерсона взаимного исключения доступа type PC = enum(0, 1, 2, 3, cs, 4); type PROC = enum(0, 1); PROC turn = 0; type FLAGS = array(PROC, bool); FLAGS flag = for(PROC i){false}; type PCS = array(PROC, PC); PCS pc = for(PROC i){0}; process Peterson(PROC a, b) { 0: flag[a] = true; 1: turn = b; 2: if (flag[b]) #3 else #cs; 3: if (turn = b) #2 else #cs; cs: skip; 4: flag[a] = false; #0 }
process main(); { Peterson(0, 1) || Peterson(1, 0) } Состояние: (flag[a], flag[b], turn, PC[a], PC[b]) Переменные состояния: (fa, fb, turn, pa, pb) process Pet(); { a 0: invariant (fa, fb, turn, pa, pb) = (f, f, *, 0, 0); 0 a | 0 b #b 1 a 1: inv (t, f, *, 1, 0) ; b 1: inv (f, t, *, 0, 1) ; 1 a | 0 b #c 0 0 a #c 0 | 1 b a 2: inv (t, f, b, 2, 0) ; b 2: inv (f, t, a, 0, 2) ; 2 a | 0 b #c 1 0 a #d 1 | 2 b a 3: inv (t, f, b, cs, 0) ; b 3: inv (f, t, a, 0, cs) ; csa | 0 b #f 5 0 a #e 5 | csb a 4: inv (t, f, b, 4, 0) ; b 4: inv (f, t, a, 0, 4) ; 4 a#a 0 | 0 b #f 4 0 a #e 4 | 4 b #a 0 a 5: inv (f, t, a, 0, 3) ; b 5: inv (t, f, b, 3, 0) ; ~a 5 0 a #d 2 | 3 b #b 2 3 a #a 2| 0 b #c 2
process Peterson(PROC a, b) { 0 a: flag[a] = true; 1 a: turn = b; 2 a: if (flag[b]) #3 else #csa; 3 a: if (turn = b) #2 else #csa; csa: skip; 4 a: flag[a] = false; #1 a process Peterson(PROC b, a) { 0 b: flag[b] = true; 1 b: turn = a; 2 b: if (flag[a]) #3 else #csb; 3 b: if (turn = a) #2 else #csb; csb: skip; 4 b: flag[b] = false; #1 b } c 0: inv (turn, pa, pb) = (*, 1, 1); 1 a | 1 b #d 1 c 1: inv (b, 2, 1) ; 2 a | 1 b #f 2 c 2: inv (b, 3, 1) ; 3 a #c 1 | 1 b #d 6 c 3: inv (a, cs, 2) ; csa | 2 b #d 8 c 4: inv (a, 4, 2) ; 4 a #b 2| 2 b c 5: inv (a, 4, 3) ; 4 a #a 5 | 3 b #c 4 d 1: inv (a, 1, 2) ; 1 a #e 2 | 2 b #d 2 d 2: inv (a, 1, 3) ; 1 a #c 6 | 3 b #d 1 d 3: inv (b, 2, cs) ; 2 a #c 8 | csb d 4: inv (b, 2, 4) ; 2 a | 4 b #a 2 d 5: inv (b, 3, 4) ; 3 a #d 4 | 4 b #b 5
process Peterson(PROC a, b) { 0 a: flag[a] = true; 1 a: turn = b; 2 a: if (flag[b]) #3 else #csa; 3 a: if (turn = b) #2 else #csa; csa: skip; 4 a: flag[a] = false; #1 a process Peterson(PROC b, a) { 0 b: flag[b] = true; 1 b: turn = a; 2 b: if (flag[a]) #3 else #csb; 3 b: if (turn = a) #2 else #csb; csb: skip; 4 b: flag[b] = false; #1 b } c 6: inv (b, 2, 3) ; 2 a | 3 b #d 3 c 7: inv (b, 3, 3) ; 3 a #c 6 | 3 b c 8: inv (b, 3, cs) ; 3 a #d 3 | csb #d 5 e 2: inv (b, 2, 2) ; 2 a | 2 b #c 6 e 3: inv (b, 3, 2) ; 3 a #e 2 | 2 b #c 7 e 4: inv (a, 1, 4) ; 1 a #d 4 | 4 b #a 1 e 5: inv (a, 1, cs) ; 1 a #d 3 | csb #e 4 d 6: inv (a, 3, 2) ; ~c 6 3 a #c 3 | 2 b d 7: inv (a, 3, 3) ; ~c 7 3 a #d 8 | 3 b #d 6 d 8: inv (a, cs, 3) ; ~c 8 csa #c 5 | 3 b #c 3 f 2: inv (a, 2, 2) ; ~ e 2 2 a #d 6 | 2 b f 3: inv (a, 2, 3) ; ~ e 3 2 a #d 7 | 3 b #f 2 f 4: inv (b, 4, 1) ; ~e 4 4 a#b 1 | 1 b #c 4 f 5: inv (b, cs, 1) ; ~e 5 csa #f 4 | 1 b #c 3
Темпоральная логика Классическая логика (propositional logic) – Примитивная модель истины: “черно-белая”модель, не существует степени уверенности - неуверенности, высказывания статичны, неизменны во времени – Пример - некоммутативность конъюнкции, A&B ≠B&A : • “Джону стало страшно и он убил” ⇐? ⇒ “Джон убил и ему стало страшно” • “Смит умер и его похоронили” ⇐? ⇒ “Смита похоронили и он умер” • “Джейн вышла замуж и родила ребенка” ⇐? ⇒ “Джейн родила ребенка и вышла замуж”
Определение Модальной логики – Модальность(от лат. modus – вид, способ, наклонение) –это категория, определяющая отношение высказывания к действительности (“необходимо, чтобы А”, “возможно, что А”, “когда-нибудь в будущем будет верно, что А”и т. п. ) – Модальная логика – любая формальная логическая система, в которой присутствуют модальные операторы Примеры модальных операторов: – М-“возможно, что” (Мр – “возможно, что р”) – L-“необходимо, что” (Lq – “q обязательно должно выполниться”) – F – “когда-нибудь в будущем будет верно, что. . . ” – G - “всегда в будущем будет верно, что. . . ” – P - “когда-то в прошлом было верно, что. . . ” Соотношения между модальностями: Мр ≡ ¬L¬р, Lр ≡ ¬M¬р, Fр ≡ ¬G¬р, Gр ≡ ¬F¬р
Динамически порождаемые процессы Создание и запуск нового процесса: new <имя процесса>(<параметры вызова>) Происходит создание объекта класса, в котором находится программа данного процесса (аналогично конструктору класса). Создается новый процесс и запускается на исполнение параллельно с текущим процессом, исполняющим данную конструкцию. Результат конструкции – порожденный объект.
Радиус-сервер интернет-телефонии Система интернет-телефонии (СИТ) внутренние и внешние абоненты, удаленные узлы, сеанс связи абонента и СИТ сеанс исходящего звонка сеанс внутреннего абонента сеанс входящего звонка сеанс внешнего абонента авторизация внутреннего абонента (номер + код), внешнего абонента (IP-адреса + пути к удаленному телефону) радиус-сервер (РС), биллинговый сервер (БС) СИТ РС БС
процесс = скелет + функциональное наполнение скелет действия и структуры данных, от которых зависит выбор следующего состояния Типовая схема взаимодействия Auth. Num() СИТ Auth. Num. Billing() РС БС Auth. Num. Reply(bool ответ) Auth. Num. Billing. Reply(bool ответ)
Спецификация скелета радиус-сервера. Множество сеансов type ID; // тип уникального идентификатора сеанса class SEANCE; { ID id; // идентификатора данного сеанса process сеанс. Входящего. Звонка 1(ID j); process сеанс. Входящего. Звонка 2(ID j); process сеанс. Исходящего. Звонка(ID j); } to be continued interface множество. Сеансов; { создать. Сеанс(ID j, SEANCE se); // в множество сеансов добавляется новый сеанс se с идентификатором j cеанс(ID j: SEANCE se); // в множестве сеансов находится сеанс se, соответствующий идентификатору j удалить. Сеанс(ID j); // из множества сеансов удаляется сеанс с идентификатором j }
Главный процесс радиус. Сервер process радиус. Сервер() { loop: обработка. Очередного. Сообщения( : #loop) } process обработка. Очередного. Сообщения( : #loop) { receive Auth. Incoming(ID j): { создать. Сеанс(j, new сеанс. Входящего. Звонка 1(j)) } else receive Auth. Incoming. Path(ID j): { создать. Сеанс(j, new сеанс. Входящего. Звонка 2(j)) } else receive Auth. Outgoing(ID j): { создать. Сеанс(j, new сеанс. Исходящего. Звонка(j)) } else receive Stop(ID j): сеанс(j) ! Stop( ) else receive Auth. Num(ID j): сеанс(j) ! Auth. Num( ) else receive Auth. Num. Billing. Reply(ID j, bool ответ): сеанс(j) ! Auth. Num. Billing. Reply (ответ) ………. . и т. д. , всего 15 сообщений #loop }
Сеанс входящего звонка process сеанс. Входящего. Звонка 1(ID id: #end) { авторизация. Внешнего. Номера( : #path : #stop); path: авторизация. Пути. Звонок( : #nextcall : #stop); nextcall: #stop stop: БС ! Stop. Billing(); удалить. Сеанс(id) #end } process сеанс. Входящего. Звонка 2(ID id: #end) { авторизация. Внешнего. Номера. Пути( : #call : #stop); call: сеанс. Звонка( : #nextcall : #stop); nextcall: #stop stop: БС ! Stop. Billing(); удалить. Сеанс(id) #end }
Авторизация внешнего абонента, номера и пути process авторизация. Внешнего. Номера( : #path : #stop) { авторизация. Внешнего( : #yes 1 : #stop); yes 1: авторизация. Номера( : #yes 2 : #no : #stop); yes 2: #path no: #stop } process авторизация. Внешнего. Номера. Пути( : #call : #stop) { авторизация. Внешнего( : #yes 1 : #stop); yes 1: авторизация. Номера( : #yes 2 : #no : #stop); yes 2: авторизация. Пути( : #yes 3 : #no : #stop); yes 3: #call no: #stop }
process авторизация. Внешнего( : #yes| #stop) { БС ! Auth. Incoming. Billing(); $s. Auth. Incoming: receive Auth. Incoming. Billing. Reply(bool ответ); СИТ ! Auth. Incoming. Reply(ответ); if (Stop() ответ) #stop else #yes } process авторизация. Номера( : #yes| #no| #stop) { БС ! Auth. Num. Billing(); $s. Auth. Num. Billing: receive Auth. Num. Billing. Reply(bool ответ); СИТ ! Auth. Num. Reply(ответ); if (Stop()) #stop else if (ответ) #yes else #no } process авторизация. Пути( : #yes| #no| #stop) { БС ! Auth. Path. Billing(); $s. Auth. Path. Billing: receive Auth. Path. Billing. Reply(bool ответ); СИТ ! Auth. Path. Reply(ответ); if (Stop()) #stop else if (ответ) #yes else #no }
Сеанс звонка process авторизация. Пути. Звонок( : #nextcall | #stop) { $s. Auth. Num: receive Auth. Path(): { авторизация. Пути( : #yes 2: #nextcall: #stop); yes 2: сеанс. Звонка( : #nextcall : #stop) } else receive Start. Call(): звонок( : #nextcall : #stop) else receive Stop(): #stop } process сеанс. Звонка( : #nextcall : #stop) { $s. Call: receive Start. Call(): звонок( : #nextcall : #stop) else receive Stop(): #stop } process звонок( : #nextcall : #stop) { $s. Start. Call: receive Start. Talk(): { $s. Talk: receive Stop. Talk(); $s. Stop. Talk: receive Stop. Call(); БС ! Call. Billing() } else receive Stop. Call(): БС ! Call. Billing(); if (Stop()) #stop else #nextcall }
Сеанс исходящего звонка process сеанс. Исходящего. Звонка(ID id: #end) { авторизация. Внутреннего. Абонента( : #key : #num : #stop); key: авторизация. По. Коду( : #key : #num : #stop); num: авторизация. Номера. Пути. Звонок( : #num : #stop); stop: БС ! Stop. Billing(); удалить. Сеанс(id) #end } process авторизация. Номера. Пути. Звонок( : #nextcall : #stop) { $s. Auth. Num. Path: receive Auth. Num(): { авторизация. Номера( : #yes 1 : #nextcall : #stop); yes 1: авторизация. Пути. Звонок( : #nextcall : #stop) } else receive Stop(): #stop }
Авторизация внутреннего абонента process авторизация. Внутреннего. Абонента( : #key : #num : #stop) { БС ! Auth. Outgoing. Billing(); $s. Auth: receive Auth. Outgoing. Billing. Reply(bool ответ); СИТ ! Auth. Outgoing. Reply(ответ); if (Stop()) #stop ; if (ответ) #num else #key } process авторизация. По. Коду( : #key : #num : #stop) { $s. Key: receive Key(): { БС ! Key. Billing(); $s. Key. Billing: receive Key. Billing. Reply(bool ответ); СИТ ! Key. Reply(ответ); if (Stop()) #stop ; if ( ответ) #key } else receive Stop(): #stop #num }
Свойства спецификации сеанса • • сообщение Stop() может придти в любой момент, но его обработка реализуется не всегда в порядке поступления остальные сообщения упорядочены Цепочки следования сообщений: Auth. Incoming. Path Start. Cal Start. Talk Stop. Call Stop Auth. Incoming Auth. Path Start. Call … Auth. Outgoing Key Auth. Num Auth. Path Start. Call … Правило: пока не завершена авторизация (посылкой ответного сообщения на СИТ) другие сообщения этого сеанса, в том числе сообщение Stop(), не обрабатываются. Вхождения сообщения Stop() в спецификации являются источником недетерминизма дедлок ?
Реализация скелета радиус-сервера Неэффективность: • использование параллельных процессов • блокировка исполнения на операторах receive Этап 1. Фиксация специальных внутренних состояний $s. Auth: state : = s. Auth; Этап 2. Вынос обработки сообщений Stop() type STATE = enum (s. Auth. Num, s. Call, s. Key, s. Auth. Num. Path, s. Auth. Incoming, s. Auth. Num. Billing, s. Auth. Path. Billing, s. Start. Call, s. Talk, s. Stop. Talk, s. Auth, s. Key. Billing); class SEANCE { STATE state; // текущее специальное состояние данного сеанса bool stop = false; // = true поступило сообщение Stop() для данного сеанса } to be continued
process обработка. Очередного. Сообщения( : #loop) { receive Auth. Incoming(ID j): ……………………… else receive Stop(ID j): // сеанс(j) ! Stop( ) { se = сеанс(j); if (se. state in {s. Auth. Num, s. Call, s. Key, s. Auth. Num. Path}) { БС ! Stop. Biling(); удалить. Сеанс(se. id) } else se. stop = true }; ! После этапа 2 порядок поступления сообщений в процесс сеанса радиус-сервера совпадает с порядком их обработки. Этап 3. Замена процесса сеанса на сопрограмму Специальное внутреннее состояние точка сопрограммного прерывания ! После этапа 3 всякий оператор receive выполняется без ожидания
Этап 4. Замена receive на if receive <сообщение 1>: <оператор1> receive else… receive else <сообщение. N>: <оператор. N>} if (<сообщение 1>) <оператор1> else if…else if (<сообщение. N>) <оператор. N> Этап 5. Замена создания параллельного процесса сеанса на непосредственный вызов процесса receive Auth. Incoming(ID j): { se= new SEANSE(j); создать. Сеанс(j, se); сеанс. Входящего. Звонка 1(j) } ! После этапа 5 нет параллельных процессов. Программа исполняется в сопрограммном режиме. Обработчик сообщения фрагмент программы, соответствующий обработке одного сообщения
Этап 6. Сборка обработчика из разных кусков сопрограммы На примере Auth. Incoming() и Auth. Path. Billing. Reply(). Auth. Incoming() БС ! Auth. Incoming. Billing(); $s. Auth. Incoming: Auth. Path. Billing. Reply() СИТ ! Auth. Path. Reply(ответ); if (Stop()) #stop else if (ответ) #yes else #no ; Необходимо продолжить для #yes и #no авторизация. Пути авторизация. Внешнего. Номера. Пути сеанс. Входящего. Звонка 2 сеанс. Звонка (#yes 3 #call $s. Call ) авторизация. Пути. Звонок сеанс. Звонка (#yes 2 l $s. Call ) #yes $s. Call авторизация. Пути. Звонок сеанс. Входящего. Звонка 1 (#no #nextcall #stop ) авторизация. Пути. Звонок авторизация. Номера. Пути. Звонок сеанс. Исходящего. Звонка авторизация. Номера. Пути. Звонок (#no #nextcall #num $s. Auth. Num. Path ) авторизация. Пути авторизация. Внешнего. Номера. Пути (#no #stop ) #no #stop, $s. Call вводится новое поле outgoing #no if (se. outgoing) $s. Auth. Num. Path else #stop
class SEANCE { bool outgoing = false; // = true для сеанса исходящего звонка bool incoming. Path = false; // = true если первым приходит сообщение // Auth. Incoming. Path() SEANCE(ID j, bool outgoing, bool incoming. Path); // конструктор сеанса радиус-сервера для сеанса СИТ с идентификатором j bool completedl. All(); // = true в случае, когда все звонки в серии звонков // завершены либо серия пуста }
SEANCE se; // текущий сеанс в радиус-сервере process собработка. Очередного. Сообщения(: #loop) { if (Auth. Incoming(ID j)) { se = new SEANCE(j, false); БС ! Auth. Incoming. Billing(); $s. Auth. Incoming } else if (Auth. Incoming. Path(ID j)) { se = new SEANCE(j, false, true); БС ! Auth. Incoming. Billing(); $s. Auth. Incoming } else if (Auth. Outgoing(ID j)) { se = new SEANCE(j, true, false); БС ! Auth. Outgoing. Billing(); $s. Auth } else if (Auth. Incoming. Billing. Reply(ID j, bool ответ)) { СИТ ! Auth. Incoming. Reply(ответ); if (se. stop ответ) #stop else { БС ! Auth. Num. Billing(); $s. Auth. Num. Billing } else if (Auth. Num. Billing. Reply(ID j, bool ответ)) { СИТ ! Auth. Num. Reply(ответ); if (se. stop) #stop else if ( ответ) if (se. outgoing) $s. Auth. Num. Path else #stop else if (se. outgoing se. incoming. Path) $s. Auth. Num else { БС ! Auth. Path. Billing(); $s. Auth. Path. Billing } }
else if (Auth. Path. Billing. Reply(ID j, bool ответ)) { СИТ ! Auth. Path. Reply(ответ); if (se. stop) #stop; if (ответ) $s. Call else if (se. outgoing) $s. Auth. Num. Path else #stop } else if (Auth. Outgoing. Billing. Reply(ID j, bool ответ)) { СИТ ! Auth. Outgoing. Reply(ответ); if (se. stop) #stop; if (ответ) $s. Auth. Num. Path else $s. Key } else if (Key(ID j)) { БС ! Key. Billing(ID j); $s. Key. Billing } else if (Key. Billing. Reply(bool ответ)) { СИТ ! Key. Reply(ответ); if (se. stop) #stop; if ( ответ) $s. Key else $s. Auth. Num. Path } else if (Stop(ID j)) if (se. state in {s. Auth. Num, s. Call, s. Key, s. Auth. Num. Path}) #stop else se. stop = true else if (Auth. Num(ID j)) { БС ! Auth. Num. Billing(); $s. Auth. Num. Billing } else if (Auth. Path(ID j)) { БС ! Auth. Path. Billing(); $s. Auth. Path. Billing }
else if (Start. Call(ID j)) $s. Start. Call; else if (Start. Talk(ID j)) $s. Talk else if (Stop. Talk(ID j)) $s. Stop. Talk; else if (Stop. Call(ID j)) { БС ! Call. Billing(); if (se. stop) #stop else if (se. outgoing) $s. Auth. Num. Path else #stop }; stop: БС ! Stop. Biling(); удалить. Сеанс(se. id) #loop }
Реализация для ненадежных каналов Особенности ненадежных каналов: потеря, дублирование, изменение порядка сообщений Цепочки следования сообщений: Auth. Incoming. Path {Start. Cal, Start. Talk, Stop. Call, Stop} Auth. Incoming Auth. Path {Start. Cal, Start. Talk, Stop. Call, Stop} Auth. Outgoing Key Auth. Num Auth. Path {Start. Cal, Start. Talk, Stop. Ca ll, Stop} Спецификация процесса сеанс. Звонка меняется ! В четверке сообщений Start. Cal, Start. Talk, Stop. Call значимыми являются только Stop. Talk и Stop. Call. Используется таймер, чтобы избежать дедлок в случае потери сообщений Сообщения, относящиеся к предыдущему звонку, могут прийти при обработке очередного звонка необходимо уметь распознавать принадлежность сообщения звонку в случае серии звонков в одном сеансе хранить информацию о всех звонках серии Stop() завершает сеанс лишь в случае завершения сеанса звонка (получения Stop. Call)
Изменившаяся часть реализации радиус-сервера else if (Auth. Num. Billing. Reply(ID j, bool ответ)) { СИТ ! Auth. Num. Reply(ответ); if (se. stop) if (se. completed. All()) #stop else Set. Timeout() else if ( ответ) if (se. outgoing) $s. Auth. Num. Path else #stop else if (se. outgoing se. incoming. Path) $s. Auth. Num else { БС ! Auth. Path. Billing(); $s. Auth. Path. Billing } } else if (Stop()) if (se. state = s. Key) #stop else se. stop = true else if (Stop. Talk() Stop. Call()) if ( (se. stop se. outgoing) & se. completed. All() ) { БС ! Call. Billing(); #stop } Почти все специальные внутренние состояния становятся ненужными
Процессорная спецификация языка исчисления вычислимых предикатов Процессорная спецификация описывает функционирование процессора языка программирования. Операционная семантика языка исчисления вычислимых предикатов, определяемая предикатной программой исполнения программы на языке исчисления Кодирование программы и данных type NAME; // множество всевозможных имен type TYPE; // множество произвольных типов type VAR = struct NAME name, TYPE type end; // переменная type SVAR = seq VAR; // список переменных type PREDNAMES = set NAME; // набор имен предикатов программы type Program(PREDNAMES pred. Names) = array pred. Names of Predicate. Def; type Predicate. Def = struct SVAR in, out, local, RIGHT right end;
type RIGHT = union super: CALL fst, snd | // суперпозиция fst; snd paral: CALL fst, snd | // параллельная композиция fst || snd alter: VAR cond, CALL then, else | // if cond then else end gen: NAME pred. Name, SVAR in 1, in 2, out | // lambda(in 2: out) pred. Name(in 1, in 2: out) appl: NAME pred. Name, SVAR in, out | // pred. Name(in: out) arrcons: VAR arr, NAME pred. Name, range, SVAR in 2, rangepars | // for. All i range(rangepars) do arr[i] = pred. Name(i, in 2) end base: // базисный предикат исчисления end; type CALL = struct NAME pred. Name, SVAR in, out end; // вызов предиката type VALUE; // значение произвольного типа type SVALUE = seq VALUE; // список значений type QNAME = set NAME; type SECT(QNAME sn) = array sn of VALUE; // секция памяти
type ID; // генеральное множество имен секций type SID = set ID; // тип подмножества имен секций type MEMORY(SID sip) = array sip of SECT; // память программы Операции над секциями new. Sect(SVAR q: SECT s, ID id) id sip & profile. Sect(q: s) & sip’ = sip + id & mem’ = mem + (id: s); val(SECT s, VAR x: VALUE v) v = s[x]; assign(SECT s, VAR x, VALUE v: SECT s’) s[x] : = v s’ = s(x: v); multival(SECT s, SVAR z: SVALUE w) w = s[z] if z = nil then w = nil else w = s[head(z)] + multival(s, tail(z)) end; multiassign(SECT s, SVAR z, SVALUE w: SECT s’) s[z] : = w if z = nil then s’ = s else multiassign(s(head(z): head(w)), tail(z), tail(w): s’) end; del. Sect(ID id: ) id sip’ = sip - id & mem’= mem[sip’];
Исполнение программы Program prog; PREDNAMES pred. Names; run. Program(NAME start. Pred, SVALUE pars: SVAR results) start. Pred pred. Names { Predicate. Def p = prog[start. Pred]; new. Sect(p. in + p. out: SECT s, ID id); s[p. in] : = pars; run. Call(s, start. Pred, p. in, p. out); results: = s[p. out]; }; Исполнение вызова предиката run. Call(SECT sext, NAME pred. Name, SVAR in, SVAR out) pred. Names { Predicate. Def p = prog[start. Pred]; new. Sect(p. in + p. out + p. local: SECT s, ID id); s[p. in] : = sext[in]; run. Rirht(s, p. right); sext[out] : = s[p. out]; del. Sect(id) };
run. Right(SECT s, RIGHT right) { case right of super: run. Super(SECT s, CALL fst, snd) | paral: run. Paral(SECT s, CALL fst, snd) | alter: run. If(SECT s, VAR cond, CALL then, else) | gen: run. Lambda(SECT s, NAME pred. Name, SVAR in 1, in 2, out) | // lambda(in 2: out) pred. Name(in 1, in 2: out) lambda appl: run. Appl. Pred(SECT s, NAME pred. Name, SVAR in, out) | arrcons: run. For. All(SECT s, VAR arr, NAME pred. Name, range, SVAR in 2, rangepars) | // for. All i range(rangepars) do arr[i] = pred. Name(i, in 2) end base: run. Base. Pred(SECT s) // базисный предикат исчисления end }; Исполнение суперпозиции run. Super(SECT s, CALL fst, snd) { run. Call(s, fst. pred. Name, fst. in, fst. out); run. Call(s, snd. pred. Name, snd. in, snd. out); };
Исполнение параллельной композиции run. Paral(SECT s, CALL fst, snd) { run. Call(s, fst. pred. Name, fst. in, fst. out) run. Call(s, snd. pred. Name, snd. in, snd. out); }; || Исполнение условного оператора run. If(SECT s, VAR cond, CALL then, else) { if s[cond] then run. Call(s, then. pred. Name, then. in, then. out) else run. Call(s, else. pred. Name, else. in, else. out) end };