Termware - система компьютерной алгебры, предназначенная для встраивания в системы языковой обработки. В этой статье определяется формальная модель, лежащая в основании семантики языка, бегло описывается синтаксис языка TermWare и внутреннее строение Java API. Текст рассчитан на знакомство читателя как с практикой объектно - ориентированного и функционального программирования, так и с основами математической логики. Впрочем, если Вы — программист, думающий использовать TermWare в своих проектах, то чтение первой части можно заменить чтением ее первого параграфа.
Здесь построена обычная терминальная алгебра, где объектами языка являются термы (выражения вида fi(x1…xn), переменные и элементарные типы данных, такие-же как во всех языках функционального программирования) с одним отличием от стандартного подхода: конструктор упорядоченного множества является выделенным термом и операции подстановки на этих термах сохраняют порядок.
Остаток раздела посвятим обычному утомительному построению:
Σpt = {CHAR,SHORT,INT,BigDecimal,BigInteger,BOOL,STRING,ATOM}
Определим множество конкретных термов Tc :
Σc, ci
Tc
Σt,∀r
Tc+ = {T1,…Tn} t(T1,…Tn)
TcИ множество подстановочных термов Tv
Tc{t
Tv}
Σx, x
Tv
Σt,r
Tv+ = {T1,…Tn} t(T1,…Tn)
TvТерм, принадлежащий Tv∕Tc будем называть термом со свободными переменными, для каждого терма T множество входящих в него подстановочных символов будем называть множеством свободных переменных этого терма и обозначать как v(T).
Определим на нашей системе термов следующие модельные функции:
{INT} : subterm(ci,j) = NIL
{INT} : subterm(xi,j) = NIL
Tv,j
{INT} : j < 1 → subterm(t,j) = NIL

Tv,j
{INT} : j >= arity(t) → subterm(t,j) = NIL
1…nri == qi
Tv : arity(t1) < arity(t2) → t1 < t2
Tv,t1.getName() <
t2.getName() → t1 << t2
т. е. множество термов просто частично-упорядоченно. Зачем - это позволяет нам выделить конструктор упорядоченного множества.

И fvi(x) - множество индексов термов.
![(| N IL length(K ) = 0
|{ N IL K [0] > n
subterm *(t(t1 ...tn),K ) = | t K [0] < n ∧length(K) = 1
|( sku[0b]term *(t ,K∕K [0]) K [0] < n ∧length(K) > 1
k[0]](Semantics_rus2x.png)
S
В случае, когда это не будет вызывать неоднозначности, мы будем также
обозначать ее как s([x1,t1]…[xn,tn]) или просто как s[xi,ti]
![subst(t,s([x1,t1]...[xn,tn])) = subst(t,...(subst(t,s[x1,t1])...,s[xn∕tn])](Semantics_rus3x.png)
![{
subst(xi,s[xj,tj]) = tj i = j
xi i ⁄= j](Semantics_rus4x.png)
![{
subst(t(t1...tn),s[x1,y1]) = t(subst(t1,s[x1,y1])...subst(tn,s[x1,y1])) x1 ⁄= t(t1 ...tn)
x1 t(t1...tn) = y1](Semantics_rus5x.png)




Правило переписывания это тройка: (X,tin,tout) где:
Tv входной терм, такой-что fv(tin) = X
Tv выходной терм, такой-что fv(tout)
XСемантика действия переписывания определяется следующим выражением:

Расширим действия переписывания на множество правил:

и на множество свободных термов1 :

Естественно, само правило может быть представленно в виде терма: rule(vars,tin,tout) где:
Будем говорить, что множество термов x переписывается в множество термов y, если существует цепочка z1…zn такая, что

Наконец, будем говорить что множество термов T сходится относительно множества правил R если существует неподвижная точка уравнения:
Множество правил R называется сходящимся, относительно конечного множества термов T, если apply*(T,R) - конечно.
Множество правил обладает свойством нетеровости если


Таким образом мы приходим к широко известной теории переписывающих правил, с некоторыми отличиями от канонических формулировок:
Эти отличия не добавляют ничего существенного нового к математическим свойствам алгебры кроме того, что чисто технически с нею удобно работать.
Мы можем расширить семантику применения правил не ненетеровы системы, фиксируя порядок применения правил в несводимых критических парах. Т. е. правила p, s образуют критическую пару, если существует такой терм t, что apply(p,t)≠apply(s,t). Для сходящихся систем для любого терма t существует общая редукция apply(p,t) и apply(s,t). Однако много практически интересных вещей лучше описываются с помощью локально-неконфлюэнтных правил с фиксированным порядком применения.
Введем частичное упорядочивания переписывающих правил по ’степени конкретности’ их входных образцов. Будем писать t1≤ct2 когда t1 ’более конкретно’ чем t2. А что такое ’более конкретно’ ? - это означает что t1 может быть представлен как частичный случай t2, т. е. существует подстановка переменных s такая, что subst(t2,s) ≡ t1. Эквивалентное определение: ∀t : free_unify(t,t1) ⇒ free_unify(t,t2).
Далее, пусть p = (inp → outp) и s = (ins → outs) два правила, формирующие критическую пару. Мы говорим, что p ≤cs if inp≤cins, и определим порядок применения как "более конкретный образец применяется первым", т. е.

Легко показать что для каждого набора правил r1…rn, где ∀i,j : i≠j ⇒⁄ ri ~crj может быть построена эквивалентная система правил без ограничений на порядок применения.
Следующий вопрос, который следует рассмотреть - это представление вычислений над термами. Обычный подход (множество правил, преобразующих входное множество термов в выходное) нас не устраивает, так как в реальном мире нам нужно несколько больше:
Примерами таких применений могут быть: набор правил для определения следуйщих действий в каком-либо бизнес-процессе, зависящий от переменных этого процесса, или процесс генерации кода, зависящий от конкретной архитектуры, или правила вывода, представляемые фактами в дедуктивной базе данных.
Следовательно, нам необходимо определить операционную семантику, включив в нее в явном виде взаимодействие с внешней средой и изменение набора правил в зависимости от состояния.
Терминальная машина это четверка: < S,E,ϕs,ϕe > где:
Заметим, что это разделение - довольно условно, так как правила переписывания представлены терминами специального вида.
Поведение терминальной машины определяется следующим преобразованием за единицу дискретного времени:

(тут x|Y обозначает проекцию x на координату Y в обычном теоретико-множественном смысле).
Нижеприведенная диаграмма может быть более ясна для понимания.
phi_s
<S,E,X> ----------> <S’,Y’> phi_e | ----------> E’ ---------------------E |
Какие изменения нам требуются внести для отражения требований операционной семантики в систему переписывания термов - просто добавить некоторый синтаксис взаимодействия со средой :
Пара вход/выход (X : x → y) заменяется на четверку (X : (x,ein) → (y,eout), где
Будем обозначать эту четверку как x[ein] → y[eout]. Выражение x[ein] для терма t можно интерпретировать как сопоставление с образцом x при выполнении subst(ein,snd(free_unify(t,x))) (пусть snd(free_unify(t,x)) = s), y[eout] - как подстановка унификации в y и выполнения subst(eout,s).
Лексемы: