MPS 2019.1ヘルプ

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

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

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

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

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

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

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

テンプレートベースのモデル変換フェーズは、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はスコープ(通常はルートノード)に「含まれる」名前を生成するように最善を尽くします。(入力モデルやジェネレータモデルの変更により)名前が再計算されても、範囲外の他の名前には影響しません。context nodeパラメータはオプションですが、生成の安定性を保証するために指定することをお勧めします。

生成された名前の一意性は、生成セッション全体を通して保証されます。
このサービスを使用して生成されなかった名前と衝突することはまだ可能です。

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

$SWITCH$マクロを使用して列挙型データ型をJava列挙型に縮小する必要があるのが通常最善の選択肢です。

Generator1
Generator2

is()メソッドを使用して、実際の列挙データ型の等価性がテストされる方法に注目してください。

Generator3

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

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

cp iface

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

生成モデルの間に、木の形をしています(抽象構文木、基本的な考え方を見てください)、生成されたモデルはまた木です。通常、ルートノードはルートノードに生成され(たとえば、ロボットスクリプトからJavaクラスに)、非ルートノードは非ルートノードに生成されます(たとえば、ロボットステップコマンドからJava ブロックステートメントへ)。ルートマッピング規則のテンプレートは生成されたモデルの開始点を表し、コンテキストを保持して実際の生成内容をテンプレートフラグメントマークで示すことができる縮小テンプレートとは異なり、テンプレートコンテキストを指定することはできません。

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

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

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

テンプレート内のテンプレートフラグメントは、どのノードが現在の入力ノードを置き換えるかを示します。テンプレートフラグメントはテンプレート内の1つのノードにしかアタッチできませんが、ジェネレータテンプレートには複数のテンプレートフラグメントを含めることができます。ただし、すべてのフラグメントが同じ親で同じロールのノードにアタッチされている場合です。このようにして、単一の入力ノードに対して複数のノードを生成することができます。

templateFragments

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

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

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

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

単に概念のためのルートマッピング規則を作成し、おそらくそれをさらに条件で制限します。この規則は、ルートノードを生成するため、ルートと呼ばれます。ルートとして入力されるとは限りません。

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

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

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

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

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

accessoryGeneration

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

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

マッピングラベルは、マッピング設定(例: 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)です。ノードとその生成されたノード間のマッピングをマッピングラベルに格納するようにジェネレータに明示的に指示する必要があります。テンプレートフラグメントとノードマクロによって、ユーザーは生成されたノードを保存するマッピングラベルを指定できます。

RG(R)に縮小するとき、G(R)の参照マクロは、ラベルおよび入力によるgenContext.getの出力でジェネレータコンテキストを呼び出すときにNをキーとして使用して、マッピングラベルからG(N)を取得できます。

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

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

最初のオプションは、過渡モデルの保存を有効にすることです: MPSが生成中に作成する中間モデルは保存され、あなたのスクリーンの左側のプロジェクト・ビューパネルでそれらにアクセスすることができます:

transient1
transient2

保存されたトランジェントモデルを使用すると、生成プロセスのさまざまな段階でモデルがどのように見えるかを調べることができます。

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

tracer1
transient2

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

Trace2
Trace1

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

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

genplan1
genplan2

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

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

Priorities2

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

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

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

Generator101

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

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

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

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

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

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

TextGenは何に使用しますか?

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

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

TextGenはルートノードごとに1つのファイルしか許可しません。また、コンセプトごとに1つのTextGenコンポーネントしか持てません。代わりに、柔軟性をジェネレータにエンコードする必要があります。ジェネレータがノードの複数のコピーを作成することを手に入れます。多分異なる概念の新しいノードに包みます。これらの新しいノードは、希望するモデルからファイルへの変換を実行するようにTextDefを定義しています。

最終更新日: 2019年7月5日

関連ページ:

生成プログラム

MPSジェネレーターに関する素早い使い方ドキュメントはジェネレータクックブックをチェックしてください。導入、概要、ジェネレーターモジュール、新しいジェネレータを作成する、ジェネレーターのプロパティー、ジェネレーター、変換、マッピング設定、ジェネレータルール、マクロ、外部テンプレート、テンプレートスイ...

ジェネレーターデモ

ジェネレータチュートリアル:更新されたGenerator Tutorialへようこそ。MPSで言語生成プログラムを定義および拡張する手順を案内します。チュートリアルは7つの部分から成り、徐々に複雑さが増しています。すべてのデモは同じ基本的な物語 -Java SwingコンポーネントへのXMLコードの...

依存関係を正しくする

目的、便利なキーボードショートカット、ソリューション、ソリューションモデル、プロジェクトへの外部Javaクラスとjarの追加 - ランタイムソリューション、言語、言語モデル/側面、生成プログラム、目的:モジュールとモデルは通常、さまざまなタイプの依存関係のネットワークによって相互接続されています。M...

基本的な考え方

この章では、MPSの基本的な概念(ノード、概念、および言語)について説明します。これらはMPSがどのように機能するかを正しく理解するための鍵です。それらはすべて他のものと組み合わされたときに意味をなさないため、それらについてすべて一緒に話さなければなりません。このセクションでは、各要素の本質について...

構造

MPSはあなたの意図した言語のための文法を定義することからあなたを解放するため、明らかにあなたの言語の構造を指定するための異なる方法を必要とします。これは構造言語が便利になるところです。それはあなたに言語構造を定義するためのすべての手段を与えます。前に説明したように、MPSでコーディングするときは、...

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

ジェネレータユーザガイドデモ7:この最後のデモでは、デモ3に戻り、目的とする機能を少し異なる方法で実装します。そのため、MPSジェネレーターの別の領域 - ウィービング規則とルートマッピング規則 - を探ります。ここで構築するデモ2では、次のようなjavaステートメントを生成していました。conta...