MPS 2020.3 ヘルプ

共通言語パターン

この章では、MPS を学ぶ初心者がよく遭遇するであろう共通言語設計パターンについて説明します。私達は MPS ユーザーがオンラインフォーラムで確認する最も頻繁な質問としてこれらの時間を経て特定したため私達は容易な参照のために一箇所に答えをまとめることにした。

言語パターン付きのサンプルプロジェクト

MPS にはサンプルプロジェクトがバンドルされています。ここで説明するパターンの多くは、languagePatterns サンプルプロジェクトに実装されています。MPS で開き(MPS のウェルカム画面でサンプルプロジェクトを開くをクリック)、サンプルプロジェクトを参照するこの章のパターンの実際の実装を確認できます。

Mps patterns1

パターンは言語定義とサンドボックスソリューションの両方で仮想パッケージにまとめられ、個々のパターンを形成する要素を識別できます。

初期のヒント

命名の概念

多くの概念では、ノードの名前を保持するための文字列プロパティを提供する必要があります。概念の名前には特定の特別な性質があり、MPS によって特別な方法で認識および処理される必要があるため(たとえば、コード補完メニュー、プロジェクトビュー、ノードエクスプローラー、デバッガーツールウィンドウなどでノードにラベルを付けるため)、INamedConcept コンセプトインターフェースからプロパティを継承することをお勧めします。多くの概念とほとんどすべてのルート概念は、INamedConcept の 実装を宣言する必要があります。

有効な識別子

BaseLanguage を拡張していて、概念の名前が Java 識別子に直接変換される場合は、INamedConcept を拡張する IValidIdentifier 概念インターフェースから name プロパティを継承することを検討する必要があります。制約を通じて、名前が有効な Java 識別子の基準を満たしていることを確認します。

固有の名前

多くの場合、同じ概念のノードの特定のグループの名前の一意性を確保する必要があります。制約または非型システムルールのいずれかを使用できます。Not-typesystem ルールは、エラーメッセージをカスタマイズするオプションを提供し、自動問題解決のためにユーザーにクイックフィックスを提供する場合もあります。電卓チュートリアルの電卓 での InputField の名前の一意性チェックのサンプルは次のようになります。

checking rule check_InputField {   applicable for concept = InputField as inputField   overrides false   do {     if (inputField.parent : Calculator.inputField.any({~it => it.name :eq: inputField.name && it :ne: inputField; })) {   error "Duplicate name " + inputField.name -> inputField; }   }                                                                                                                                                                                    }                                                                                                                                                                                     

constraint で指定されたものと同じ制約は、次のようになります。

concepts constraints InputField {    can be child <none>        can be parent <none>        can be ancestor <none>            property {name}      get:<default>      set:<default>      is valid:(propertyValue, node)->boolean {        node.parent : Calculator.inputField.where({~it => it.name :eq: propertyValue; }).size <= 1;      }            <<referent constraints>>        default scope      <no default scope>      }

いくつかの理由から、ここでは制約はおそらくあまり最適ではないことに注意してください。

  • クイックフィックスを指定することはできません

  • エラーメッセージはカスタマイズできません

  • 非型システムルールではエラーを示すために重複した名前にのみ下線を引いていますが、制約はモデルに無効な値が挿入されるのを防ぎ、無効な値を赤いフォントで表示します。

型システムエラーが表示されない

型システムはバックグラウンドで実行され、結果をエディターに配信するのが遅くなることがあります。エディターのすべてのエラーと警告メッセージをリフレッシュするために F5 を押してください。省電力モード設定がオフになっていることも確認してください。パワーセーフモードでは、型システムはユーザーからの明示的な要求に応じてのみ動作します(F5)。

正規表現

デフォルトでは、プロパティは整数ブール値文字列の 3 つのタイプのいずれかになります。よりカスタマイズされたデータ型が必要な場合は、データ型を定義し、正規表現によって許可される値を制限する必要があります。BaseLanguage は、このようにフロートタイプを定義します(敵の例)。FloatingPointConstant コンセプト Alt+Insert)を開き、プロパティ値を確認します。タイプは _FPNumber_String です。_FPNumber_String Ctrl+Space の定義に移動して、制約されたデータ型の例を確認します。

constrained string datatype: _FPNumber_String                                                                                           matching regexp: -?[0-9]+\\.[0-9]*([Ee][\\+\\-]?[0-9]+)?[dD]?

安全なオペレータと操作

BaseLanguage とそのコア拡張機能は、Java で正しく処理するためにより多くの労力を必要とする一般的な操作のためのいくつかの便利なショートカットを提供します。たとえば、比較する前に null をチェックする、空のリストと null リストを区別する、「==」の代わりに equals を呼び出すなどです。最も一般的に役立つもののリスト:

  • : 式: - null-safe が等しい

  • ねえ: - null セーフではない

  • 無効です

  • isNotNull

  • サイズ

  • isEmpty

  • isNotEmpty

