MPS 2026.1 ヘルプ

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

この文書は、MPS ジェネレーターに関する最も一般的な質問に対する回答を提供することを目的としています。代わりにジェネレーターのドキュメントを調べてジェネレーターデモをチェックすることもできます。

ジェネレーターはどのようにルールを処理しますか?

生成は、入力モデルを徐々に出力モデルに変換します。出力モデルは、TextGen を使用してテキストに変換する場合としない場合があります。生成プロセス自体はステップで構成されています。各ステップには 3 つのフェーズがあります。

  1. マッピング前スクリプトの実行

  2. テンプレートベースのモデル変換

  3. マッピング後スクリプトの実行

テンプレートベースのモデル変換フェーズは、1 つ以上のマイクロステップで構成されます。マイクロステップとは、入力モデルを一時的な(出力)モデルに変換する、1 回のパスでのモデル変換のことです。生成ステップ中、ジェネレーターはモデルを反復処理し、このステップに関与するすべての言語のジェネレーター内で、入力モデルのノードに適用可能なルールを検索します。適用可能なルールが見つからない場合、生成ステップは停止します。次の生成ステップ(存在する場合)は、前の生成ステップの出力モデルを入力として受け取ります。

ジェネレーターのドキュメントでジェネレーターのアルゴリズムの完全な説明をチェックすることができます。

一つの言語に対してさらに多くのジェネレーターを使うことができますか?

いいえ、MPS は現時点では言語ごとに 1 つのジェネレーターしか許可しません。1 つの言語に対して複数のジェネレーターが必要な場合は、自分の言語を拡張する空の言語を作成し、それぞれの拡張言語で目的の代替ジェネレーターを定義することをお勧めします。

ジェネレーターごとに複数のマッピング設定を持つことができますか?

はい、生成プロセス中はすべて同じものとして扱われます。さらに、各マッピング構成で 生成プロセスの優先順位を個別に指定できるため、生成をより柔軟に調整できます。

単一のソースから複数のターゲットを生成する方法

同じコードベースから複数のターゲットプラットフォーム用のコードを生成することができます。それを達成するには、少なくとも 2 つの方法があります。

  • 異なるプラットフォームのすべての生成ルールを単一のジェネレーターに配置し、おそらく仮想パッケージと複数のマッピング構成に論理的に分離し、各ルールの条件を使用して、現在選択されているターゲットに基づいてルールをアクティブ化します。開発者は、コードにフラグを設定して、目的のターゲットプラットフォームを示します

  • 開発者は、使用言語にはジェネレーターを直接用意せず、各ターゲットプラットフォーム向けに、元の言語を拡張した別のの言語でジェネレーターを提供します。開発者は、適切な拡張言語をインポートすることで、目的のターゲットプラットフォームを選択します。

テンプレートにはどのようなマクロがありますか?

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

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

  • ノードマクロ - 生成時にテンプレートの塗りつぶしを制御するために使用されます。

    • $IF$ - 条件付き生成

    • $CALL$ - 現在位置に別のテンプレートを挿入し、それを現在のノードに渡して処理します

    • $LOOP$ - ノードのコレクションを反復処理し、反復ごとに現在のノードを設定します

    • $COPY_SRC$ - 指定されたノードをコピーしてラップされたノードを置き換えます。処理中に、コピーされたノードとその子に削減規則が適用されます。

    • $COPY_SRCL$ - 指定されたノードのコレクションをコピーし、折り返したコードを置き換えます。処理中に、コピーされたノードとその子に削減規則が適用されます。

    • $MAP_SRC$ - 折り返しコード内で現在のノードとして使用されるノードを設定します

    • $MAP_SRCL$ - ラップされたコード内で、各ノードが順番に現在のノードとして使用されるノードのコレクションを設定します。

    • $SWITCH$ - 複数の選択肢から生成に使用するテンプレートを選択します

    • $LABEL$- ラップされたノードをマッピングラベルに格納して、他のマクロで簡単に検出できるようにします

    • $VAR$- 値を変数に設定します。変数は、ラップされたノードで genContext.varName を介してアクセスできます。

    • $TRACE$- ラップされたノードの元のノードをトレースバックするために必要な情報を格納し、ソースノードと結果の生成されたテキスト間のマッピングを trace.info ファイルに格納します。一時モデルの保存がオンの場合、これによりデバッグ起点ノードを表示オプションが有効になります。一時モデルのポップアップメニュー項目

    • $WEAVE$ - 特定の製織規則を呼び出す

    • $INSERT$ - 現在位置にノードを出力モデルに挿入します

