MPS 2020.3 ヘルプ

生成プログラム

導入

ジェネレーターは、言語の概念の表示(英語)的意味論を定義する言語仕様の一部です。

MPS はモデル間変換アプローチに従います。MPS ジェネレーターは、入力言語でエンコードされた構文を出力言語でエンコードされた構文に変換することを指定します。モデルからモデルへの変換のプロセスには、多くの中間モデルが含まれる可能性があり、最終的には sn 出力モデルになります。このモデルでは、すべての構造が、セマンティクスがすでに他の場所で定義されている言語で作成されます。

たとえば、baseLanguage のほとんどの概念(クラス、メソッドなど)は「マシンで理解できる」ため、baseLanguage が出力言語としてよく使用されます。

ターゲットアセットは、モデルからテキストへの変換を適用して作成されます。これは、出力言語でサポートされている必要があります。モデルからテキストへの変換を定義する言語の側面TextGen と呼ばれ、コンセプトのエディターで別のタブとして使用できます。MPS は、生成されたアセットの破壊的な更新のみを提供します。

たとえば、baseLanguageTextGen アスペクトは、次の場所に *.java ファイルを生成します。
< ジェネレーター出力パス > \ < モデル名 > \ < クラス名> .java
どこ:
ジェネレーター出力パス - 入力モデルを所有するモジュールで指定されます。
モデル名 -「.」を置き換えることによって作成されたパスセグメントです。入力モデルの名前にファイルセパレータを使用します。

概要

ジェネレーターモジュール

他の言語の側面とは異なり、ジェネレーターの側面は単一のモデルではありません。ジェネレーターの仕様には、実用新案だけでなく多くのジェネレーターモデルを含めることができます。ジェネレーターモデルには、ジェネレーター言語のテンプレート、マッピング構成、およびその他の構造が含まれています。

ジェネレーターモデルは、モデルのステレオタイプ -' ジェネレーター '(モデル名の後に < 名前 > @ ジェネレーターとして表示)によって通常のモデルと区別されます。
以下のスクリーンショットは、例として smodel 言語のジェネレーターモジュールを示しています。

Gug generator module

新しいジェネレーターを作成する

新しいジェネレーターは、言語のポップアップメニューの新規 -> ジェネレーターコマンドを使用して作成されます。

1 つの言語に対して複数のジェネレーターを作成することは可能です。言語に単一のジェネレーターがある場合、その言語を使用することは、そのジェネレーターを使用してモデルのコードを生成することを意味します。ただし、複数のジェネレーターで言語を使用する場合、ユーザーはトリガーするジェネレーターを選択するために追加の手順が必要です。現在、これはジェネレーター計画を通じて行われています。

新しいジェネレーターモジュールを作成するとき、MPS は空のマッピング構成ノードを含むジェネレーターモデル「main @generator」も作成します。

ジェネレーターのプロパティ

モジュールとして、ジェネレーターは他のモジュールに依存し、言語使用し、devkit を使用することができます(モジュールメタ情報を参照)。

ジェネレーターのプロパティダイアログには、2 つの追加プロパティがあります。

  • ジェネレーターに依存 - 他のジェネレーターへの依存関係を指定します。これにより、依存ジェネレーターは別のジェネレーターで定義されたテンプレートを参照できます。

  • マッピング制約 - マッピングルール間の優先関係を指定できます。そのような関係に他のジェネレータールールが含まれる場合は、そのジェネレーターへの依存関係を宣言することも必要です。

ジェネレーター

MPS ジェネレーターエンジン(またはジェネレーター言語ランタイム)は変換の実行に混合コンパイル / 解釈モードを使用します。

テンプレートは実行時に解釈および入力されますが、ルール、マクロ、スクリプト内のすべての関数は事前にコンパイルされている必要があります。

混乱を避けるために、常にこのルールに従ってください。ジェネレーターモデルに変更を加えた後、モデルを再生成する必要があります( Shift + F9)。さらに良いのは、Ctrl + F9 を使用することです。これにより、ジェネレーターモジュールで変更されたすべてのモデルが再生成されます。

変換

変換はテンプレートを使用して記述されます。テンプレートは出力言語を使用して記述されているため、その言語で「通常のコード」を記述するために通常使用されるのと同じセルエディターで編集できます。追加の作業なしで、「テンプレートエディター」は、構文 / エラーのハイライト、自動補完など、同じレベルのツールサポートをすぐに利用できます。テンプレートは、入力モデルを参照することによってパラメーター化されます。

個々のテンプレートの適用性は # ジェネレータールールによって定義され、それらは # マッピング設定に分類されます。

マッピング設定

マッピング構成は最小単位であり、単一の生成ステップを形成できます。# ジェネレータールールが含まれ、マッピングラベルが 定義され、前 処理スクリプトと後処理スクリプトが含まれる場合があります。

