MPS 2020.1 ヘルプ

共通言語パターン

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

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

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

mps patterns1

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

初期のヒント

命名の概念

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

有効な識別子

BaseLanguage を拡張していて概念の名前が直接 Java ID に変換される場合は、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 サンプルでは container-component 仮想パッケージとして示されています。

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

mps patterns2

また、seamless-substitution パターンを参照して、ユーザーがリンゴをオレンジに切り替えたり、元の状態に戻したりできるようにする方法についても説明します。現在の実装では、ユーザーが最初にノード全体(Apple または Orange)を選択する必要があり、それからコード補完が代替案を提供します。

patterns3

カスタマイズプレゼンテーション

languagePatterns サンプルでは custom-presentation 仮想パッケージとして示されています。

http://forum.jetbrains.com/thread/Meta-Programming-System-2138?message=Meta-Programming-System-2138-3(英語) での議論に動機付けられて

コンテナー内で保持されているコンポーネントは ComponentUsages から参照されています。ただし、参照には、補完メニューとエディターの両方に、コンポーネントの名前と一緒に、コンテナー名前を含めてください。

patterns4

patterns6

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

patterns5

宣言 - 参照

languagePatterns サンプルでは declaration-references 仮想パッケージとして示されています。

patterns8

宣言とそれらへの参照の典型的なパターン - イベントでの歌手は、それらのパフォーマンスを使って議題にまとめることができます。さまざまなタイプのパフォーマンスがあります。

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

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

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

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

流暢な編集

languagePatterns サンプルでは fluent-editing 仮想パッケージとして示されています。

patterns7

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

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

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

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

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

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

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

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

  • IncompleteCommand は線か長方形のどちらかがタイプされることを期待しており、即座に希望の描画コマンドに置き換えられるでしょう

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

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

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

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

オーバーライドエディターコンポーネント

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

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

patterns9

シームレス置換

languagePatterns サンプルでは seamless-substitution 仮想パッケージとして示されています。

patterns10

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

patterns11

patterns12

階層スコープ

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

自分の参照用に DotExpression を拡張する

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

ドット表記による要素の参照解除は、多くの言語で非常に一般的な方法です。BaseLanguage は、Java の " ドット " 演算子を模倣する DotExpression の概念を提供します。BaseLanguage の式を拡張するのであれば、あなたの言語でそれを利用することができます。検証式で検証する必要があるいくつかのアドレスを持つ単純な形式を想定しましょう。検証式に値を含めるには、式で各住所の番地と郵便番号を参照する必要があります。

patterns13

各アドレスはアドレスコンセプトのノードで表されます。また、コード補完メニューに「kind」プロパティが表示されるようにプレゼンテーションもカスタマイズされています。

patterns14

patterns15

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

patterns16

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

patterns17

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

patterns18

関連ページ:

エディタークックブック

このドキュメントは、上級言語設計者を対象としており、MPS エディターに関する最も一般的な質問に対する回答を提供します。エディターのドキュメントを読むのを好むかもしれません。それはサブジェクトに関する徹底的な情報を含みます。MPS にバンドルされているRobotKajaサンプルプロジェクトは、流暢な...

スコープ

カスタム言語要素のスコープを定義する 2 つの方法、継承 (階層)と参照アプローチを見ていきます。実験用のテストベッドとして計算機のチュートリアル言語を選択しました。MPS ディストリビューションに付属のサンプルプロジェクトのセットにcalculator-tutorialプロジェクトが含まれています...

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

MPS でノードをコメントアウトするための一般的なサポート :MPS は、モデル内のノードをコメントアウトする普遍的な方法を提供します。以前のバージョンでは、この機能は、ノード属性または専用のコメントノードを通じて、すべての言語で個別に実装する必要がありました。MPS 3.3 から、コメントアウトさ...

使い方 -MPS Make フレームワークへの統合

ファセットを構築 :概要 :基本的に他のビルドシステムや make システムと同様に、MPS make はアーティファクトをビルドするために一連のステップ、つまりターゲットを実行します。必要な make ステップのグローバルな順序付けは、各ビルドターゲットに指定された相対的な優先順位から導き出されま...