MPS 2019.1ヘルプ

軽量DSL

MPSコア言語の長年の進化により、IDE統合用の言語記述型DSLの繰り返しパターンが認識されるようになりました。概念的には、それらはいくつかのより高いレベルのインターフェースを実装するプレーンなクラスによって表現されるより高いレベルの構造のように見え、ふるまいました。言語指向プログラミングの優れた伝統の中で、これらのパターンを言語に反映し、プレーンなBaseLanguageクラスの上に薄い抽象として再実装することを決めました。そのような抽象化を可能にするために、新しい 軽量DSL言語が作成されました。

jetbrains.mps.baselanguage.lightweightdsl言語により、内部DSLをBaseLanguageクラス内に埋め込むことができます。一般的に内部DSLは、本格的な外部DSLよりも開発が簡単かつ迅速です。通常、ホストDSLの構文を再利用し、周囲の非DSLコードと緊密に統合されています。同様に、MPSの軽量DSLは、単一のノードを定義し、そのノードをBaseLanguage ClassConceptまたはそのサブコンセプトに織り込むことによって作成できます。

MPS自体がいくつかの場所でこのメカニズムを利用しています。

  • 単なるBaseLanguageクラスであるMigrationScriptの概念は、マイグレーション DSLDescriptorによって強化されています。これは、いくつかの追加のプロパティー、メンバー、およびカスタムメンバーを追加します。

  • 使用箇所の検索

  • インテンション

  • カスタム言語の側面

軽量のDSLをプレーンなBaseLanguageクラスまたはClassConceptを拡張した独自の概念に織り込むことができます。

普通の授業を充実させる

Lightweight DSL言語の背後にある基本的な考え方は、DSLデザイナーが、オプションのメソッドやプロパティー、制約に応じた型、オプションのメソッドパラメータ、カスタムクラスメンバーなど、制約付きのインターフェースを定義できるようにすることです。DSLDescriptorの概念は、クラスの実装に関して強制されるべきそのような制約のあるインターフェースを体系化するノードを表します。例:以下のDSLDescriptorインスタンスがクラスにnumberOfFramesプロパティーを織るだけでなく、calculateFoo()方法とカスタムBuilderMemberノードます:

dslclass SwingBuilder for概念ClassConcept {
プロパティーnumberOfFrames:整数。プレースホルダー<1フレーム>
メソッドcalculateFoo(int value):int;必須
カスタムメンバーBuilderMember。<修飾子>

イニシャライザ:
{node <ClassConcept>ノード、モデルmodel =>}
}

特定のDSLDescriptorをクラスに適用するには、DSL注釈で注釈を付ける必要があります。これはインテンションを介して行われます。

ldsl1
ldsl2

注釈が追加されるとすぐに、DSLDescriptorで定義された必須要素、またはプレースホルダが指定された要素がクラスに追加されます。必要な要素を削除すると、クラスにエラーが表示されます。

ldsl3

インテンションを使用して、必要な要素とプレースホルダーを1つのステップで追加し直すことができます。

ldsl4

標準のメソッドの実装アクション(Control/Cmd + I)も必要なメソッドに対して機能します。

DSLDescriptorを定義する

DSLDescriptorがクラスに追加できる要素は4つあります。

  • プロパティー

  • メソッド

  • カスタムメンバー

  • イニシャライザ

これらはそれぞれ必須であり、欠落しているメンバーを表すように定義されたプレースホルダーを持つことができ、カスタムメンバー複数としてマークされてこの種の複数のノードがクラスのメンバーになることができることを示します。

プロパティー

プロパティーには名前があり、文字列型、int型、またはboolean型にすることができます。プロパティーは編まれたクラスの本格的なメンバーになり、これまたは他のDSLDescriptorを通して編まれたものを含む他のメンバーからアクセスすることができます。

メソッド

メソッドはあなたの軽量DSLのユーザがコードをインジェクションすることを可能にする非常に便利な方法を提供します - DSLDescriptorは強化されたクラスが実装することができるか実装しなければならないメソッドのメソッドシグネチャーを指定します。通常のメソッドとは異なり、これらのウィーブメソッドの戻り値の型およびパラメータの型は、ホスト(拡張)クラスでの実際の使用状況に基づいて決定できます。

依存型

依存型は、メソッドの戻り型またはパラメータ型に指定されている場合、特定のクラスのメソッドの実際の型を計算する方法を指定します。

ldsl5

条件付きメソッドパラメータ

メソッドは、条件付きとしてマークされたいくつかのパラメータを持つことができるため、それらは提供された条件が満たされたときにだけユーザコードで見えるようになります。パラメータを条件付きとしてマークするには、対応するインテンションを使用できます。

ldsl19

実際の条件はインスペクターで指定されています。

ldsl20

カスタムメンバー

プロパティーもメソッドも必要な抽象化レベルを提供しない場合は、カスタムメンバーを使用して、わずかな追加作業で任意の概念を織り込むことができます。

ldsl6

CustomMemberDescriptorは、新しいメンバーとしてクラスに織り込まれる概念(この例ではBuilderMember)を指しています。これを可能にするためには、コンセプトはMemberInstanceClassifierMemberのコンセプトインターフェースを実装し、オーバーライドするgetDeclaration()メソッドからCustomMemberDescriptorに戻る必要があります。

ldsl7
ldsl8

指定された概念のノード(またはCustomMemberDescriptor複数として定義されている場合は複数のノード)をホストクラスのメンバーとしてインスタンス化し、その中で直接編集することができます。

ldsl9

イニシャライザー

イニシャライザ関数は、ホストクラスが作成またはDSL注釈でアノテートされるとすぐに、プログラム的にホストクラスを拡張する機会を得ます。イニシャライザが呼び出されたときにノード(ホストクラス)自体がモデルに追加されていない可能性があるため、モデルパラメータはノードと同様に提供されます。smodel言語をインポートすると、クラスとモデルを操作することができます。通常、イニシャライザはインポートと使用言語を設定するか、必要に応じて、メンバーに織り込まれたユーザにデフォルト値と実装を提供します。

ldsl10

カスタムClassConceptサブコンセプトの強化

BaseLanguageクラスを直接拡張するのではなく、ClassConceptクラスの特定のサブコンセプトを拡張する場合の詳細がいくつかあります。これにより、外部DSLと内部DSLの利点を組み合わせることができます。目的のDSLにカスタマイズされた編集経験、専用のジェネレータ、または特定の型システム規則が必要になった場合は、通常、単純なBaseLanguageクラスを使用する代わりにClassConceptサブコンセプトを作成します。そこで、ClassConceptのサブコンセプトを作成し、それにAutoInitDSLClassを実装させます。

ldsl11

AutoInitDSLClassを実装することで、あなたの概念のノードが作成されるときはいつでも、それらのDSLDescriptor で定義されたイニシャライザを呼び出すことによって、DSLに織り込まれたものが正しく初期されることを確実にします。

ldsl12

AutoInitDSLClassインターフェースはまた、特定のDSLDescriptorインスタンスを織り込むべきgetDescriptor()メソッドをオーバーライドするように実装の概念を強制します。

サンプル

Lightweight DSLの基本的な使い方を説明するサンプルは、MPSディストリビューションにバンドルされているlightweightDSLサンプルプロジェクトにあります。

最終更新日: 2019年6月7日