ジェネレータールール

各変換の適用可能性は、ジェネレータールールによって定義されます。
ジェネレータールールには次の 6 種類があります。

  • 条件付きルート規則

  • ルートマッピング規則

  • 製織規則

  • 削減ルール

  • パターンルール

  • ルートルールを放棄する

  • 属性ルールの削除 (3.3 の新機能 )

各ジェネレータールールは、前提結果で 構成されます(ルート放棄ルール属性ドロップルールを除き、ユーザーが指定できない事前定義された結果があります)。

条件付きルートルールを除くすべてのルールには、その前提内の入力ノードの概念(または単に入力概念)への参照が含まれています。すべてのルール前提には、オプションの条件関数も含まれています。

ルールの結果には、通常、外部テンプレート(つまり、同じモデルまたは異なるモデルでルートノードとして宣言されたテンプレート)またはいわゆるインラインテンプレート(条件付きルートルールとルートマッピングルールは外部テンプレートへの参照のみを持つことができます)への参照が含まれます。結果には他にもいくつかのバージョンがあります。

次のスクリーンショットは、ジェネレーターモデルの内容とマッピング設定の例を示しています。undefined

Gug mapping configuration

マクロ

テンプレート内のコードはマクロを通してパラメーター化することができます。ジェネレーター言語は 3 種類のマクロを定義します。

  • プロパティマクロ - プロパティ値を計算します。

  • 参照マクロ - 参照のターゲット(ノード)を計算します。

  • ノードマクロ - 生成時にテンプレートの塗りつぶしを制御するために使用されます。ノードマクロにはいくつかのバージョンがあります。LOOP-macro はその一例です。

マクロは特別な種類のいわゆるアノテーション概念を実装しており、テンプレートコード内で(マクロの種類に応じて)プロパティセル、参照セル、またはノードセルをラップできます。

コードの折り返し(つまり、新しいマクロの作成)は、Ctrl + Shift + M を押すか、「マクロの作成」インテンションを適用することによって行われます。

次のスクリーンショットは、プロパティマクロの例を示しています。undefined

Gug property macro sample

マクロ関数およびその他のパラメーター化オプションは、インスペクタービューで編集されます。たとえば、プロパティマクロでは、生成時にプロパティの値を提供する value 関数を指定する必要があります。上記の例では、出力クラスノードは入力ノードと同じ名前を取得します。

ジェネレーター言語のすべての関数のノードパラメーターは、常に、変換が現在適用されているコンテキストノード(入力ノード)を表します。

いくつかのマクロ(LOOP および SWITCH マクロなど)は入力ノードを新しいものと置き換えることができるため、後続のテンプレートコード(たとえばそれらのマクロによってラップされるコード)は新しい入力ノードに適用されることになる。

外部テンプレート

外部テンプレートは、ジェネレーターモデルのルートノードとして作成されます。

MPS には 2 種類の外部テンプレートがあります。

それらの 1 つはルートテンプレートです。ジェネレーターモデルで作成されたルートノードは、このノードがジェネレーター言語の一部でない限り(つまり、マッピング構成がルートテンプレートで はない場合)、ルートテンプレートとして扱われます。ルートテンプレートは、通常のルートノードとして作成されます(モデルのポップアップのルートノードの作成メニューを使用)。

次のスクリーンショットは、ルートテンプレートの例を示しています。

Gug root template sample

このルートテンプレートは、入力ノード(ドキュメント)をクラスbaseLanguage)に変換します。ルートテンプレートヘッダーは作成時に自動的に追加されますが、入力ノードの概念はユーザーが指定します。

MPS はマクロ関数のコード内で静的型チェックを実行できるため、入力の概念を指定することをお勧めします。

ルートテンプレート(参照)は、条件付きルートルールおよびルートマッピングルールの結果として使用できます。(条件付きルートルールで使用する場合、入力ノードは使用できません)。

2 番目の種類のテンプレートはジェネレーター言語で定義され、その概念名は「TemplateDeclaration」です。これは、ルートノードの作成メニューのテンプレート宣言アクションを介して作成されます。

Gug new template declaration menu

次のスクリーンショットはテンプレート宣言の例を示しています。

Gug template declaration sample

実際のテンプレートコードは、テンプレートフラグメントに「ラップ」されています。テンプレートフラグメントの外側のコードは変換に使用されず、コンテキストとして機能します(たとえば、Java クラスを持つことができますが、そのメソッドの 1 つだけをテンプレートとしてエクスポートします)。

テンプレート宣言には、ヘッダーで宣言されたパラメーターを含めることができます。パラメーターには、#generation コンテキストからアクセスできます。

テンプレート宣言は、織り、縮小、パターンのルールの結果として使用されます。また、INCLUDE-macro(パラメーターのないテンプレートの場合のみ)に含まれているテンプレートとして、または CALL-macro の呼び出し先としても使用されます。