基本パターン

languagePatterns サンプルのコンテナーコンポーネント仮想パッケージとして示されています。

コンテナー(この場合は FruitPlate)に複数の種類(リンゴ、オレンジ)の要素(果物)が含まれる一般的なシナリオ。抽象概念(Fruit)がコンテナーのプレースホルダーとして使用され、具体的な下位概念(Apples、Oranges)が言語ユーザーによって明示的に提供されます。サブコンセプトは完全に異なる外観を持つことがあります。

Mps patterns2

ユーザーが少しの労力で Apple を Oranges に切り替えたり、元に戻したりできるようにする方法については、シームレス置換パターンも参照してください。現在の実装では、ユーザーは最初にノード全体(Apple または Orange)を選択する必要があり、その後、コードの補完によって代替手段が提供されます。

Patterns3

languagePatterns サンプルのカスタムプレゼンテーション仮想パッケージとして示されています。

http://forum.jetbrains.com/thread/Meta-Programming-System-2138?message=Meta-Programming-System-2138-3(英語) での議論に動機付けられた
コンテナー内に保持されているコンポーネントは、ComponentUsages から参照されます。ただし、参照には、コンプリーションメニューとエディターの両方で、コンポーネントの名前と一緒に 含まれているコンテナーの名前を含める必要があります。

Patterns4

Patterns6

さらに、スコープルールは、コンポーネントへの参照が 1 つだけ存在することを保証し、完了メニューがフィルタリングされて、すでに参照されているコンポーネントが提供されないようにする必要があります。

Patterns5

languagePatterns サンプルの宣言参照仮想パッケージとして示されています。

Patterns8

宣言とそれらへの参照に関する典型的なパターン - イベントの歌手 は、パフォーマンスを使用してアジェンダに編成できます。さまざまな種類のパフォーマンスをご利用いただけます。

スコープ規則はそれを確実にします:

  • 現在のイベントにリストされている歌手だけがアジェンダに追加できます

  • 各歌手は、組み合わせられたパフォーマンスで一度だけリストされることができます

  • 便利なインテンション( IntroduceSinger)を使用して、パフォーマンスで入力された文字列から歌手を作成できます(「使用箇所から作成」または「変数の導入」リファクタリングと呼ばれることがよくあります)。

languagePatterns サンプルの流暢な編集仮想パッケージとして示されています。

Patterns7

テキスト風の編集環境を作成し、Editor クックブック(エディタークックブック)に記載されている推奨事項の多くを実装する例。描画コマンド(線、長方形)を指定するための簡単な言語を実装しています。

  • Enter キーを押すと空行が挿入されます。子コレクションに指定されたデフォルトノードファクトリのおかげで空行はどこにでも配置できます

  • IDontSubstituteByDefault コンセプトインターフェースを実装しているため、完了メニューに空の行がオプションとして表示されません。

  • 空行に入力すると目的の項目が挿入されます (線または長方形)

  • コードブロックの本体が空の場合、カーソルは最初の行(ヘッダーの隣)に置かれ、この最初の行から編集を開始できます。

  • NodeFactories は、ノードが別のノードに置き換えられた場合に、新しいノードへの値の伝播を処理します

  • 左側の変換により、描画コマンドの左側にオプションの「線種」子を指定できます。

  • ラッパーを使用すると、空の行に目的の線種を入力でき、中間の「 IncompleteCommand 」が自動的に作成されます。

  • IncompleteCommand は、線または長方形のいずれかが入力されることを想定しており、目的の描画コマンドに即座に置き換えられます

  • draw コマンドはエイリアスとエディターを定義し、それらが同じ単語で始まるようにします。

  • draw コマンドの抽象スーパーコンセプトのエディターは、具象サブコンセプトによって再利用されます。

  • コマンドの左側に入力すると、許可されている接頭辞が表示されます。

  • 接頭辞(実線、点線)を削除しても、接頭辞のみが正しく削除されます。

languagePatterns サンプルの override-editor-component 仮想パッケージとして示されています。

サブコンセプト(Truck)でオーバーライドされるエディターコンポーネントの使用例。Car のエディター は、Car でも定義されているエディターコンポーネント CarProperties を使用します。サブコンセプト( Truck)は、CarProperties エディターコンポーネントを TruckProperties エディターコンポーネントでオーバーライドして、独自のプロパティを含めます。 Car のエディターは、Trucks 用のエディターコンポーネントの Trucks バリアントと、Cars 用の Car バリアントを使用します。

Patterns9

languagePatterns サンプルのシームレス置換仮想パッケージとして示されています。

Patterns10

