ПРЕДВАРИТЕЛЬНОЕ СООБЩЕНИЕ О ЯЗЫКЕ ИСПОЛНЯЕМЫХ ПРОГРАММНЫХ СПЕЦИФИКАЦИЙ
(Работа выполнена при поддержке Программы фундаментальных исследований Президиума РАН № 3 «Фундаментальные проблемы системного программирования»)
В.Б. Новосельцев, д.ф.-м.н. (ИПС им. А.К. Айламазяна РАН, г. Переславль-Залесский, [email protected]); Ф.А. Новиков, к.ф.-м.н. (Институт прикладной астрономии РАН, г. Санкт-Петербург, [email protected])
В статье рассматривается предметно-ориентируемый язык исполняемых программных спецификаций, позволяющий описывать модели формализуемых предметных областей, ставить на них вычислительные задачи и синтезировать программы решения задач на основе логического вывода в специальном классе исчислений.
Ключевые слова: предметно-ориентируемый язык, автоматический синтез программ, формальные спецификации.
Автоматический синтез программ по спецификациям - мечта методологов программирования. Несмотря на заметные успехи в области теоретической информатики, доля промышленных проектов по разработке ПО, основанных на автоматической генерации кода и доказательном программировании, остается незначительной. Наряду с яркими примерами в журнальных публикациях есть и многочисленные отрицательные отзывы практикующих программистов.
Многие полагают, и авторы разделяют это мнение, что одним из ключевых факторов, влияющих на распространение автоматического синтеза программ, является использование формальных методов построения моделей конкретных предметных областей. Введение в широкую практику программирования предварительных математических моделей предметных областей (именно моделей как определяющих конструкций) является признаком того, что программирование действительно становится инженерной областью деятельности.
В последние годы наиболее многообещающим в этой области представляется распространение идей порождающего программирования. Разумеется, порождающее программирование - это исторически далеко не первая попытка опереться в программировании на математические модели и методы, понятные всем. Необходимо указать три ранние работы, идеи которых - опора на рекурсивные декларативные определения, использование формализованной модели предметной области и дедуктивный синтез программ из крупных блоков, а не из операторов языка программирования -оказали значительное влияние на последующее развитие в данной области [1-3].
Практика показывает, что «сильный» пользователь, досконально знающий предметную область, имея в распоряжении предметно-ориентированный язык (domain specific language), опирающийся на развитый пакет прикладных программ, зачастую быстрее находит лучшие и более дешевые программные решения, чем команда профессиональных программистов. В настоящее время накоплен значительный запас пакетов при-
кладных программ для самых разных предметных областей, методы создания предметно-ориентированных языков (как текстовых, так и графических) достаточно развиты. Таким образом, ключевым вопросом является формализация знаний о предметной области.
Существует множество подходов к построению формализованных моделей предметных областей. В последнее время удалось значительно усовершенствовать формальный аппарат, на который опирается предлагаемый здесь подход [4, 5], что позволяет пойти дальше и предложить новое поколение средств спецификации моделей предметных областей.
Назначение и область применения языка
Предлагаемый язык исполняемых программных спецификаций (ИПС) предназначен для формализации предметных областей, определения предметно-ориентированных языков и быстрого создания прототипов программных приложений в формализуемых предметных областях (в английской нотации - Program Specification Interpreter -PSI).
В основу языка положены следующие принципы.
1. Ориентация на декларативную спецификацию предметной области в терминах формальной теории в специальном логическом исчислении, приспособленном для использования непрофессиональным программистом.
2. Симметричное описание структур (сущностей) и поведения (связей) конкретной задачи в данной предметной области: сущности определяются через связи, а связи через сущности.
3. Автоматический синтез схемы решения задачи с последующей компиляцией или интерпретацией схемы на основе доверительного программного фонда предметной области.
4. Открытое определение абстрактного синтаксиса языка (метамодели) и предоставление пользователю возможности расширения и изменения метамодели.
5. Определение нескольких вариантов конкретного синтаксиса, однозначно отображаемых в
метамодель, в том числе графической нотации, порождающей грамматики, ограниченного естественного языка, схемы XML, системы распознающих автоматов.
Абстрактный синтаксис
Опишем метамодель языка ИПС в стиле, напоминающем Венский метод определения языков программирования. Абстрактная грамматика описывается с помощью следующих обозначений. Метаклассы обозначаются прописными буквами, а их атрибуты описываются в поясняющем тексте. Метасимвол «*» означает итерацию. Альтернативы разделяются знаком «I».
Конструкция верхнего уровня называется моделью предметной области (метакласс M - от английского model). Модель агрегирует некоторое количество пакетов (метакласс P - package). Модель и пакет образуют пространство имен: различные однотипные сущности и различные однотипные именованные отношения должны иметь разные имена. Модель и пакет также имеют имена. Соответствующее грамматическое правило имеет вид: M=P*.
Между пакетами определено отношение «непротиворечивое расширение». Если пакет p2 непротиворечиво расширяет пакет p1, значит, все сущности и отношения p2, одноименные с сущностями и отношениями p1, добавляют свои свойства и составляющие к одноименным элементам p1, если это можно сделать непротиворечивым образом, то есть не переопределяя элементы p1 и не нарушая ограничения метамодели. (Используется следующее лексическое соглашение. Имя объекта, являющегося экземпляром некоторого метакласса, начинается с той же буквы, что и имя метакласса. Если объект является классом, то его имя начинается с прописной буквы, а если экземпляром, то со строчной. Таким образом, p1 - имя конкретного пакета.) Непротиворечивое расширение играет ту же роль, что и наследование в объектно-ориентированных языках, но свободно от недостатков последнего. Кроме того, пакеты могут быть вложенными и образуют строгую композиционную иерархию.
Пакет определяет группу родственных понятий, которые образуют язык предметной области. В пакет композиционно вложены «отношения» (метакласс R - relation), которые делятся на три непересекающихся подтипа: эксплицитные, или явно заданные (метакласс T - table), имплицитные, или неявно заданные (метакласс S - scheme), и встроенные, или примитивные (метакласс E -embedded). Явно заданное отношение - это совокупность кортежей с данными (метакласс D -data). Встроенное отношение - это ссылка на внешнюю программную реализацию, которых может быть несколько (метакласс I - implementation). Самым характерным является имплицитное
отношение, задаваемое набором функциональных зависимостей (метакласс F - function), постулирующих возможность вычислить значение одного атрибута - результата, если заданы значения некоторых других атрибутов - аргументов. Функциональную зависимость в моделях обозначим стрелкой «^», направленной от аргументов к результату. Соответствующее грамматическое правило имеет вид: P = R *
R = T | S | E. Любое отношение, в частности схема, обязательно содержит определенное количество атрибутов (метакласс A - attribute) и может содержать некоторое количество вариантных частей (метакласс V - variant). Вариантные части являются дополнительными альтернативными частями отношения, выбираемыми с помощью условия варианта (метакласс G - guard). Вариантные части также могут содержать атрибуты и функциональные зависимости. Соответствующее грамматическое правило имеет вид: S=A*F*V* V=G A*F* F=A*^A.
Атрибут (имплицитного) отношения может быть входным - встречается только в левых частях функциональных зависимостей, значит, его значение должно быть задано. Атрибут может быть выходным - встречается в правых частях функциональных зависимостей, значит, его значение может быть вычислено. Эта классификация лежит в основе базовой конструкции «задание» (метакласс Q - question). Задание ставится на некотором отношении, возможно, специально сконструированном на основе отношений предметной области для описания контекста конкретной задачи. В задании требуется построить программу, определяющую значения некоторых выходных атрибутов отношения по некоторым входным атрибутам. Соответствующее грамматическое правило имеет вид: Q=A*?A*.
Графическая нотация
Современная тенденция - использование для предметно-ориентированных языков графической нотации там, где это возможно. В большинстве случаев основу графического языка составляет метафора диаграммы графа: сущности изображаются вершинами, отношения - ребрами. У такого подхода множество неоспоримых плюсов, но есть и существенный недостаток: чтобы диаграмма читалась, в ней должно быть достаточно «воздуха».
В предлагаемом графическом языке основу составляет другая метафора - разлинованная страница, то есть разбиение отведенного поля диаграммы на части прямыми линиями. При этом общая картина не двух-, а трехмерная. Разлинованные страницы могут быть сложены в стопку и связаны друг с другом, например, прямоугольник
на одной странице раскрывается в виде другой страницы. При таком подходе «воздух» совсем не используется, диаграмма - это плотно упакованная кристаллическая структура. Сущности вводятся текстовыми именами, а отношение композиции - вложенностью соответствующих блоков. В текстовой нотации применение отношения композиции, как обычно, передается точкой. Пример описания отношения изображен на рисунке (серые треугольники - не часть графической нотации, а пояснительные выноски).
S Fib
2 А п, а : N
3 G п = 1 or п = 2 else
F а <- 1 A fl, f2 : Fib
I f " П a_+ a
В этом примере определяется отношение Fib (1), элементами которого являются номер (атрибут n) и соответствующее значение (атрибут a) числа Фибоначчи. Основные атрибуты n и a (2) -натуральные числа (N - встроенный тип). Отношение имеет две вариантные части (4), выбор которых производится по условию (3) (else - встроенный предикат). Причем вторая вариантная часть содержит два дополнительных атрибута f1 и f2 того же типа Fib (5). Собственно отношение определяется имплицитно с помощью функциональных зависимостей (6). Подобные рекурсивные определения не только являются допустимыми, но и служат одним из основных выразительных средств языка ИПС. В данном случае для ясности указан метакласс каждой конструкции. Разумеется, на практике это делать необязательно, если метакласс восстанавливается из контекста.
Деривационная семантика
В качестве математического фундамента предлагаемого языка используется полный формализм, выразительность которого приближается к выразительности языков первого порядка - теория структурных моделей и связанное с ней исчисление SR [4]. Формализм структурных моделей является некоторым вариантом типизированных исчислений, при этом исчисление SR позволяет эффективно (не более чем с третьей степенью от длины исходного описания) устанавливать выводимость целевого утверждения.
Базовой конструкцией теории структурных моделей выступает схема отношения, которая содержит некоторое количество атрибутов, связанных функциональными зависимостями, а также может содержать определенное количество вариантных частей, обусловленных селекторами, зависящими от значений атрибутов, не входящих в ва-
риантные части. Каждая вариантная часть, в свою очередь, может иметь некоторые атрибуты и функциональные зависимости. Среди атрибутов вариантных частей могут быть атрибуты, типом которых является само определяемое отношение. Таким образом, определение отношения может быть рекурсивным [5]. Это обеспечивает возможность синтеза рекурсивных программ определенного вида.
С помощью описания структурной модели для предметной области строится специальная (формальная) теория, в которой можно решать, в частности, задачу установления выводимости предложений соответствующего языка и генерации, реализующей вывод программы.
Постановка задачи в структурной модели носит непроцедурный характер - в ней указываются лишь исходные и искомые атрибуты некоторой схемы. Содержательно постановка задачи на модели есть задание на построение схемы алгоритма, реализующего требуемые вычисления.
Алгоритм синтеза схемы программы, включающий и стратегию поиска вывода в исчислении SR, обеспечивает синтез схемы программы за время, в худшем случае не превосходящее третьей степени длины описания модели [5]. Класс синтезируемых программ достаточно широк, он включает в себя линейные, ветвящиеся и рекурсивные конструкции, а также предусматривает распараллеливание.
Алгоритм может быть описан с использованием некоторого псевдокода, структуры управления которого традиционны для языков программирования высокого уровня. Используются следующие обозначения и соглашения:
• Ck - множество достижимых атрибутов исходной схемы;
• по-аксиома - проблемно-ориентированная аксиома из текущей схемы;
• вход в подсхему - наличие в Ck атрибутов, принадлежащих подсхеме;
• A0 и S берутся из формулировки задачи.
Описание алгоритма.
«Установить i=0, C0=A0»;
«поднять флаг "продолжать доказательство"»; «текущей схемой объявить S»;
while «поднят флаг "продолжать доказательство"» do if «имеется по-аксиома текущей схемы, аргументы которой входят в Cj» then
«применить правило композиции и, если возможно, правило ветвления или правило распараллеливания»; «определить Ci+i с новыми атрибутами»; «установить i=i+1»; «если определился вход в подсхему, запомнить ее» else if «имеется подсхема, в которую определен вход» then
«объявить ее текущей схемой» else if «текущая - рекурсивная схема» then «применить правило введения рекурсии;
установить i=i+1»; else «объявить текущей внешнюю схему» fi fi fi; if «текущая - исходная и нет по-аксиом, аргументы которых входят в Cp then «опустить флаг "продолжать доказательство"» fi od.
Доверительный программный фонд
Модель предметной области на языке ИПС опирается на некоторый программный фонд, накопленный в данной предметной области. Составляющими этого фонда могут быть отдельные программы, наборы данных, библиотеки функций, библиотеки типов и классов. По мнению авторов, очень важно обеспечить возможность использования любого нестандартного программного фонда, поскольку, во-первых, ПО, декларирующее соответствие какому-либо стандарту, встречается сравнительно редко и, во-вторых, такое соответствие невозможно проверить, а потому на него не стоит полагаться. Вместо этого описывается форма требуемого интерфейса (контракта), который должен обеспечивать используемый программный фонд.
В модели предметной области программный фонд представляется как первичные типы, первичные функции, первичные отношения.
Первичные типы мыслятся как множество значений и множество применимых к этим значениям операций. Значения первичного типа не обладают «самостью» (identity), в модели предметной области работа со значениями первичных типов осуществляется либо через атрибуты, содержащие эти значения, либо через изображения констант, обозначающих эти значения.
Значение данного первичного типа может иметь различные представления в памяти компьютера, а операция реализована разными методами - эти нюансы являются внутренним делом реализующего программного фонда и в модели не отображаются. Аналогично ответственность за обработку нештатных и исключительных ситуаций, подобных переполнению, потере значности, нехватке памяти и т.д., должен брать на себя доверительный программный фонд - в модели эти детали не учитываются.
Строки (первичный тип Str), натуральные числа с нулем (первичный тип Nat) и логические значения (первичный тип Bool) считаются встроенными и доступными при использовании любого программного фонда или даже без него.
Первичные функции - это операции предметной области. Они могут иметь входные параметры
первичных типов и должны возвращать значение первичного типа. Первичные функции могут инкапсулировать сколь угодно сложные вычисления в предметной области: с точки зрения модели предметной области первичная функция - это атомарное непрерываемое гарантированно завершающееся вычисление, доставляющее декларированный контрактом результат.
Первичные отношения - это наборы данных предметной области. Они могут быть представлены реляционными таблицами, XML-файлами или каким-то другим способом. С точки зрения модели это не имеет значения при условии, что предоставлен итератор первичного отношения, позволяющий перебирать кортежи первичного отношения, если значения атрибутов этих отношений нужны для выполнения синтезированной программы.
Предлагаемый язык ИПС является продолжением и развитием идей синтеза программ на функциональных вычислительных моделях, предложенных Э.Х. Тыугу в 70-х годах прошлого века. Позже стали использовать термины «семантические вычислительные сети» и «концептуальное программирование». На основе этой идеи в 80-е годы было несколько десятков реализаций в разных организациях как в форме систем автоматического синтеза программ общего назначения, так и в форме конкретных предметно-ориентированных пакетов прикладных программ, управляющие модули которых использовали данную идею.
В настоящее время удалось значительно усилить используемый математический аппарат, превратив эмпирическую программистскую конструкцию в развитую теорию структурных моделей и соответствующее исчисление SR [4, 5], за счет чего область применения структурного синтеза программ существенно расширилась.
Литература
1. Кахро М.И., Калья А.П., Тыугу Э.Х. Инструментальная система программирования ЕС ЭВМ (ПРИЗ). М.: Финансы и статистика, 1981. 157 с.
2. Непейвода Н.Н. Об одном методе построения правильной программы из правильных подпрограмм // Программирование. 1979. № 1.
3. Бабаев И.О., Новиков Ф.А., Петрушина Т.И. Язык Декарт - входной язык системы СПОРА // Прикладная информатика. М.: Финансы и статистика, 1981. № 1. С. 35-73.
4. Новосельцев В.Б. Теория структурных функциональных моделей // Сибирский матем. журн. 2006. Т. 47. № 6. С. 1342-1354.
5. Новосельцев В.Б. Синтез параллельных рекурсивных программ в функциональных моделях // Программирование. 2007. № 5. С. 1-6.
Обращаем внимание читателей на изменившийся телефон ред акции
8 (4822) 39-91-49