テンプレートスイッチ

テンプレートスイッチは、テンプレートコードの特定の場所で 2 つ以上の代替変換が可能な場合に使用されます。その場合、代替を許可するテンプレートコードは、テンプレートスイッチを参照する SWITCH マクロにラップされます。テンプレートスイッチは、ルートノードの作成メニューを介してジェネレーターモデルのルートノードとして作成されます(このコマンドは、上のメニュースクリーンショットに表示されています)。

次のスクリーンショットは、テンプレート切り替えの例を示しています。

Gug template switch sample

Ant から生成する

Ant MPS ジェネレータータスクは、ビルドスクリプトから構成可能なプロパティ(並列、スレッド、インプレース、警告)を公開します。ビルド言語は、内部で Ant 生成タスクを使用して、ビルドプロセス中にモデルを変換します。このタスクは、ジェネレーター設定ページでおなじみのパラメーターを公開するようになりました。

  • 厳格生成モード

  • 構成可能な数のスレッドによる並列生成

  • インプレース変換を有効にするオプション

  • 生成警告 / エラーを制御するオプション

これらのオプションは BuildMps_GeneratorOptions の概念を使用してビルド言語でも公開されているため、ビルドスクリプトでプロセスをより細かく制御できます。

サンプル

さらに実用的な体験をする時が来たと感じたら、ジェネレーターのデモをチェックしてください。
デモには、上記のすべての概念の使用例が含まれています。

関連ページ:

ジェネレータークックブック

この文書は、MPS ジェネレーターに関する最も一般的な質問に対する回答を提供することを目的としています。代わりにジェネレーターのドキュメントを調べてジェネレーターデモをチェックすることもできます。ジェネレーターはどのようにルールを処理しますか? :生成は、入力モデルを徐々に出力モデルに変換します。出力モデルは、TextGen を使用してテキストに変換する場合としない場合があります。生成プロセス自体はステップで構成されています。各ステップには 3 つのフェーズがあります。マッピング前スクリプトの実...

TextGen

TextGen 言語アスペクト:導入 TextGen 言語の側面は、モデルからテキストへの変換を定義します。モデルを直接テキスト形式に変換する必要があるたびに便利です。この言語には、テキストを印刷し、ノードをテキスト値に変換し、出力に適切なレイアウトを与えるための構造が含まれています。操作 append コマンドは変換を実行し、結果のテキストを出力に追加します。found error コマンドを使用して、モデルの問題を報告できます。with indent コマンドは、インデントが増加したブロックの境界を定...

SModel 言語

SModel 言語の目的は、MPS モデルを照会および変更することです。これにより、モデルのノード、属性、プロパティ、リンク、その他の多くの重要な品質を調査できます。言語は、言語のいくつかの異なる側面(アクション、リファクタリング、ジェネレーター)をエンコードして、最も目立つものに名前を付けるために必要です。通常、jetbrains.mps.lang.smodel 言語を BaseLanguage と組み合わせて使用します。null 値の扱い:SModel 言語は、null 値を非常に安全な方法...

世代計画

世代計画:生成計画を使用すると、開発者は自分のモデルに望ましい生成順序を明示的に指定でき、生成プロセスをより適切に制御できます。目的大規模プロジェクトでは、相互ジェネレーターの優先順位を指定するのが面倒になるかもしれません。さらに、優先順位を指定するためには、適切な相互依存関係を宣言することによって関係言語が互いについて知る必要があります。これは、(時に望ましい)独立性を破ります。生成計画は、生成ステップの適切な順序付けの責任を単一の場所、つまり生成計画にまとめます。これにより、言語設計者は、

ジェネレーターデモ

ジェネレーターチュートリアル:MPS で言語ジェネレーターを定義および拡張するプロセスをガイドする、更新されたジェネレーターチュートリアルへようこそ。チュートリアルは 7 つのパートで構成されており、徐々に複雑さが増しています。すべてのデモは、同じ根底にあるストーリー、つまり Java Swing コンポーネントへの XML コードの変換を共有しています。各デモは前のデモに基づいており、より高度な(または場合によっては単に異なる)機能、プラクティス、アプローチを示しています。すべてのデモは論理的...

データフロー

言語のデータフローの側面では、到達不能なステートメントの検索、未使用の代入の検出、変数が読み込まれる前に初期化されていない可能性があるかどうかの確認などを行うことができます。また、「抽出メソッド」リファクタリングなど、いくつかのコード変換を実行することもできます。データフロー分析のほとんどのユーザーは、その内部作業の詳細には関心がありませんが、必要な結果を得ることには関心があります。彼らはどのステートメントに到達できないのか、それが初期化される前に何を読むことができるのかを知りたがっています。こ...