ユーティリティクラスはどこに配置すればよいですか ?

ジェネレーター内に新しいモデルを作成します。ジェネレーターステレオタイプがアタッチされていないことを確認してください。モデルは通常、BaseLanguage に依存して、クラスを作成できるようにする必要があります。その後、元のジェネレーターモデルはユーティリティモデルをインポートする必要があります。

ランタイムクラスはどこに配置すればよいですか ?

依存関係を正しくするプロジェクトへの外部 Java クラスと jar の追加 - ランタイムソリューション」セクションに従って、生成コードが依存するクラスとライブラリは、別々のランタイムソリューションに入れる必要があります。

一意の名前を生成する方法

genContext パラメーターを使用します。これにより、ジェネレーターコンテキストオブジェクトにアクセスして、以下を呼び出すことができます。

  • からの固有の名前 <base name> 文脈で <node>

  • ベース名 - 生成された名前の一部である必要がある任意の文字列です

  • コンテキストノード - 指定されている場合、MPS はスコープ (通常はルートノード) 内に「含まれる」名前を生成するよう最大限努力します。その後、名前が再計算された場合 (入力モデルまたはジェネレーターモデルの変更による)、スコープ外の他の名前には影響しません。コンテキストノードパラメーターはオプションですが、生成の安定性を保証するために指定することをお勧めします。

    生成された名前の一意性は、生成セッション全体を通じて保護されます。

    このサービスを使用して生成されなかった名前との衝突は引き続き発生する可能性があります。

列挙データ型を生成する方法

列挙型データ型を Java 列挙型に縮小する必要がある場合、通常は $SWITCH$ マクロを使用するのが最良のオプションです。

Generator2.png

is() メソッドを使用して実際の列挙データ型が等しいかどうかをテストする方法に注意してください。

Generator3.png

生成された Java クラスのパッケージを変更する方法

複雑な Java コードを生成する場合、Java クラス、インターフェース、列挙型をパッケージに編成する必要があることがよくあります。デフォルトでは、MPS ジェネレーターは、生成された Java コードのパッケージの構造に MPS モデルの構造を反映します。各 BaseLanguage モデルは、同じ名前の Java パッケージに変換されます。生成された Java パッケージの構造を操作する必要がある場合は、Classifier コンセプトの packageName プロパティを使用してください。このプロパティは、ルート分類子で使用できます。

cp_iface.png

ルートマッピング規則と縮小規則の違いは何ですか?

生成時には、ツリー構造(抽象構文木、基本的な考え方を参照)を持つモデルが、同じくツリー構造を持つ生成モデルに変換されます。通常、ルートノードはルートノードに(たとえば、ロボットスクリプトは Java クラスに)、非ルートノードは非ルートノードに(たとえば、ロボットステップコマンドは Java BlockStatement に)生成されます。そのため、ルートマッピングルールのテンプレートは生成モデルの開始点を表し、テンプレートコンテキストを指定することはできません。一方、リダクションテンプレートはコンテキストを保持し、テンプレートフラグメントマークで実際の生成内容を示すことができます。

未変換の根はどうなりますか?

適用可能な変換規則がないルートは、そのまま次の生成ステップに持ち越されます。

単一のノードに対して複数のノードを生成する方法

