MPS 2020.3 ヘルプ

スコープ

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

2 つの方法

すべての参照は許可されたターゲットのセットを知る必要があります。これにより、ユーザーが参照の値を入力しようとしているときはいつでも MPS が完了メニューに値を入力することができます。既存の参照がそのセットに対して検証され、範囲外の要素を参照している場合は無効としてマークされます。デフォルトでは、参照に対して有効範囲が定義されていない場合、現在のモデル内およびインポートされたモデル内のすべてのターゲットが有効範囲内にあるため、参照に使用できます。

MPS はスコープを定義する 2 つの方法を提供します。

  • 継承スコープ

  • 参照スコープ

継承スコープではモデル内のノードの階層に従ってスコープを徐々に構築することができますが、参照スコープでは低いセレモニーが提供されます。

継承スコープ

最初に、スコープ解決の新しい階層(継承)メカニズムについて説明します。 このメカニズムは、スコープ解決を ScopeProvider を実装する祖先に委譲します。

  1. MPS は、ScopeProvider を実装し、現在の種類のスコープを提供できる参照ノードに最も近い祖先の検索を開始します。

  2. ScopeProvidernull を返す場合、MPS はより遠い祖先の検索を続行します。

  3. ScopeProvider は次のことができます
    • スコープ実装をビルドして返す (これらの詳細)

    • 親スコープに委譲する

    • 独自の要素を親スコープに追加します

    • 親スコープから要素を非表示にする (スコープを操作する方法の詳細については後で説明します)

親スコープを取得するための呼び出しは、ScopeProvider 内から明示的に行う必要があります。

私たちは、このように InputFieldReference の InputField のための検索は、ノードとそれらのリストを構築するためにその祖先に依存しています。

Sc1

Sc2

の InputField を検索 InputFieldReference ためのスコープが継承されることを指定したら、電卓が ScopeProvider であることを示す必要があります。これにより、Calculator は、その子孫として配置されるすべての InputFieldReferences のスコープを構築する際に発言権を持つようになります。

Sc3

この場合の電卓 は、InputField のスコープを照会するたびに、すべての InputField のリストを返す必要があります電卓 の動作の側面では、getScope() メソッドをオーバーライド( Control + O)します。

Co1111

スコープが未解決のままの場合は、スコープ(jetbrains.mps.scope)を含むモデル(Control + R)をインポートする必要があります。

Sc5

getScope() メソッドは 2 つのパラメーターを取ります。

  • 種類 - 参照の可能なターゲットの概念

  • - 実際の参照は、ノードの子孫の中にあるため、要求が来た現在の(この)ScopeProvider の子ノード

一部の機能をエンコードする必要があるため、BaseLanguage も必要です。jetbrains.mps.langノードをクエリするには、smodel 言語をインポートする必要があります。これらの言語は自動的にインポートされているはずです。そうでない場合は、Control + L ショートカットを使用してインポートできます。

Sc6

これで、スコープ定義コードを完成させることができます。これは、本質的に、計算機内 からすべての入力フィールドを返します(親スコープを使用できるようにするには、jetbrains.mps.lang.Scopes 言語をインポートします)。

Sc8

簡単なヒント: SimpleRoleScope クラスの使用に注意してください。これは、独自のカスタムスコープの構築に役立ついくつかのヘルパークラスの 1 つです。SimpleRoleScope(Control/Cmd + N)に移動し、含まれているパッケージ構造 Alt+F1 を開いて、確認してください。

スコープヘルパーの実装

MPS には、考えられる多くのシナリオをカバーするいくつかのヘルパー Scope 実装が付属しており、使用してスコープを定義するタスクを簡単にすることができます。

  • ListScope- コンストラクターに渡されるノードを表します

  • DelegatingScope- コンストラクターに渡された Scope インスタンスに委譲します。通常は、LazyScope などの既存のスコープの周囲に機能を追加する必要があるスコープによって拡張されます。

  • CompositeScope- (ラップされた)スコープインスタンスのグループに委譲します

  • FilteringScope- 単一の Scope インスタンスに委譲し、そのノードを述語でフィルタリングします (isExcluded メソッド)

  • FilteringByNameScope- 単一の Scope インスタンスに委譲し、コンストラクターパラメーターとして取得する名前ブラックリストでノードをフィルタリングします

  • EmptyScope- ノードのないスコープ

  • SimpleRoleScope- 特定のロールに一致するノードのすべての子ノードを提供するスコープ

  • ModelsScope- 提供されたモデルのセットに含まれる特定の概念のすべてのノードを含むスコープ

  • ModelPlusImportedScope -ModelsScope と同様ですが、特定のモデルによってインポートされたすべてのモデルが含まれます

