やっと何をやっていたのか思い出したメモ。
世の中には趣味で Scheme を実装する人が山程いらっしゃると思いますが、私もその一人で、趣味と実益を兼ねて Adobe Flash の AVM2 を対象に Scheme のような物を作っていました。Scheme というと、関数をどうやって作るかが肝だと思うんだけど、とりあえずそれなりに動けば良いと思って、
- let 文の変数はレジスタ(スタック的な物)に実装
- lambda 文の変数はアクティベーション(ヒープ的な物)に実装
- lambda 文は AVM2 のメソッドして実装。スタックに積まれた引き数を毎回アクティベーションに全部コピー
という感じで作っていました。しかしそんな簡単に行くはずもなく、例えば let で定義した変数は他の関数からアクセス出来ないので (let ( (x "Hello, World")) ( (lambda () (print x)))) のような文で内側の lambda から x が参照出来ないという情けない事が起こっていました。
これを避けるには let でも変数をアクティベーションに入れれば良いんだけど、全部アクティベーションだとActionScript より三倍くらい遅くなってしまって感じ悪いので、必要な分だけアクティベーションに入れたい。具体的には、最初全部アクティベーションに入れておいて最適化パスでレジスタに入れるという二段構えでやれば良いのではないかと思いましたが、普通の人はどうするのだろうと色々文献を読もうとしていた所でした。
最適化は最後まで行わないという考え方もあるけど、これくらい出来ないとプログラマとしての沽券に関わるような気がしています。