テンプレート内のテンプレートフラグメントは、現在の入力ノードを置き換えるノードを示します。テンプレートフラグメントは、テンプレート内の単一のノードにのみ関連付けることができますが、ジェネレーターテンプレートには複数のテンプレートフラグメントを含めることができます。ただし、それらはすべて同じ親ノードにある同じロールのノードに関連付けられている必要があります。このようにして、単一の入力ノードに対して複数のノードを生成することができます。

templateFragments.png

マクロの編集がなぜ奇妙なのでしょうか。

実際、ジェネレーターマクロとテンプレートフラグメントマークは、最初は少し編集するのが面倒です。しかし、それらがどのように機能するかの基本原則を理解すれば、効率的に使用することができます。

マクロはノード / プロパティ / 参照属性として実装されています(構造の章の属性セクションを参照)。そのため、それらは任意の言語で使用することができ、その言語で使用可能になるための事前サポートを必要としません。MPS では任意の言語を生成対象として使用できるため、これは重要です。マクロはそれらがラップするノードに付加された属性です。マクロで囲まれたノードを削除または置換すると、そのマクロも削除されるため、新しいノードにアタッチするにはマクロを再入力する必要があります。推奨される方法は、最初にテンプレートのコードを入力してからマクロを追加することです。マクロで囲まれたノードを変更する必要がある場合は、新しいノードのマクロにコピーペーストすることによって、少なくとも古いノードのマクロのインスペクターウィンドウの内容を保存できます。

非ルートノードに対してルートノードを生成するにはどうすればよいですか?

概念のルートマッピングルールを作成し、必要に応じて条件を追加してさらに制限します。このルールはルートノードを生成するため「ルート」と呼ばれますが、必ずしも入力としてルートを受け取るという意味ではありません。

あるいは、ブール述語の評価に基づいてルートノードを挿入する条件付きルート規則、または入力モデルをインスペクションして必要に応じてルートノードを作成する前処理スクリプトを使用することもできます。

不要になった根をモデルから削除する方法

ルートノードは、ルートマッピングルールを使用して変換されると自動的に削除されます。直接変換されていないルートの場合は、次の生成ステップに伝播されないようにするために放棄ルート規則を使用します。

アクセサーリモデルのノードに対してノードを生成する方法

アクセサーリモデル内のノードは、ジェネレーターによってはまったく処理されません。アクセサーリモデル内のノードに基づいてノードを生成するために、条件付きルート規則または前処理スクリプトを利用できます。

accessoryGeneration.png

次いで、削減規則を使用して、「挿入されたノード」を所望のゴール言語にさらに生成することができます。

マッピングラベルの使い方

マッピングラベルは、マッピング構成(たとえば、main)で定義されます。その後、$LOOP$、$LABEL$、$COPY_SRC$ などのマクロで格納したいノードをラップすることで、ラベルを設定する必要があります。

生成中に参照を処理する方法

生成された参照に適切なターゲットノードを設定するには、参照マクロを使用する必要があります。通常、参照マクロはマッピング ラベルと一緒に使用します。

ここでの基本的な作業は、ノード N を指す参照 R に対して、R から生成された参照 G(R) が、N から生成されたノード G(N) を指すようにする必要があることです。

R-> N の場合、N は G(N) に生成され、R は G(R) に生成され 、G(R)-> G(N)

マッピングラベルは辞書として機能し、ノードはキーとして、またそれらが値として生成されたものは何でも格納します。この例では N-> G(N) です。ノードとその生成されたノード間のマッピングをマッピングラベルに格納するようにジェネレーターに明示的に指示する必要があります。テンプレートフラグメントとノードマクロによって、ユーザーは生成されたノードを保存するマッピングラベルを指定できます。

G(R)R を低減する場合、G(R) に参照マクロは、ラベルおよび入力によって genContext.get 出力に発生コンテキストを呼び出すキーとして N を使用してマッピングラベルから G(N) を取り出すことができます。

ジェネレーターチュートリアル第 7 章では、ラベルのマッピングについて詳しく説明しています。

生成プロセスをデバッグできますか?

最初のオプションは、一時モデルの保存を有効にすることです。MPS が生成中に作成する中間モデルは保持され、画面の左側にあるプロジェクトビューパネルからアクセスできます。