例: getScope() メソッドは、次のように ListScope を使用して書き直すことができます。

Scopex1001

VariableReference

少し高度な例が BaseLanguage にあります。VariableReference は、その variableDeclaration 参照に継承されたスコープを使用します。

Scp1

ForStatementLocalVariableDeclarationBaseMethodDeclarationClassifier などの概念は、スコープに変数宣言を追加して、ScopeProvider を実装します。

Scp2

例: ForStatementScopes.forVariables ヘルパー関数を使用して、for ループで宣言されたすべての変数で親スコープを強化し、親スコープで同じ名前の変数を非表示にする可能性のあるスコープを構築します。come from 式は、現在スコープを解決している参照がサブツリーの指定された部分にあるかどうかを検出します。

参照スコープを使用する

スコープは、参照スコープを使用して、高速ではありますがスケーラビリティの低い方法で実装することもできます。undefined

Rsc1

ScopeProvider タイプの祖先に委譲して解決を行う代わりに、スコープ解決コードを制約定義に直接挿入できます。


Rsc2

元々電卓の getScope() メソッド内にあったコードの代わりに、スコープを定義するのは InputFieldReference 自体になりました。 参照スコープの関数は、ScopeProvider.getScope() メソッドと同様に、Scope インスタンスを返すことになっています。スコープは基本的に、潜在的な参照ターゲットと、これらのターゲットをテキスト値で解決するためのロジックのリストです。

念のために言っておきますが、いくつかの事前定義された Scope 実装と関連するヘルパーファクトリメソッドをすぐに使用できます。

  • SimpleRoleScope- 指定されたノードに接続され、指定されたロールにあるすべてのノードを追加するだけです

  • ModelPlusImportedScope- インポートされたモデルからの参照ターゲットを提供します。ユーザーが ctrl + R/cmd + R (インポートを含むモデル)でスコープにターゲットを追加できるようにします。

  • FilteringScope- 一部の要素を別のスコープから除外できます。FilteringScope のサブクラスは、isExcluded() メソッドをオーバーライドします。

  • DelegatingScope- 別のスコープに委譲します。元のスコープの動作をカスタマイズするためにオーバーライドすることを意味します。

スコープモデルで自分の周囲を見回すこともできます。

Scp3

関連ページ:

MPS 電卓言語チュートリアル

このチュートリアル導入、テンプレートの実装、導入このチュートリアルでは、MPS での言語デザインのさまざまな分野について説明します。単純なスタンドアロン言語の抽象的な構造を定義し、そのためのエディターを設計し、タイプを制限し、スコープを作成し、最後に Java コードを生成するジェネレーターを準備します。以前の MPS への露出に応じて、このチュートリアルでは完了までに約 1 日かかります。このチュートリアルでは、主に MPS を評価する必要のある言語デザイナーを対象とし、ベアボーンの例以外のも...

MPS 電卓言語チュートリアル

導入:このチュートリアルでは、MPS での言語デザインのさまざまな分野について説明します。単純なスタンドアロン言語の抽象的な構造を定義し、そのためのエディターを設計し、タイプを制限し、スコープを作成し、最後に Java コードを生成するジェネレーターを準備します。以前の MPS への露出に応じて、このチュートリアルでは完了までに約 1 日かかります。このチュートリアルでは、主に MPS を評価する必要のある言語デザイナーを対象とし、ベアボーンの例以外のものを見たいと思っています。Java の基...

説明コメント

ノードに属性を追加する機能を活用する方法を学びます。この機能は、構造の章の属性のセクションで詳しく説明されています。このクックブックでは、電卓チュートリアル言語に簡単な追加機能を作成して、電卓定義の入力フィールドと出力フィールドに説明的なコメントを付けることができます。これらの説明コメントは、入力フィールドと出力フィールドに対応する Swing テキストフィールドに添付された「ポップアップツールチップ」の形式で、生成された Java コードに伝達されます。計算機の言語:実験のテストベッドとして...