それ自体から言語を変更することは、リフレクションとメタプログラミングの傘下にあります。それは行動反射と呼ばれます。これは、言語レベルではなく、アプリケーション (クラス、メソッドなど) のレベルで機能する構造的リフレクションとは異なります。行動反射のサポートは、言語によって大きく異なります。
言語の変更は、大きく次の 2 つのカテゴリに分類できます。
- 言語自体のセマンティクス (つまりルール) を変更する変更 (たとえば、メソッド検索アルゴリズムの再定義)、
- 構文を変更する変更 (たとえば、配列を作成するための構文 '1..4')。
ケース 1 の場合、特定の言語は、メタオブジェクトと呼ばれる特別なオブジェクトを介して、アプリケーション自体の構造 (構造リフレクション) と実装の内部動作 (動作リフレクション) をアプリケーション自体に公開します。メタオブジェクトは、それ以外の場合は暗黙的な側面の具体化であり、明示的に操作可能になります。アプリケーションはメタオブジェクトを変更して、その構造の一部または言語の一部を再定義できます。言語の変更に関しては、オブジェクト指向言語のコアメカニズムであるため、メッセージ送信/メソッド呼び出しの変更に通常焦点が当てられます。しかし、言語によっては、フィールド アクセス、同期プリミティブ、foreach 列挙など、言語の他の側面を公開するために同じ考え方を適用できます。
ケース 2 の場合、プログラムは、変更する適切なデータ構造で表す必要があります。Lisp ファミリーの言語の場合、プログラムはリストを操作し、プログラム自体をリストとして表すことができます。これはホモイコニシティと呼ばれ、メタプログラミングに便利です。したがって、Lisp に似た言語の柔軟性があります。他の言語の場合、その表現は通常 AST です。プログラムの表現を変換したり、書き直したりすることは、コンパイルまたはクラスのロード中に、マクロ、プリプロセッサ、またはフックを使用して可能です。
ただし、1 と 2 の境界線はあいまいです。構文の変更は、言語のセマンティクスを変更するように見える場合があります。たとえば、適切な getter と setter を使用してすべてのフィールド アクセスを書き換え、トランザクション メモリを実装するなどの追加ロジックを実行できます。フィールド アクセスとは何かという意味の変更を行ったのか、それとも単に構文を変更しただけなのか? また、線の間に落ちる他の構造もあります。たとえば、プロキシと#doesNotUnderstand
トラップは、メッセージ送信の具体化をある程度シミュレートするための一般的な手法です。
Lisp と Smalltalk は、メタプログラミングの分野で非常に影響力がありました。次の 2 つのプロジェクト/プラットフォームは、それぞれの代表例として興味深いと思います。
- Racket、言語内から言語を成長させることに焦点を当てた Lisp に似た言語
- Helvetiaは、ホスト環境の AST を利用して新しい言語をホスト言語に埋め込む Smalltalk 拡張機能です。
私があなたの質問に実際に答えていなくても、これを楽しんでいただければ幸いです ;)
必要な変更を行うには、リテラルの作成方法を変更する必要があります。これは、通常、アプリケーションに公開されていない私の知る限りです。私が思いつくクローズドな作品は、Javascript に取り組んだVirtual Values for Language Extensionです。