transient1.png
transient2.png

保存された過渡モデルを使用すると、生成プロセスのさまざまな段階でモデルがどのような状態だったかを調べることができます。

2 番目の選択肢はジェネレータートレーサツールを使うことです。このツールでは、Save transient models オプションも on に設定する必要があります。ジェネレータートレーサツールを使用すると、選択したノードの生成プロセスを詳細に調査することができます。元のモデルまたは一時的なノードのいずれかでノードを選択すると、コンテキストメニューに生成プロセスを前方または後方にトレースするためのオプションが表示されます。その結果、生成中に特定のノードが通過したすべてのステージとその生成に影響を与えるルールにアクセスできるツリー状のレポートが得られます。

tracer1.png
transient2.png

さらに、$TRACE$ ジェネレーターマクロには、トレース用にテンプレートの一部をマークするオプションがあり、コンテキストメニュー起点ノードを表示オプションを使用して、一時モデルで生成されたノードから元のノードに戻ることができます。> 言語デバッグメニュー:

Trace2.png
Trace1.png

実際の生成手順はどのようにしてわかりますか?

ジェネレーターのコンテキストメニューからジェネレーションプランの表示アクションを使用します。これにより、計画されているすべての生成フェーズを示し、各フェーズで実行されるマッピング構成を一覧表示する詳細なレポートが提供されます。

genplan1.png
genplan2.png

ジェネレーターを実行する順序を指定できますか?

ジェネレーターのモジュールプロパティダイアログジェネレーターの優先順位タブでは、2 つの異なるマッピング構成間の順序付けルールを指定できます。

Priorities2.png

より複雑なシナリオでは、生成計画の新機能によりジェネレータープロセスを完全に制御できます。

ジェネレーターを起動する前にモデルにエラーがないことを確認する方法

モデル / 言語 / ソリューションでモデル(言語 / ソリューション)のコンテキストメニューアクションを実行して、チェックします。

Generator101.png

環境設定 -> ビルド、実行、デプロイ -> ジェネレーター -> 生成前にモデルのエラーをチェック構成フラグは、ジェネレーターがトリガーされるたびにモデルチェッカーを自動的に実行するかどうかを指定します。

既存のジェネレーターを拡張する方法

従うべき 1 つの規則があります - あなたの拡張ジェネレーターが拡張されたものの前に実行されることを確認する - ジェネレーター順序優先順位ダイアログでより高い優先順位を与えてください。

拡張可能なジェネレーターを構築する方法

ジェネレーターを拡張することで、拡張機能は元の言語の意味を変更することができます。MPS ジェネレーターは設計によって拡張可能です - それはすべての関係言語からすべてのジェネレータールールとマッピング設定を解決して、グローバルな世代計画を構築します。プロジェクトにアタッチされている言語には、その規則が含まれます。プランは、マッピング構成で表現された相互の相対的優先順位に基づいてジェネレータールールの実行順序を指定します。これにより、言語拡張機能は、最適な生成フェーズに独自の目的の生成規則を挿入することができます。優先順位はマッピング構成間の相対的な順序付けの集まりとして表現されるため、言語拡張は機能するために生成に関与する他のすべての生成子について知る必要はありません。潜在的な(そしてまれな)衝突が検出され、解決するために開発者に任されます。いったん作成されると、生成計画は、相互に独立した規則のために潜在的に基礎となるハードウェアの並列処理を利用する可能性があるジェネレーターを繰り返し呼び出すために使用されます。

追加の削減規則を提供することは、言語を拡張するための 1 つの方法です。ジェネレータースイッチの使用は別の選択肢です。親言語がジェネレータースイッチを使用して正しいリダクションルールを選択する場合、言語拡張はリダクションルールを選択するための追加ロジックでそのジェネレータースイッチを拡張します - 通常は拡張言語によって提供された新しいルールを含みます。

TextGen を何に使用すればよいですか ?