関連するさまざまなサブコンセプトをシームレスに切り替える(置換する)例。リクエストには「説明」が含まれます。これは、文字列単純な形式、または複雑な形式のいずれかです。完了メニューを使用すると、ユーザーは要求された説明タイプを選択できます。ユーザーが単にテキストを入力した場合、「文字列」ベースの説明は「 PickTheRightDescriptionType 」代替アクションで自動的に選択されます。各説明の概念のエディターの最初のセルは、置換(セルの「メニュー」プロパティで設定)に敏感であるため、完了メニューを使用して説明の種類を切り替えるオプションを提供します。「コンバーター」ノードファクトリには、記述情報の一部を保持し、それを新しくインスタンス化された記述概念に伝播するコードが含まれています。

Patterns11

Patterns12

ある種の参照を定義する場合は、通常、参照のスコープを制限して、特定の場所または「距離」にあるノードのみを指すようにします。参照から: さらに、定義は、参照からさらに離れた同じ名前の他の参照を非表示にする場合があります。たとえば、パラメーター宣言またはフィールドを非表示にする Java のローカル変数について考えてみてください。MPS では、参照を定義するときに、言語定義の制約アスペクトで参照のスコープを指定する: 階層スコープの場合、参照で継承されたスコープタイプを使用してから、コードコンテナー(クラス、メソッド、ブロックステートメントなど)に ScopeProvider コンセプトインターフェースを実装させる: その getScope() メソッドでは、特定の種類の候補ターゲットを、ポイントしたい参照用に取得するロジックを実装する: 詳細な使い方については、スコープドキュメントをチェックしてください。

languagePatterns サンプル(MPS 3.3 以降にバンドルされている)の dotexpression 仮想パッケージとして示されています。

「ドット」表記による要素の参照解除は、多くの言語で非常に一般的な方法です。BaseLanguage は模倣に Java の「ドット」演算子を DotExpression コンセプトを提供し、彼らが BaseLanguage の表現を拡張している場合、あなたの言語でそれを活用することができます。検証式で検証する必要のあるいくつかのアドレスを持つ単純なフォームを想定してみましょう。式は、検証式に値を含めるために、各住所の番地と郵便番号を参照する必要があります。

Patterns13

各アドレスは、アドレス概念のノードによって表されます。また、コード完了メニューに「kind」プロパティが表示されるようにプレゼンテーションをカスタマイズしていることに注意してください。

Patterns14

Patterns15

AddressReference の概念により、検証セクションの BaseLanguage 式内からアドレスを参照できます。

Patterns16

すべての BaseLanguage 式は、「ドット」を追加するとすぐに DotExpression に変換され、左側のオペランドが元の式になります。残っているのは、操作と呼ばれる DotExpression の右側です。オペレーションは、IOperation コンセプトインターフェースを実装します。ストリート用と郵便番号用の 2 つの操作が必要になるため、これらの一般的な抽象的なスーパーコンセプトから始めます。

Patterns17

具体的な操作では、意味のある別名と型システム規則のみを指定して、周囲の式全体に正しく参加するようにします。

Patterns18

関連ページ:

エディタークックブック

このドキュメントは、上級言語設計者を対象としており、MPS エディターに関する最も一般的な質問に対する回答を提供します。エディターのドキュメントを読むのを好むかもしれません。それはサブジェクトに関する徹底的な情報を含みます。エディター定義を作成する方法:MPS がエディターをデザインするために言語デザイナーに提供する DSL は、セルの概念に基づいて構築されています。言語設計者は、エディターセルを組み合わせて、表記法の望ましい最終レイアウトを反映するように画面上に配置します。画面の右下隅にある...

スコープ

カスタム言語要素のスコープを定義する 2 つの方法、つまり継承された(階層的)アプローチと参照アプローチについて見ていきます。実験のテストベッドとして計算機のチュートリアル言語を選択しました。MPS ディストリビューションに付属するサンプルプロジェクトのセットに含まれている電卓チュートリアルプロジェクトを見つけることができます。2 つの方法:すべての参照は許可されたターゲットのセットを知る必要があります。これにより、ユーザーが参照の値を入力しようとしているときはいつでも MPS が完了メニュー...

ノードをコメントアウトする

MPS でノードをコメントアウトするための一般的なサポート:MPS は、モデル内のノードをコメントアウトするための普遍的な方法を提供します。以前のバージョンでは、この機能は、ノード属性または専用のコメントノードを介して、すべての言語で個別に実装する必要がありました。MPS 3.3 以降、コメントアウトされているノードに関する情報は、一般的な方法でモデルに格納されます。smodel 言語はデフォルトでコメント化されたノードを無視するため、クエリでコメント化されたノードを明示的に除外する必要はありま...

ハウツー MPS Make フレームワークへの統合

ファセットを構築:概要基本的に他のビルドまたはメイクシステムと同様に、MPS メイクは一連のステップまたはターゲットを実行してアーティファクトをビルドします。必要な make ステップのグローバル順序は、各ビルドターゲットに指定された相対的な優先順位から導出されます(ターゲット A は B の前に実行する必要があり、B は C の前に実行する必要があるため、グローバル順序は A、B、C です)。完全なビルドプロセスでは、モデルをテキストに生成する、これらのモデルをコンパイルする、サーバーにデプ...