私は、バイトコードにコンパイルされ、カスタム VM で実行される小さな言語を作成中です。そのアーキテクチャは、Python と Lua について読んだことの影響を大きく受けています。関数の引数、ローカル変数、および一時的な値を格納するデータ スタックと、アクティブな関数呼び出しごとに 1 つのエントリを含むフレーム スタックの 2 つのスタックがあります。フレーム スタックの各エントリには、現在の関数、命令ポインター (現在の関数のバイトコード配列へのインデックス)、ベース ポインター (データ スタックへのインデックス - 関数の args/locals の開始位置を示すマーク) などの情報が含まれます。
私が動けなくなったのは、REPL の実装、またはより具体的には の実装ですeval()
。これまでのアイデアは、同じスタック フレーム内でユーザー入力を継続的に評価することでしたが、内部で新しいローカル変数を作成できるようにするきれいな方法がわかりませんeval()
。一時データは常にスタックのローカルより上にある (スタックは上に成長する) ため、私が考えることができた唯一のアプローチは、新しいローカルが作成されたことにeval()
何らかの方法で気づき、ハッカーを使用してスタックを再配置することですが、これは一般的なケースで問題を引き起こします。たとえば、条件付きで使用される再帰関数がある場合eval()
、フレーム スタックを調べて、場合によってはフレームごとにデータ スタックを調整する必要があります。
私の VM は の適切な実装をサポートできeval()
ますか? はいの場合、上記のアプローチは賢明ですか? いいえの場合、どのようなアーキテクチャの変更が必要ですか?