MPS 2023.3 ヘルプ

生成プログラム

導入

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

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

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

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

たとえば、baseLanguageTextGen アスペクトは、次の場所に *.java ファイルを生成します。

< ジェネレーター出力パス >\< モデル名 >\< クラス名 >.java

where:

ジェネレーター出力パス - 入力モデルを所有するモジュールで指定されます。

モデル名 - '.' を置き換えることによって作成されたパスセグメントです。入力モデルの名前にファイル区切り文字を使用します。

概要

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

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

ジェネレーターモデルは、モデルステレオタイプ「ジェネレーター」(モデル名の後に < name >@ generator として表示されます) によって通常のモデルと区別されます。

以下のスクリーンショットは、例として smodel 言語のジェネレーターモジュールを示しています。

gug-generator-module.png

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

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

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

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

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

モジュールとして、ジェネレーターは他のモジュールに依存したり、使用言語開発キットを使用したりできます ( モジュールメタ情報を参照)。

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

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

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

ジェネレーター

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

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

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

変換

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

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

マッピング設定

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

ジェネレータールール

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

ジェネレータールールには次の 6 種類があります。

  • 条件付きルート規則

  • ルートマッピング規則

  • 製織規則

  • 削減ルール

  • パターンルール

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

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

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

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

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

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

gug-mapping-configuration.png

マクロ

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

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

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

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

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

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

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

gug-property-macro-sample.png

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

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

一部のマクロ(LOOP や SWITCH-macro など)は、入力ノードを新しいものに置き換えることができるため、後続のテンプレートコード(つまり、これらのマクロによってラップされるコード)が新しい入力ノードに適用されます。

外部テンプレート

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

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

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

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

gug-root-template-sample.png

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

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

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

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

gug-new-template-declaration-menu.png

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

gug-template-declaration-sample.png

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

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

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

テンプレートスイッチ

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

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

gug-template-switch-sample.png

Ant から生成する

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

  • 厳格生成モード

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

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

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

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

MPS 独自の生成タスクと通常の Ant の javac タスクに加えて、MPS は、MPS IDE から認識される Make プロセスに対応する新しい mps.make タスクを提供します。モデルからコンパイル済みコードへの完全な移行を担当します。このタスクは、コード生成とコンパイルの両方を組み合わせます。MPS は、モジュールのクラスローディングの目的でコンパイル済みのクラスを必要とするだけでなく、IDE と非 IDE の両方のコマンドラインビルドを同様で信頼性の高いものにするため、時間を節約できます。

サンプル

さらに実用的な体験をする時が来たと感じたら、ジェネレーターのデモをチェックしてください。

デモには、上記のすべての概念の使用例が含まれています。

関連ページ:

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

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

ジェネレーターアルゴリズム

ジェネレーターアルゴリズム:入力モデルからターゲットアセットを生成するプロセス(生成セッション)には、5 つのステージが含まれます。関与する必要があるすべてのジェネレーターの定義、変換の優先順位を定義する、段階的なモデル変換、テキストを生成してファイルに保存する (出力モデルの各ルートに対して)、後処理アセット: コンパイルなど、このプロセスの最初の 3 段階について詳しく説明します。関与するジェネレーターの定義必要なジェネレーターを定義するために、MPS は入力モデルを調べて、その中で使用さ...

TextGen

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

世代計画

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

ジェネレーターデモ

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

データフロー

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