Extending Structure Language (Moved)
From IT SPb Academy
Выявились случаи, когда при описании концептов языка structureLanguage выглядит недостаточно выразительным.
Случай 1
Надо вставить блок кода baseLanguage-а в модель (solution) написанную на языке ортогональном baseLanguage-у. Например в описание едиторов.
Случай 2
В языке, котороый расширяет baseLanguage (напр. SModelLanguage), хочется использовать нотацию с точкой (как при вызове методов в baseLanguage).
Реализация.
Случай 1 (на примере 'cell rendering condition' в editorLanguage ):
Сейчас такая inline-function описывается так:
1. в structure-model editorLanguage-а декларируется концепт: QueryFunction_NodeCondition extends abstract ConceptFunction (baseLang)
2. декларируется тип возвращаемого значения: вставляется concept link 'conceptFunctionReturnType' со ссылкой на тип (в данном случае - boolean)
3. декларируются параметры функции
В данном случае это:
- node с типом "вычислимый, но приводимый к snode" - scope с типом IScope (обычный интерфейс)
Каждый параметр декларируется как child-concept с ролью 'conceptFunctionParameter' и extends abstract ConceptFunctionParameter (baseLang).
Свойства параметра (имя, тип) задаются с помощью соответствующих concept-property/concept-link
4. для концепта функции пишется едитор (опционально, иначе используется едитор базового концепта (т.е. abstract ConceptFunction (baseLang)))
5. для вычислимых типов пишутся рулы в typesystem (в данном случае для типа выражения 'node'. этот тип зависит от того, в каком едиторе используется этот блок кода)
6. описывается генератор для концепта функции.
Обычно генерится 2 сущности:
- декларация метода с нужными параметрами (должно совпадать имя и приводиться тип), и телом, которое просто копируется из источника - вызов этого метода в нужном месте и с нужными аргументами
Проблема:
structureLanguage ничего незнает о
- семантике базовых концептов (abstract ConceptFunction (baseLang), abstract ConceptFunctionParameter (baseLang)) - семантике концептуальных пропертей и линков (типа alias, conceptFunctionReturnType, conceptFunctionParameter) - семантике типов - семантике самого концепта (что генерится)
Соответственно, писать такой концепт крайне трудно, поскольку тул никак в этом не помогает.
Как хотелось-бы
описывать такой класс концептов (т.е. встроенные блоки кода или inline-functions):
В опиании editorLanguage-а (в каком месте?) на специальном DSL (типа InlineFunctionSpecificationLanguage) задекларировать inline-function способом, который напоминает декларацию обычных функций.
Например:
inline-function boolean cell_rendering_condition( <? : snode> node , IScope scope)
как минимум, из такого описания должны сгенериться концепты с начинкой (см пп 1-3 выше).
дополнительно надо чтобы:
- для типа <? : snode<>> можно было-бы легко создать правило вычисления типа (в typesystem) - для всей функции и ее параметров можно было-бы легко понять, какие концепты им сответствуют (с тем, что-бы использовать их в других местах MPS-a: делать на них ссылки, определять едиторы, генераторы, констраинтсы итд.).
Кроме того, желательно чтобы не надо было каждый раз писать генератор, а просто сконфигурить заготовленные шаблоны (типа: static или instance method, имя метода итд.)
Как это могло-бы работать:
1. надо создать небольшой DSL (типа InlineFunctionSpecificationLanguage) специально приспособленный для декларирования inline-function и для него написать генератор --> structureLanguage
2. где-то в специальном месте в editorLanguage-е пользуясь InlineFunctionSpecificationLanguage задекларировать нужные inline-functions
3. после этого MPS должен сгенерить соответствующие концепты. они будут находиться не в structure-model editorLanguage, а в специальной модели, которая, возможно, не будет сохраняться (подобно тому, как сейчас делается с java_stub-ами).
4. далее со сгенеренными концептами можно работать как с обычными (едиторы и прочее для них совершенно обычные)
5. концепт для вычисляемого типа (его экземпляр в примере выглядит как <? : snode>), скорее всего, стоит создать в baseLanguage, т.к. он может реюзаться.
6. как конфигурить шаблоны генератора пока не рассматривается (какой-то dsl со ссылками на шаблоны и параметрами). на первом этапе это не обязательно.
Случай 2
в smodelLanguage слева от точки находится выражение smodelLanguage-а (это, например, preperty-access, которое записывается как node.property_name), а справа помещается операция.
Например, для property-access можно применить операцию 'set' с параметром Expression (baseLang):
node.name.set( "aaa" )
Это очень похоже на вызов метода класса, хотя на самом деле и для proprty-access и для set-operation определены концепты, а в выражение подставляются экземпляры этих концептов.
Как и в случае 1, здесь используются базовые концепты, concept-links и concept-propeties, которые несут в себе специфическую семантическую нагрузку и, неявно, образуют небольшой 'framework' для описания класса концептов типа smodel-expression.
И, как и в случае 1, хотелось бы этот 'framework' оформить в виде DSL, где эта семантика выражалась бы явно.
Видно, что тип выражения property-access имеет анологию с classifier-type, а операция 'set' напоминает метод. Поэтому все обисание могло бы походить на декларацию класса с методами.
Например (упрощенно):
typeclass PropertyAccess { void set ( Expression ) }