ジェネレーターがモデル間の変換を実行している間、TextGen はテキストへのマッピングを行います。これは通常、生成の最後のステップであり、ジェネレーターによって完全に管理されています。根はジェネレーターによって選択され、ファイルに変換されます。TextGen は言語設計者に意図的にほとんど柔軟性を提供していません。それはジェネレーターで、生成プロセスは主に構成され処理されるべきです。TextGen の制限を回避する必要があると感じる場合は、おそらく間違ったやり方で試してください。ジェネレーターは最も柔軟性がある場所です。

生成された出力を別の場所にコピーするにはどうすればよいですか?

jetbrains.mps.lang.makeup 言語の CopyOutcome 属性を使用して、ノード用に最終的に生成されたテキストが指定された場所にコピーされるようにすることができます。

ルートノードごとに複数のファイルを生成する方法

TextGen では、ルートノードごとに 1 つのファイルしか作成できません。また、概念ごとに 1 つの TextGen コンポーネントしか作成できません。柔軟性はジェネレーターに組み込むべきです。ジェネレーターにノードの複数のコピーを作成させ、それぞれを異なる概念の新しいノードでラップさせます。これらの新しいノードには、目的のモデルからファイルへの変換を実行するための TextDef が定義されます。

2026 年 5 月 06 日

関連ページ:

生成プログラム

導入:ジェネレーターは、言語の概念の表示的意味論を定義する言語仕様の一部です。MPS はモデル間変換アプローチに従います。MPS ジェネレーターは、入力言語でエンコードされた構成から出力言語でエンコードされた構成への変換を指定します。モデル間変換のプロセスには多くの中間モデルが含まれ、最終的には sn 出力モデルが生成されます。このモデルでは、すべての構成はすでに意味が別の場所で定義されている言語になります。たとえば、baseLanguage のほとんどの概念 (クラス、メソッドなど) は「機械が...

ジェネレーターデモ

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

依存関係を正しくする

目的:モジュールとモデルは通常、様々な種類の依存関係のネットワークによって相互に接続されています。MPS プロジェクト構造のページで説明されているモジュールとモデルの基本原則と分類を理解した上で、さらに深く掘り下げて詳細を見ていきましょう。MPS で依存関係を正しく取得することは、経験の浅いユーザーやベテランのベテランの間でもフラストレーションの頻繁な原因です。このページは、問題を一度に解決することを目的としています。さまざまなモジュールと依存関係の種類によってセクションに分類されたすべての関...

基本的な考え方

この章では、基本的な MPS の概念であるノード、概念、言語について説明します。これらは、MPS の仕組みを正しく理解するための鍵となります。これらはすべて、他の要素と組み合わせることで初めて意味を成すため、すべて一緒に説明する必要があります。このセクションの目的は、各要素の本質を説明することです。詳細については、ノード、概念 (構造言語)、言語 (プロジェクト構造) に関するセクションを確認することを検討してください。抽象構文木 (AST):MPS は、テキスト形式を避けることで他の多くの言語...

構造

MPS では、意図する言語の文法を定義する必要がないため、当然ながら、言語の構造を指定するための別の方法が必要になります。ここで構造言語が役立ちます。構造言語は、言語構造を定義するためのあらゆる手段を提供します。先に記述されていたように、MPS でコーディングする場合、実質的に AST を直接構築することになるため、言語の構造では、AST を構築するために使用する要素、つまり構成要素を指定する必要があります。プロパティ、参照、および子供: レンガをコンセプトと構造言語が公開の概念と概念インターフ...

ジェネレーターユーザガイド Demo7

ジェネレーターユーザガイドデモ 7:この最後のデモでは、デモ 3 に戻り、目的とする機能を少し異なる方法で実装します。そのため、MPS ジェネレーターの別の領域 - ウィービング規則とルートマッピング規則 - を探ります。ここで構築するデモ 2 では、次のような java ステートメントを生成していました。container.add(new JButton());Swing コンポーネントを作成してアプリケーションのコンテンツペインに追加します。デモ 7 では、デモ 3 と同様に、コンポーネント...