УДК 004.435
ПОСТРОЕНИЕ ФОРМАЛЬНЫХ МОДЕЛЕЙ С ПРИМЕНЕНИЕМ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО МЕТАЯЗЫКА
А. А. Седунов, Н.А. Тюкачев
В рамках данной работы рассматривается оригинальный подход к решению проблемы разработки метаязыка путем соединения логического и объектно-ориентированного подходов, приводится описание типов и операций языка, вводится определение трансформационной семантики как набора правил преобразования модели предметной области в формальную теорию над исчислением предикатов первого порядка с равенством
Ключевые слова: метаязык, формальные методы, ООП, мультипарадигмальные языки, гибридные языки
ВВЕДЕНИЕ
Разработка программного обеспечения [1, 3] в настоящее время сопряжена с необходимостью составления и поддержки различного рода документации, качество и полнота которой во многом определяет качество и надежность программной системы, а также возможность ее модификации и расширения в случае изменения требований. Однако, как показывает практика, даже наличие полноценной документации не позволяет гарантировать надежность и корректность работы сложного программного продукта. Поведение реальных программных систем всегда отличается от исходных требований и приводит к возникновению незапланированных эффектов. Причиной данного явления является высокая сложность современных программных систем, которая может выражаться в формулировке функциональных требований, анализе вариантов использования системы и взаимодействия с ее окружением, а также в необходимости разработки системы с учетом возможных изменений в требованиях. Как правило, информация
о системе закрепляется в документах, составленных с использованием естественного языка, либо частично формализованной нотации (например, иМЬ [2]). Автоматизация ее анализа и применения в большинстве СЛ8Е-средств существенно ограничена, либо вообще невозможна. Более того, такое описание часто не отличается точностью и является неоднозначным. Принципиальное решение проблемы состоит в автоматизации процесса разработки и изменении подхода к документированию информации о разрабатываемом программном продукте.
Формальные методы разработки ПО представляют собой [1, 5] особую разновидность ма-
Седунов Алексей Александрович - ВГУ, аспирант, Е-таП: [email protected]. тел.8-961-182-31-28 Тюкачев Николай Аркадиевич - ВГУ, канд. физ.-мат. наук, доцент,
Е-таЛ: шк@^^и.т, тел. 8-903-854-78-97
тематических моделей, предназначенных для составления спецификаций ПО, построения программного кода, а также проверки корректности программ. Главное преимущество формального подхода состоит в возможности применения математических методов к разработке и анализу программного обеспечения, позволяя тем самым гарантировать его корректность и надежность. Ядром инструмента автоматизации разработки является специальный метаязык, с помощью которого разработчик может описывать предметную область решаемой проблемы [4, 5]. В данной работе предлагается при построении метаязыка объединить формализм логики предикатов и элементы теории множеств с объектноориентированным подходом
Исследование, выполненное авторами в рамках проекта JANE по созданию инструментальной среды для разработки и анализа формальных спецификаций, представляет собой оригинальный способ построения гибридного метаязыка. В данной статье описывается структура (абстрактный синтаксис) ядра метаязыка JLS, касающаяся типов и операций, а также приводятся примеры описаний с использованием соответствующей текстовой нотации.
JLS-МОДЕЛИ
JLS-модель описывает набор взаимосвязанных сущностей предметной области. Каждая модель образует отдельное пространство имен, состоящее из определений классов. Возможно также использование определений из других моделей - в этом случае имеет место зависимость между моделью, использующей объект и моделью, содержащей его определение. Внешние определения должны квалифицироваться именем модели. Граф отношения зависимости между моделями не должен содержать циклов -в противном случае все модели, образующих цикл, считаются некорректными.
Процедура трансформации получает на входе корректную JLS-модель и строит на вы-
ходе соответствующую ей формальную теорию над исчислением предикатов первого порядка с равенством, которая может использоваться алгоритмами логического вывода для получения ответов вопросы в рамках предметной области модели (включая проверку истинности утверждений, поиск решений, синтез программ и т. д.).
Формальная теория, построенная в результате трансформации модели, характеризуется множествами предикатных и функциональных символов, набор собственных аксиом, устанавливающих свойства предикатов и функций, а
также множеством утверждений V, которые должны быть верифицированы для подтверждения корректности модели. Если хотя бы одно из утверждений V не удается проверить, модель считается некорректной.
СИСТЕМА ТИПОВ ^
Тип характеризует множество значений, которые могут принимать объекты модели, а также допустимые операции и отношения, в которых они могут использоваться. В типы существуют только на уровне модели и при трансформации преобразуются в предикаты соответствующей формальной теории.
Система типов вводится на основе иерархически определяемых множеств. Пусть То -
некоторое множество, далее именуемое множеством типов нулевого уровня (элементарных типов). Множество типов уровня п, где п > 0 рекуррентно определяется следующим образом:
def йе[ . -
Т = Р [Тп-1 ] = {Р (Т)|Т €Тп_,}, п > 0(1),
где Р - оператор, называемый оператором степенного типа.
Тип Т = Р(3) называется степенным
типом с базовым типом 3 .
Системой типов называется множест-
во
def
т = т =Uт (2)
го n
n>0
Оператор степенного типа представляет собой биективное отображение вида р : Т^Т+, характеризуемое следующим свойством:
У(п > 0)У(Т еТ,)[Р(Т) еТ„+,](3)
Два типа Т и $ называются подобными, если они находятся на одном уровне системы типов:
Т ~ $ = 3(п > 0 )Т еТ, л $ еТ, ](4)
Каждый тип T е Т характеризуется множеством своих экземпляров, которое будет обозначаться через Set[T] . Если T = P(S) - степенной тип, то множество его экземпляров определяется как степенное множество по отношению к множеству экземпляров базового типа
S:
def
Set [P( S )] = 2Set[ S ](5)
Константный тип Any представляет собой
корневой тип нулевого уровня, т. е. любой элементарный тип является подтипом Any. Введение Any (как и других корневых типов) в систему типов JLS связано с необходимостью поддержки обобщенных операций, тип параметров которых не всегда может быть известен заранее.
Множеством экземпляров типа Any является специальная предметная константа Any , которая автоматически включается в формальную теорию модели в процессе трансформации. def *
Set[Any] = Any (6)
. *
Состав множества Any не определяется
явным образом, однако аксиомы, генерируемые при трансформации модели, гарантируют, что множество экземпляров любого элементарного типа будет подмножеством Any* .
Основным отношением, определенным в системе типов JLS, является отношение специализации <:, выражающее тот факт, что экземпляр одного (подтипа) всегда может рассматриваться как экземпляр другого типа (супертипа). Отношение специализации характеризуется рядом свойств:
T <: T
(7)
Т <: 3,3 <: Я ^ Т <: Я Т <: 3 ^ 3в1[Т] с 3^[3] [Т <: 3 ^ Ор[ 3 ] с Ор[Т ]
Точное определение специализации в случае элементарных типов зависит от их структуры. Для степенных типов специализация определяется следующим образом. Пусть Т и 3 -подобные типы, тогда тип Т является подтипом типа 3 тогда и только тогда, когда базовый тип Т является подтипом базового типа 3 :
def
Т <: 3 о Т ~ 3 Л Р-1(Т) <: Р-1(3)(8)
Два подобных типа Т и 3 называются эквивалентными, если они являются подтипами друг друга:
def
Т * 3 о Т <: 3 Л 3 <: Т (9)
В языке эквивалентные типы фактически являются неразличимыми, так как любой из них может использовать в контексте, требующем второго типа.
ОПЕРАЦИИ
Каждый элементарный тип Т характеризуется множеством Ор[Т ] операций, которые могут быть выполнены над его экземплярами. В
существуют две разновидности операций: отношения и функции.
Каждая операция Г характеризуется следующими свойствами:
Логический признак абстрактной операции А . Операция, имеющая этот признак, называется абстрактной, не имеющая - замкнутой.
Имя операции - произвольная текстовая строка, идентифицирующая данную операцию среди множества всех операций соответствующего типа. Все операции, принадлежащие одному типу, должны иметь различные имена.
Кортеж параметров г.Р = ^Р)™1 • Каждый параметр Р характеризуется своим типом Р Т и необязательным предикатом ограничения Р .С = Р .С(р). Если С1 не задан, подразумевается тождественно-истинное утверждение.
Необязательный предикат
Я = Я( P1,..., рт) , называемый предусловием
и используемый для дополнительного ограничения области изменения значений параметров. Если предусловие отсутствует, подразумевается тождественно-истинное утверждение.
Тело операции, которое представляет собой выражение вида В = В(^,р1,...,рт ) . Тело
операции может зависеть от ее параметров, а также от tЫs-переменной ^, представляющей произвольный экземпляр типа, которому принадлежит данная операция. Для операции-
отношения выражение В является предикатом, для операции-функции - термом. Для абстрактной операции тело не определено.
Сигнатурой операции Г называется кортеж sig (г):
sig (г ) = ( К, N, Р) (10),
где K - вид операции (для отношения K = 0 , для функции K = 1).
Полной сигнатурой Sig (r) операции называется кортеж вида
0. , ч \sig(rXsig(r)K = 0 (ii)
lg Г Кsig(rXTo),sig(r)K = 1
Операции-функции дополнительно характеризуются типом результата T0 и необязательными ограничениями значения функции
C = Co(s) и E = E(Pi,..., pm, s), которые
называется result-ограничением и постусловием соответственно.
КЛАССЫ
Классы представляют собой основную разновидность типов в языке JLS, предназначенную для описания сущностей предметной области модели. Классы позволяют непосредственно определять набор операций, доступных для своих экземпляров и специализацию по отношению к другим типам. Все остальные элементарные типы, кроме Any, строятся на основе классов.
Класс C характеризуется следующим набором свойств:
• Набор атрибутов
\ Primal, Abstract ,Unique, |
[Closed, Disjoint, Case, Final J
• Имя класса - произвольная текстовая строка, идентифицирующая данный класс среди других классов модели. В пределах одной модели все классы должны иметь различные имена.
• Кортеж параметров
cp=р: и предусловие
C.R = C.R(p1,..., pm) . Эти свойства аналогичны свойствам функций и отношений и определяют условия существования экземпляра класса.
• Определение класса
C.D = C .D (P1,..., Pm ). Определение - терм
элементарного типа, который может зависеть от параметров класса, а также его произвольного экземпляра t (this-переменная). Тип определения называется прямым супертипом класса C . Определение может отсутствовать - в этом случае прямым супертипом класса является Any.
• Произвольный предикат
C.I = C.I(t,p1,...,pm ) , который называется
инвариантом и может зависеть от параметров класса и this-переменной. Инвариант выражает условие, которое выполняется для любого экземпляра класса.
• Множество Op непосредст-
* imm 1
венных операций. Выражения, входящие в эти операции, могут зависеть от параметров класса и this-переменной.
Поскольку утверждения о существовании объектов с теми или иными свойствами часто применяются при построении математических моделей, в языке JLS вводится специальные соглашения, упрощающие использование таких утверждений.
Атрибут Primal связан с проверкой существования экземпляров класса. В JLS каждый класс должен иметь хотя бы один экземпляр, т. е. утверждение, описывающее принадлежность произвольного объекта данному классу должно быть выполнимым в логике предикатов. Если класс отмечен атрибутом Primal (такой класс называется первичным), то соответствующее утверждение о существовании будет добавлено к списку аксиом формальной теории и не будет верифицировано в процессе трансформации. В противном случае система попытается вывести это утверждение из аксиом теории. Если выполнить вывод не удается, модель считается некорректной.
Смысл автоматически генерируемого утверждения можно неформально выразить следующим образом: для любой комбинации объектов, удовлетворяющих ограничениям класса, существует хотя бы один экземпляр, значения параметров которого совпадают с этими объектами.
Другая важная категория утверждений, также часто применяемых в математических моделях, описывают единственность объекта, характеризуемого заданными свойствами. В языке JLS для поддержки утверждений этого типа вводятся атрибуты класса Abstract и Unique. В зависимости от наличия или отсутствия этих атрибутов все классы делятся на 3 группы:
• Если класс отмечен атрибутом
Abstract, он называется абстрактным.
• Если класс не отмечен ни одним
из атрибутов Abstract или Unique, он называется неявно уникальным.
• Если класс отмечен атрибутом
Unique, он называется явно уникальным.
Одновременное использование атрибутов Abstract и Unique не разрешается.
Смысл утверждения о единственности можно неформально выразить следующим образом: если для любой комбинации объектов, удовлетворяющих ограничениям параметров конструктора, существует хотя бы один экземпляр класса, значения параметров которого совпадают с этими объектами, то такой экземпляр является единственным.
Если класс является абстрактным, то утверждение о единственности не генерируется и не проверяется - тем самым подразумевается, что единственность экземпляра не гарантируется. Класс, содержащий хотя бы один абстрактный метод, должен обязательно быть отмечен атрибутом Abstract (в силу того, что абстрактный метод может иметь различные реализации в подклассах, гарантировать существование только одного экземпляра для такого класса нельзя и, следовательно, он обязательно должен быть абстрактным).
Для неявно уникального класса утверждение о единственности генерируется и в процессе трансформации модели выводится из имеющихся аксиом теории. Если вывод не удается, модель считается некорректной.
В случае с явно уникальным классом утверждение о единственности генерируется, но не верифицируется, а включается в число аксиом теории.
Класс, отмеченный атрибутом Closed, называется замкнутым. Замкнутый класс позволяет описать специальный набор Case-подклассов, характеризуемый следующим свойством: объединение множеств экземпляров Case-подклассов совпадает с множеством экземпляров данного класса. Case-подклассы отмечаются с помощью атрибута Case и должны принадлежать той же модели, что и данный класс. При этом замкнутый класс, как и любой другой, может иметь обычные (не Case) подклассы.
Замкнутый класс, отмеченный атрибутом Disjoint, называется дизъюнктным. Дизъюнктный класс характеризуется тем, что если некоторый объект является экземпляром одного из его Case-подклассов, то он не может быть экземпляром никакого другого его Caseподкласса (иначе говоря, множества экземпляров Case-подклассов попарно не пересекаются). Дизъюнктный класс автоматически становится замкнутым, независимо от наличия атрибута Closed.
Класс, отмеченный атрибутом Final, называется завершенным. Такой класс не может использоваться в качестве суперкласса (непосредственно или в составе пересечения). Все методы завершенного класса автоматически становятся
3в1[С ]
(12)
замкнутыми.
ЭКЗЕМПЛЯРЫ И ОПЕРАЦИИ КЛАССА Пусть С = (А,N,Р,Я,В,I,Ортт) -
класс с прямым супертипом Т .
Множество экземпляров класса определяется с помощью вспомогательного предиката isC (/, р1,..., рт ) (IS-предикат), который выражает тот факт, что объект ^ является экземпляром класса С со значениями параметров
р^-рт .
3(Pl, ...рт ) |>С (, Pl,..., рт )]
Для определения множества операций Ор[С ] необходимо ввести некоторые вспомогательные понятия. Пусть Г е Ор - непо-
'7 г шт
средственная операция С . Если существует такая операция г ’ е Ор[Т], что Г ’ .N = Г.N, то Г называется потенциально переопределяющей операцией (по отношению к Г ’):
def
Г ^ Г ’ о Г^ = Г ' N (13)
?
Если при этом полные сигнатуры Г и Г ' совпадают, Г не является абстрактной, не содержит явных ограничений параметров и не определяет явным образом предусловие, то операция Г называется переопределяющей операцией (также по отношению к Г ' ):
def
г ^ г ’ о г г 'л 3ig(г) = 3ig(г ') лг. А = 0 л г.Я( х1,..., хк) = Тгие л
(14)
Л
Г к
л г.Р .С = Тгие
г=1 г
В противном случае Г и Г называются конфликтующими операциями. Пусть теперь
Орп
- множество неявных опе-
раций прямого супертипа, которые потенциально не переопределяются какой-либо операцией
Ор. :
± шт
I (15)
г ’ е Ор[Т ]
Ор тр =< -3(г е Ор1тт) “1 > г ^ г ’ ? J
Ор - множество собственных
это непосредственная операция, которая не является потенциально переопределяющей по отношению к какой-либо операции из набора
Ор[Т ]:
(16)
Г е Ор,тт
Оррго = -3(г' е Ор[Т ]) г ^ г ’ ? J
Оро
I (17)
• Ороуг - множество операций
Ор1тт, переопределяющих операции Ор[Т]:
ГГ е Фтт
|з(г' е Ор[Т]) ^ Г']
• Орсгу - множество операций,
конфликтующих с операциями Ор[Т ]:
Орсп/ = Ор[Т ] ^ Фшш \ (18)
Если конфликтующих операций нет (Орсп/ = 0), то класс считается корректным и
набор его операций выражается через введенные
множества:
def
операций класса
С . Собственная операция -
°р[С] = Ортр ^ Оррго и ^г (19)
В противном случае (Орсп^ ^0) класс
считается некорректным и множество Ор[С ]
не определено.
Правило специализации для классов определяется следующим образом. Пусть С - класс с прямым супертипом Т и 3 - элементарный тип, тогда:
def
С <: 3 о Т <: 3 (20)
ПРОИЗВОДНЫЕ ТИПЫ
Категория производных типов индуктивно
определяется следующим образом. Пусть Т -класс или ранее построенный производный тип с непустым множеством операций, Г е Ор[Т]
- одна из его операций с именем X = Г N и у
- произвольное имя, не совпадающее ни с одним из имен операций Ор[Т ]. Тогда выражение
Т [X = у ] называется производным типом, образованным от Т подстановкой х := у (тип
Т при этом называется исходным типом).
Из определения следует, что любой производный тип Т можно представить в виде
Т = 3[ х1 = У1]...[ хк = Ук ](21)
где к > 0. В представлении (21) тип S называется основным исходным типом T .
Множество значений производного типа совпадает с множеством значений соответствующего исходного типа:
def
Set [T [ X = y]] = Set[T ](22)
Множество операций производного типа фактически совпадает с множеством операций его исходного типа за исключением того, что операция r меняет имя с X на y . Эта операция называется производной операцией типа T [ X = y ] , все остальные операции называются неявными (неявно унаследованными от исходного типа).
def
Op T[ X = y ]]= (23),
Op[T ]\{r} =y },rN = X
где rN обозначает операцию, все атрибуты которой (кроме имени N ) совпадают с соответствующими атрибутами операции r , а имя совпадает с y .
Таким образом, эффект производного типа состоит в простом переименовании одной из операций исходного типа без изменения ее семантики. Данная операция является необходимой во многих случаях множественного (в частности, повторного) наследования классов.
Правила специализации для производных типов сводятся к следующему: T [ X = y ] <: S
тогда и только тогда, когда S имеет вид U[X = y ], где T <: U :
def
T[x = y] <: S ^ (24)
S = U[x = y] л T <: U
Из правила (24) и данного выше определения T [ x = y ] следует, что специализация производных типов сводится к специализации классов, на основе которых они построены.
Производные типы не связаны с соответствующими исходными типами отношением специализации. В частности, терм, имеющий тип T [ X = y ] не может непосредственно использоваться в контексте, требующем объект типа
T.
венного наследования при описании классов.
Для определения понятия типа-пересечения вначале необходимо рассмотреть ряд вспомогательных понятий.
Пусть {Т }™1 - множество типов, в котором
каждый тип является либо производным, либо классом, Ор1 = Ор[Т ] - множество операций
т
1 -го типа и Ор = и Ор. . Следующая проце-
!=1
дура строит на основе множества Ор три множества Ортр , Орт^ и Ор^, кот°рые называются соответственно множествами неявных, объединенных и конфликтующих операций для
набора типов {т. }™1:
1. Если множество Ор пусто, завершить процедуру.
2. Пусть г е Ор - произвольная
операция из набора Ор и ^ - номер исходного
набора, которому она принадлежит, т. е. Г е Ор0 С Ор . Если ни в одном из наборов,
отличных от Ор не содержится операции, имя
* .0
которой совпадает с именем г , то операция г добавляется к множеству Ор и удаляется из
множества Ор . Затем происходит переход к шагу 1.
Op ^ Op \ {r}
(25)
множе-
Ор 1тр ^ Ор.тр и М . Пусть
Я = {(г,Т) Г е Ор1 л г-N = г^} -
ство пар, включающих операции, имена которых совпадают с Г.N (в частности, Г е Я ) вместе с соответствующими типами из набора
{Т }”\. Если множество Я является родственной совокупностью (определение соответствующего понятия дается ниже), то все операции,
принадлежащие парам Я , удаляются из Ор, а к множеству Ор добавляется операция
теще(Я). После этого происходит переход к шагу 1:
ТИПЫ-ПЕРЕСЕЧЕНИЯ
Типы-пересечения используются в языке JLS, главным образом, для реализации множест-
Я’ = {г’|э(/) [{гТ) е Я ]}
Ор ^ Ор \ Я' (26)
°Ршр ^ ОРгтр ^ {тєг£є(Я)}
4. Все операции, принадлежащие
парам Я , удаляются из Ор и добавляются к множеству Ор у:
\Ор ^ °р \Я' (27)
Ортр ^ Фтр ^ Я'
Если множество Я является группой родства, то все операции в Я ' имеют одинаковые полные сигнатуры (такую же полную сигнатуру имеет и операция тєг^є( Я)). Если все операции в Я ' имеют вид
г, = ( л,,«0, р,, Я, в),, = 1„/, тогда тє^є( Я) = (Ло, Ро, Яо, Во) (28),
где
Д = min A
l
P = P, Pi c (i) = A/j.p .c (i)
j=i
(29)
Я0(Л —рп) = Л Г Я(Л — рп)
У=1
и, если А = 0, а Jо - номер неабстрактной
операции (в группе родства такая операция, если вообще существует, является единственной):
В0( Pl,•••, рп , * ) = ВД Pl,•••, рп , * )(30)
Если Д = 1, то В0 не определено.
Таким образом, объединенная операция те^е(Я) является абстрактной, если все операции, входящие в Я \ являются абстрактными и замкнутой - в противном случае. Ограничения параметров и предусловие объединенной операции представляют собой конъюнкции соответствующих предикатов операций Я ’. Тело объединенной операции (если она не является абстрактной) совпадает с телом замкнутой операции
из Я \
Если Орсп^ =0 (т. е. конфликтующих
т
операций нет), то Т = №
1=1
называется типом-
пересечением, образованным типами T, i = 1..m. При этом
def m
Set IT = I Set [T ](31)
Op
n т
. i=l
m
Пт
i=1
i=1
def
= Op ^ Op (32)
г imp г mrg
mrg
Если типы, образующие пересечение, имеют одноименные, но не связанные друг с другом операции, множество Орсп^ окажется непустым, а пересечение будет не определено. В этом случае один или несколько типов, содержащих конфликтующие операции, следует заменить на производные типы, в которых этим операциям присваиваются различные (неконфликтующие) имена.
Для типов-пересечений вводится два пра-
вила специализации. Тип
т=Пт
называется
i=1
подтипом типа 3 , если
• Тип 3 является производным
типом или классом, причем
3(1 = 1..п)Т <: 3](33)
к
• 3=13 и
1=1
У(1 = 1..к)3(J = 1..т)[Т <: 3.](34)
РОДСТВЕННЫЕ ОПЕРАЦИИ На основе отношения специализации вводится ряд отношений, связывающих операции, принадлежащие типам. Эти отношения совместно с выражениями формального вызова позволяют формализовать полиморфное поведение операций.
Пусть Т <: 3, гТ е Ор[Т] и г3 е Ор[3] -две операции с одинаковой полной сигнатурой, рассматриваемые в контексте типов Т и 3 соответственно и пусть, по крайней мере, одна из
них является абстрактной. Операция г3 называется базовой по отношению к операции гТ (запись: гТ <: Г3), если выполняется одно из следующих условий:
• ГТ = Г ;
и
• Существует класс и и операция
Ги е Ор[и] , такие, что Т <: и,и <: 3 и
гт <: ги, ги <: Г3 ;
• Т - класс с прямым супертипом
и и гТ - операция, переопределяющая опера-
цию ги е Ор[и] , причем ги <: г3.
Succ(Sum(x, Pred(y))
}
t=пт
i=1
rT = merge(R), R с Op и rS е R.
Операция rS называется корневой по отношению к операции rT (запись: rT <<: rS), если rT <: rS и не существует базовой операции
для rS .
Две операции rT и rS называются родственными в контексте типов T и S, если они имеют общую базовую операцию. Множество
R=r ,t) ц , где ^е Op[T ] , называ-
етсяродственной совокупностью, если любые
две операции rT и rT , входящие в него, родст-
Ti Tj
венны в контексте соответствующих типов Ti и Tj ■
ПРИМЕРЫ JLS-МОДЕЛЕЙ Первый пример описывает начало простой теории, основанной на арифметике Робинсона, в которой аксиоматически вводится понятие натурального числа:
model Naturals;
disjoint abstract Nat;
primal unique case 0 = Nat; primal unique case Succ(n: Nat) = Nat where {
all[n1: Nat, n2: Nat](
Succ(n1) = Succ(n2) -> n1 = n2);
}
1 = Succ(0);
Pred(n: Nat) = Nat requires n != 0 where Succ(this) = n;
Sum(x: Nat, y: Nat) = match[Nat] { y = 0 => x; default =>
Первая строка вводит класс Nat, который представляет произвольное натуральное число. Этот класс описан как абстрактный (т. е. модель не утверждает существования непосредственно экземпляров Nat) и дизъюнктный (множества экземпляров его прямых подклассов не пересекаются).
Далее описываются два конкретных подкласса 0 и Succ. Эти классы описывают два способа построения натуральных чисел в арифметике Робинсона: с помощью константы "нуль" и операции следования (Succ(n) - это число, следующее за n, т. е. n + 1 в обычных обозначениях). Классы отмечены атрибутами primal и unique, поэтому для них конструируются соответствующие аксиомы существования:
1. Существует единственный нуль.
2. Для каждого натурального числа n существует единственное натуральное число, следующее за ним.
Так как эти классы отмечены атрибутами case, то на них распространяется ограничение дизъюнктности суперкласса Nat. Дизюнктность фактически означает, что
3. Никакое натуральное число не является одновременно нулем и следующим за другим натуральным числом.
Так как дизъюнктный класс всегда замкнут, то это также означает, что
4. Любое натуральное число является нулем или следует за другим натуральным числом.
Класс Succ, кроме того, определяет инвариант, смысл которого состоит в следующем:
5. Для любых натуральных чисел n и m из Succ(n) = Succ(m) следует, что n = m.
Так как класс Succ в силу атрибута unique задает функцию, то предыдущее утверждение фактически означает, что эта функция инъек-тивна.
Далее в модели вводится вспомогательный объект "1", определяемый как число, следующее за нулем.
Класс Pred описывает предыдущее число и определяется на основе уже определенного класса Succ:
• Ограничение requires означает, что операция предшествования имеет смысл только для числе, отличных от нуля.
• Инвариант означает, что k = Pred(n) тогда и только тогда, когда Succ(k) = n. Выражение this обозначеает "текущий" объект k.
X + y = ■
Для класса Pred также конструируется утверждение о существовании и единственности его экземпляра, однако оно не включается в число аксиом, а автоматически верифицируется в процессе трансформации модели.
Введенные классы Pred и Succ далее используются для построения рекурсивного описания суммы двух натуральных чисел. В более традиционных обозначениях описание этого объекта можно представить следующим образом:
\ X, y = 0 .
[(X + (y -1)) +1 y * 0
Второй пример описывает фрагмент предметной области абстрактной алгебры и иллюстрирует, главным образом, множественное (в том числе дублирующее) наследование:
model Alg;
abstract Magma(S: set \ S != []) = { abstract function
op(x \ x in S, y \ y in S)
\ result in S;
}
abstract CommutativeMagma(S: set) = Magma(S) where {
all[x \ x in S, y \ y in S](
x op y = y op x
);
}
abstract AssociativeMagma(S: set) = Magma(S) where { all[x \ x in S]
all[y \ y in S]all[z \ z in S](
x op (y op z) = (x op y) op z
);
}
abstract UnitalMagma(S: set) =
Magma(S) {
function identities: set =
[e =>
e \ e in S
where all[x \ x in S](
(x op e = x) &&
(e op x = x)
)
];
} where {
some[e](e in identities);
}
abstract InversibleMagma(S: set) = UnitalMagma(S) { function
inverses(x \ x in S): set =
[y =>
y \ y in S where (
(op(x, y) in identities) &&
(op(y, x) in identities)
)
} where {
all[x \ x in S]some[e]
(e in inverses(x));
}
abstract Semigroup(S: set) = AssociativeMagma(S);
abstract Monoid(S: set) =
Semigroup(S), UnitalMagma(S); abstract Group(S: set) =
Monoid(S), InversibleMagma(S); abstract AbelianGroup(S: set) = Group(S), CommutativeMagma(S); abstract Ringoid(S: set) =
Magma[op = add](S),
Magma[op = mul](S) where {
all[x \ x in S]
all[y \ y in S]all[z \ z in S] (
x mul (y add z) =
(x mul y) add (x mul z)
);
all[x \ x in S]
all[y \ y in S]all[z \ z in S] (
(x add y) mul z =
(x mul z) add (y mul z)
);
}
abstract Semiring(S: set) =
Ringoid(S),
CommutativeMagma[op = add](S), Monoid
[op = add,
identities = zeros](S),
Monoid
[op = mul,
identities = units](S)
where {
all[x \ x in S] all[e \ e in zeros]
(((x mul e) in e) &&
((e mul x) in e))
}
Эта модель вначале вводит абстрактный класс Magma, который описывает непустое множество S с заданной на нем замкнутой бинарной операцией op (свойство замкнутости выражается ограничениями, наложенными на параметры и результат функции).
Затем описывается ряд подклассов Magma, каждый из которых характеризуется некоторым свойством, выраженным в виде инварианта класса:
• CommutativeMagma - множество с коммутативной операцией;
• AssociativeMagma - множество с ассоциативной операцией;
• UnitalMagma - множество с нейтральными элементами (множество таких элементов возвразается методом identities);
• InversibleMagma - множество с обратимой операцией (для каждого элемента
];
ва S метод inverses возвращает множество его обратных элементов).
После этого описанные подклассы Magma комбинируются, образуя в результате производные классы:
• Semigroup (полугруппа) - ассоциативная магма;
• Monoid (моноид) - унитарная полугруппа;
• Group (группа) - обратимый моноид;
• AbelianGroup (Абелева группа) -коммутативная группа.
Более сложный случай наследования представлен классами Ringoid и Semiring. Первый из них определяет множество с двумя замкнутыми операциями, которые называются "сложением" (add) и "умножением" (mul) и удовлетворяют свойству дистрибутивности. Класс дважды наследует от Magma с переименованием исходной операции op - это позволяет использовать объект Ringoid в контексте, требующем объекта Magma. Класс Semiring (полукольцо) определяет 4 операции (add - сложение, mul - умножение, zeros - нули и units - единицы) и накладывает различные ограничения на add и mul, причем за счет комбинирования соответствующих супертипов класса класс наследует все свойства, заданные для этих операций в суперклассах.
ЗАКЛЮЧЕНИЕ
В рамках представленной работы рассмот-ривается оригинальный подход к решению проблемы разработки гибридного метаязыка JLS путем соединения логического и объектноориентированного подходов, приведено описание структуры типов и операций.
Литература
1. Jim Woodcock. Using Z. Specification, Refinement and Proof. - Prentice Hall International Ltd., 1996. - 386 c.
2. Yingzhou Zhang. A Survey of Semantic Description Frameworks for Programming Languages. ACM SIGPLAN Notices. - 2004. - № 39.3-C.14 - 30.
3. Лавров С. С. Программирование. Математические основы, средства, теория. - СПб.: БХВ-Петербург, 2001. -320 с.: ил.
4. Чень Ч. Математическая логика и автоматическое доказательство теорем: Пер. с англ. / Чень Ч, Ли Р. - М.: Наука. Главная редакция физико-математической литературы, 1983. - 360 с.
5. Benjamin C. Pierce. Types and Programming Languages. - The MIT Press, 2002. - 623 c.
6. Стюарт Рассел. Искусственный интеллект. Современный подход. 2-е издание: Пер. с англ. / Стюарт Рассел, Питер Норвиг - М.: Издательский дом "Вильямс", 2005. - 1424 с.
7. Седунов А. А. Гибридный объектно-
ориентированный метаязык. Технологии Microsoft в теории и практике программирования: Тр. VI Всерос. конф. студентов, аспирантов и молодых учкных. Центральный регион. Москва, 1 - 2 апреля 2009 г. - М.: Вузовская книга, 2009., стр. 177 - 178.
Воронежский государственный университет
FORMAL MODEL DESIGN USING OBJECT-ORIENTED METALANGUAGE A.A. Sedunov, N.A. Tukachev
In this paper the authors consider original method of solving the specification metalanguage design problem by composing logical and object-oriented paradigms. Language types and operations are presented along with syntax details description and definition of transformational semantics in terms of translation from domain model to formal theory over the first-order predicate calculus with equality
Keywords: metalanguage, formal methods, OOP, multi-paradigm languages, hybrid languages