MPS プロジェクト構造
言語を設計したりコードを書いたりするときには、優れた構造を使用して各部分を移動したり、組み合わせたりすることができます。MPS はこの点で他の IDE と似ています。
プロジェクト
プロジェクトは MPS の主な組織単位です。プロジェクトは 1 つ以上のモジュールで構成されており、それら自体がモデルで構成されています。モデルは生成 / コンパイルの最小単位です。以下でこれらの概念を詳細に説明します。
モデル
MPS がもたらす大きな違いは次のとおりです。プログラムはテキスト形式ではありません。
プログラミングはテキストで行われるという事実に慣れているかもしれません。テキストを編集します。次にテキストはパーサーによって解析され、AST が構築されます。文法は通常、パーサーを定義するために使用されます。その後、AST はプログラムをさらに操作するためのコアデータ構造として使用され、コンパイラーによって実行可能なコードが生成されるか、IDE によって実用的なコーディング支援、リファクタリング、静的コード分析が提供されます。
AST が非常に便利で、柔軟性があり、強力なデータ構造であることを考えると、テキスト、文法、パーサーを完全に避けて、最初から AST を操作できるとしたら、どのように役立つでしょうか。まあ、これはまさに MPS が行うことです。
コードに構造を与えるために、MPS のプログラムはモデルに編成されています。モデルは、テキストベースの言語のコンパイルユニットにいくぶん似ていると考えてください。例を挙げると、MPS の最終的な言語である BaseLanguage は、Java に基づいて構築され、さまざまな方法で拡張されており、各モデルが Java パッケージを表すようにモデルを使用しています。モデルは通常、最上位の宣言を表すルートノードと非ルートノードで構成されます。例: BaseLanguage クラスでは、インターフェースと列挙型はルートノードです。(ノードの詳細については、こちらを参照してください)。
モデルはメタ情報を保持する必要があります。
彼らが使用するモデル (インポートモデル)
それらが書かれている言語(そして devkits も) (使用言語のセクション)
モデルファイルや特別なジェネレーターパラメーターなど、いくつかの追加パラメーター
このメタ情報は、モデルのポップアップメニューのモデルプロパティで変更するか、モデルに配置したときに Alt+Enter を使用して変更できます。
モジュール
モデル自体は、最もきめ細かいグループ化要素です。モジュールは、モデルをより高いレベルのエンティティに編成します。モジュールは通常、モジュールのプロパティと依存関係を説明するメタ情報を伴ういくつかのモデルで構成されます。MPS は、ソリューション 、言語、開発キット、ジェネレーターなど、いくつかのタイプのモジュールを区別します。
次に、メタ情報構造と個々のモジュールタイプについて詳しく説明します。
モジュールメタ情報
ものをモジュールにまとめるとき、より良い善のためにモジュールを一緒に組み合わせる方法が必要です。モジュール間の関係は、それらが保持するメタ情報を通して記述されます。モジュール間の可能な関係は、いくつかのグループに分類できます。
依存関係 -1 つのモジュールが別のモジュールに依存している場合、前者の内部のモデルは後者からモデルをインポートできます。依存関係の reexport プロパティは、依存関係が推移的であるかどうかを示します。モジュール A が reexport プロパティが true に設定されたモジュール B に依存している場合、A で依存関係を宣言する他のすべてのモジュールも自動的に B に依存します。
拡張された言語依存性 - 言語 L が言語 M を拡張する場合、M からのすべての概念は、ロールまたは拡張概念のターゲットとして L 内で使用できます。また、言語 M のすべての側面は、言語 L の対応する側面で使用および拡張が可能です。
生成ターゲット依存関係 - 2 つの言語(L2 と L1)の間の関係。L2 の生成プログラムが L1 に生成するように指定する必要があるため、L1 の実行時依存関係が必要です。
使用言語 - モジュール A が言語 L を使用している場合、A 内のモデルは言語 L を使用できます。
使用されている devkit - モジュール A が devkit D を使用している場合、A 内のモデルは devkit D を使用できます。
ジェネレーター出力パス - ジェネレーターの出力パスは、新しく生成されたすべてのファイルが配置されるフォルダーです。これは MPS が生成するものを探すことができる場所です。
ファセット - ファセットは、モジュールで使用できる追加のテクノロジーまたは設定を指定します。モジュールに関連付けられたファセットは、モジュール記述子ファイル内に記録されます。これは、ファセット構成情報の最終的なソースです。テストおよび Java を含むすべてのファセットは、完全にオプションです。
生成されたコードは、通常のコードに使用 source_gen 位置の代わり test_gen という名前のディレクトリに置かれることテストファセットを確実にします。
言語モジュールのプロパティで Java モジュールファセットのチェックを外すと、言語がクラスローディングメカニズムから除外され、まったく異なるエクスペリエンスが発生することに注意してください。
それでは、MPS にあるさまざまな種類のモジュールについて見ていきます。
ソリューション
解決策は、MPS で可能な最も単純な種類のモジュールです。コードを保持し、共通の名前で統一されたモデルのセットにすぎません。ソリューションには 4 つのタイプがあります。
通常の解決策 - これらのソリューションはエンドユーザーコードを保持します。通常、IDE はオンデマンドでコードを生成し、生成された Java コードをコンパイルします。コンパイルされたコードは IDE にはロードされませんが、別の Java プロセスでオンデマンドで実行できます。
サンドボックスソリューション - これらのソリューションは主に、言語設計のプロセス中に言語設計者によって、言語を対話的に進化させるためにコードを操作するために使用されます。通常、IDE はコードを生成しますが、生成されたコードをコンパイルしようとはしません。
ランタイムソリューション - これらのソリューションには、他のモジュール (ソリューション、言語、ジェネレーター) が依存するコードが含まれています。コードは、MPS モデルだけでなく、Java クラス、ソース、jar ファイルでも構成できます。IDE は、クラスが外部でコンパイルまたは変更されるたびに、コードを生成およびコンパイルし、クラスを再ロードします。
プラグインソリューション - これらのソリューションは、何らかの方法で IDE の機能を拡張します。新しいメニューエントリを提供したり、サイドツールパネルウィンドウを追加したり、プロジェクト設定ダイアログからカスタム設定画面を定義したりできます。ここでも、MPS はコードを生成してコンパイルし、クラスが変更されるたびにクラスを再ロードし続けます。さらに、IDE 機能もそれに応じて更新されます。
言語
言語は、ソリューションよりも複雑で、再利用可能な言語を表すモジュールです。これはいくつかのモデルで構成され、それぞれが言語の特定の側面を定義します: 構造、エディター、アクション、typesyste など。
言語は他の言語を拡張できます。拡張言語は、拡張言語からすべての概念を使用できます。独自の概念を導出し、継承された概念を参照のターゲットとして使用し、継承された概念を独自の概念内の子として直接配置することもできます。
言語は、サードパーティのライブラリまたはソリューションに実行時の依存関係があることがよくあります。たとえば、Hibernate や Swt などの Java ライブラリをラップする言語を作成できます。そうすれば、あなたの言語は、これらのライブラリに付属している標準の JavaAPI に代わるより優れたスムーズな代替手段をユーザーに提供します。
あなたの言語が機能するためには、あなたの言語にラップされたライブラリを含める必要があります。これは、ランタイムクラスパスまたはランタイムソリューションのいずれかを介して行います。ランタイムクラスパスは、Java で記述されたライブラリなどの一般的なシナリオに適していますが、ランタイムソリューションは、より複雑なシナリオに適しています。
ランタイムクラスパス - ライブラリクラスをスタブ言語ジェネレーターとして利用できるようにします
ランタイムソリューション - これらのモデルはジェネレーター内部のすべてのモデルから見える
言語面
言語の側面は、言語のさまざまな側面を表します。
構造体 - 言語 AST のノードと構造体を記述します。これはあらゆる言語の唯一の必須の側面です。
エディター - 言語がエディターでどのように表示され編集されるかを説明します
アクション - 言語に固有の補完メニューのカスタマイズについて説明します。これは、Control + Space と入力したときに発生します。
制約 - AST の制約について説明します: ノードが適用可能な場合、どのプロパティと参照が許可されるかなど。
行動 - AST の動作面、つまり AST メソッドについて説明します
型システム - 言語で型を計算するための規則について説明します
インテンション - インテンションについて説明します (バルブがポップアップしたとき、またはユーザーが Alt+Enter と入力したときに使用できるコンテキスト依存のアクション)
プラグイン - 言語を MPS IDE に統合することを可能にします
データフロー - 意図したデータフローをコードで記述します。到達不能なステートメント、初期化されていない読み取りなどを見つけることができます
このガイドの対応するセクションで各側面についてさらに読むことができます。
ジェネレーター
ジェネレーターは、ある言語から他の言語、通常は別の言語への変換を定義します。ジェネレーターは他のジェネレーターに依存するかもしれません。ジェネレーターにコードを適用する順序は重要であるため、ジェネレーターに順序付け制約を設定できます。対応するセクションで生成についてさらに読むことができます。
DevKits
DevKits は、あなたの生活を楽にするために作成されました。相互接続された言語の大規模なグループがある場合は、単一のユニットとして扱う方法を確かに高く評価します。例: 個々の言語をすべてリストせずにインポートすることもできます。DevKits はこれを可能にします。DevKit を構築するときは、含める言語をリストします。
予想どおり、DevKits は他の DevKits を拡張できます。拡張された DevKit は、継承されたすべての言語を、それ自体の言語であるかのように実行します。
プロジェクト
これは簡単です。プロジェクトは、グループ化して 1 つのユニットとして操作する必要があるモジュールをラップします。プロジェクトの Properties(プロジェクトビューパネルのプロジェクトノードの Alt+Enter)を開いて、プロジェクトに含める必要のあるモジュールを追加または削除できます。プロジェクトノードのコンテキストポップアップメニューから新しいモジュールを作成することもできます。
Java コンパイル
MPS は Java から生まれ、Java 環境でよく使われます。MPS モデルは java ファイルに生成されることが多いため、プログラムを実行する前に java をコンパイルする方法が必要です。一般的に 2 つの選択肢があります。
MPS でコンパイルする (推奨)
IntelliJ IDEA でコンパイルする (IntelliJ IDEA が必要です)
MPS でクラスをコンパイルするときは、モジュールのソースパスを設定する必要があります。ソースファイルは、モジュールが生成されるたびに、または make または rebuild アクションによって手動でコンパイルを呼び出すたびにコンパイルされます。
関連ページ:
基本的な考え方
この章では、基本的な MPS の概念であるノード、概念、言語について説明します。これらは、MPS の仕組みを正しく理解するための鍵となります。これらはすべて、他の要素と組み合わせることで初めて意味を成すため、すべて一緒に説明する必要があります。このセクションの目的は、各要素の本質を説明することです。詳細については、ノード、概念 (構造言語)、言語 (プロジェクト構造) に関するセクションを確認することを検討してください。抽象構文木 (AST):MPS は、テキスト形式を避けることによって他の多く...
依存関係を正しくする
目的:モジュールとモデルは通常、さまざまな型の依存関係のネットワークによって相互接続されています。MPS プロジェクト構造のページに従って、モジュールとモデルの基本的な原則と分類を理解していると仮定すると、私達は今やすべての詳細を学ぶようにさらに深く掘り下げることができます。MPS で依存関係を正しく取得することは、経験の浅いユーザーやベテランのベテランの間でもフラストレーションの頻繁な原因です。このページは、問題を一度に解決することを目的としています。さまざまなモジュールと依存関係の種類によ...
生成プログラム
導入:ジェネレーターは、言語の概念の表示的意味論を定義する言語仕様の一部です。MPS はモデル間変換アプローチに従います。MPS ジェネレーターは、入力言語でエンコードされた構成から出力言語でエンコードされた構成への変換を指定します。モデル間変換のプロセスには多くの中間モデルが含まれ、最終的には sn 出力モデルが生成されます。このモデルでは、すべての構成はすでに意味が別の場所で定義されている言語になります。たとえば、baseLanguage のほとんどの概念 (クラス、メソッドなど) は「機械が...
用語集
MPS 用語集:抽象構文木 (AST) ノードの階層を記述するツリーフォレストの形をしたメモリ(およびディスク)内のコードの論理表現。これらのノードは、親子関係という概念を持ちます。さらに、2 つのノードは、階層構造を横断する明示的な参照によって相互に接続できます。BaseLanguageJava 6 の射影クローン (Java 7 および 8 のオプションの拡張機能付き)。Java 仕様に準拠しており、Java 6 と 1:1 互換性があります。さらに、MPS は、日付、コレクション、クロージ...