必要と思われるのは、言語 (Java) のパーサーと、名前と型のリゾルバーです。(「シンボル テーブル ビルダー」)。
ソース テキストを解析した後、コンパイラには通常、名前の定義とそれに対応する型を記録しようとする名前リゾルバーと、各式が有効な型であることを検証する型チェッカーがあります。
通常、名前/型リゾルバーは、定義が見つからない場合に文句を言います。やりたいことは、問題の原因となっている「未定義」のものを見つけて、その型を推測することです。
為に
IPerson p = new Person();
名前リゾルバーは、「Person」と「IPerson」が定義されていないことを認識しています。もしそうなら
Foo p = new Bar();
インターフェイスが必要だったという手がかりはありません。単に Foo が Bar のある種の抽象的な親 (クラスやインターフェイスなど) であるというだけです。そのため、どちらであるかの決定は、ツールに認識されている必要があります (「そのような構造を見つけたときはいつでも、Foo がインターフェースであると想定してください...」)。ヒューリスティックを使用できます。IFoo と Foo は、IFoo がインターフェイスであることを意味し、誰かがそのインターフェイスを実現するクラスとして Foo を定義する必要があります。ツールがこの決定を下したら、シンボル テーブルを更新して、他のステートメントに進むことができるようにする必要があります。
為に
p.Name = "Sklivvz";
p が (前の推論により) Interface でなければならないとすると、Name はフィールド メンバーである必要があり、その型は代入から String であることがわかります。
それで、ステートメント:
Assert.AreEqual("Sklivvz", p.Name);
名前とタイプは、それ以上問題なく解決されます。
IFoo および Foo エンティティの内容は、あなた次第です。get と set を使用する必要はありませんでしたが、それは個人的な好みです。
同じステートメントに複数のエンティティがある場合、これはうまく機能しません。
x = p.a + p.b ;
a と b がフィールドである可能性が高いことはわかっていますが、実際に数値であるか、文字列であるかを推測することはできません (これは Java の文字列では有効ですが、C# についてはわかりません)。C++ の場合、「+」が何を意味するかさえわかりません。Bar クラスの演算子である可能性があります。したがって、「a は不定の数または文字列」などの制約を収集する必要があり、ツールが証拠を収集するにつれて、可能な制約のセットが絞り込まれます。(これは、「ジョーには 7 人の息子がいます。ジェフはサムより背が高いです。ハリーはサムの後ろに隠れることができません。ジェフの双子は誰ですか?」という単語の問題と同じように機能します。ここでは、証拠を集めて不可能を取り除く必要があります)。また、矛盾が生じる場合も心配する必要があります。
p.a+pb のケースを除外することはできますが、単体テストを無罪で作成することはできません。免責が必要な場合は、標準の制約ソルバーがあります。(なんてコンセプト)。
OK、アイデアはありますが、これを実際に行うことはできますか?
この最初の部分では、パーサーと、曲げ可能な名前と型のリゾルバーが必要です。制約ソルバー、または少なくとも「定義された値が未定義の値に流れる」操作(自明な制約ソルバー)が必要です。
Java フロント エンドを備えたDMS ソフトウェア リエンジニアリング ツールキットは、おそらくこれを行うことができます。DMS は、コンピューター言語を任意の方法で処理するツールを構築したい人のためのツール構築ツールです。(「数値ではなくプログラムの断片で計算する」と考えてください)。
DMS は汎用の構文解析機構を提供し、与えられたフロント エンド (たとえば、Java と C# フロント エンド) のツリーを構築できます。私が Java を選んだ理由は、私たちの Java フロント エンドには名前と型の解決機構がすべてあり、それを曲げることができるようにソース形式で提供されているからです。自明な制約ソルバーに固執した場合は、おそらく Java 名前リゾルバーを曲げて型を把握できます。DMS を使用すると、コード フラグメントに対応するツリーを組み立てて、それらをより大きなツリーに結合できます。ツールがシンボル テーブルのファクトを収集すると、プリミティブ ツリーを構築できます。
どこかで、あなたは自分が終わったと決心しなければなりません。ツールがインターフェイス全体を認識する前に、何回の単体テストを確認する必要がありますか? (私はそれがあなたが提供するものをすべて食べると思いますか?)。完了すると、さまざまなメンバーのフラグメントがアセンブルされ、インターフェイスの AST が構築されます。DMS はその prettyprinter を使用して、お見せしたように AST をソース コードに戻すことができます。
私たちの Java フロントエンドには名前と型の解決があるので、ここでは Java をお勧めします。私たちの C# フロントエンドはそうではありません。これは野心の「単なる」問題です。誰かがそれを書かなければなりませんが、それはかなりの作業です (少なくともそれは Java の場合であり、C# が実際に異なるとは思えません)。
しかし、DMS を使用すると、原則としてこのアイデアはうまく機能します。
これは、パーサーと曲げ可能な名前と型のリゾルバーにアクセスできる他のインフラストラクチャを使用して行うことができます。C# の場合、これを実現するのはそれほど簡単ではないかもしれません。MS は、パーサーと、名前と型の解決へのアクセスを提供する可能性があると思いますが、それを変更する方法はありません。多分Monoが答えですか?
コード フラグメントを生成してアセンブルするには、引き続き was が必要です。文字列のハッキングによってこれを行うことができます。プログラムのビットを一緒に接着することに関する私の(長い)経験は、文字列でそれを行うと、最終的にそれを台無しにするということです。文法が許す方法でのみ結合できる既知のタイプのコードフラグメントを表す断片が本当に必要です。DMSはそれを行うため、混乱はありません。