SCHEMEON.jsにevalなど付け加えてみた

Javascriptだけで実装しているSchemeインタプリタSCHEMEON.jsにevalを付け加えてみました。
http://www.d2.dion.ne.jp/~ujiie/schemeonjs/
evalの実装は、null-environment, scheme-report-environment, interaction-environmentのことを考えなければとても簡単。
でもr5rsにはこの3つのどれかがevalの第2引数に与えられることになっている。

  • null-environment (たぶん)シンタックスのみ実装された環境(プリミティブ手続きは未実装)
  • scheme-report-environment r5rsで規定されている手続きなども定義された環境
  • interaction-envioronment 通常の環境

これをグローバル環境上で選別してやらなきゃならない。
ちょっとよくわからなかったのが、例えば、scheme-report-environment上で新たに定義したシンボルがinteraction-environmentにどう影響してくるのか。
Gaucheでちょっと確認してみました。

gosh> (eval '(define a 1) (scheme-reort-environment 5))
a
gosh> a
1
gosh> (define a 2)
a
gosh> (eval 'a (scheme-report-environment 5))
1
gosh> a
2
gosh> (eval '(set! a 3) (scheme-report-environment 5))
a
gosh> a
2

なるほどー。
つまり、interaction-environmentでシンボルが定義されていないときはscheme-report-environmentを見に行くけど、interaction-environmnetでシンボルが定義されているときはinteraction-environmentの定義を見に行くと。
で、evalでscheme-report-environmentなど下位の環境が指定されたときは、interaction-environmentでの定義は無視される。
この関係は多分null-environmentでも同じ。
この挙動を基本に、SCHEMEON.jsでも実装してみました。
実行スピードになるべく影響が出ないように工夫して実装したけど、おおむねうまくいっているみたい。