ステップ実行evalが欲しい
インターフェースは以下のような感じ(仮)。
(with-step-eval expr env step-num interval-proc)
- exprとenvは、通常のevalと同じ。
- step-numに、「何ステップ分実行したらinterval-procを呼ぶか」のステップ数を設定。
- 「ステップ」は、例えば、(car (cons 1 3))を評価すると2ステップとする(仮)。自分の想定している用途では、ステップ数のカウントは厳密である必要はあまり無い。
- interval-procは、前述の条件で、指定ステップ数が経過する毎に呼び出される。
- 呼び出される際に、引数として、「またステップ実行を続行する為の継続」が渡される(仮)。
- しかしこの仕様だと、Gaucheの継続のエクステント制限に引っかかりやすそうな気がする。ただ単に、interval-procの返り値の真偽などで、ステップ実行を続行するか、終了するかを判断した方がいいかも知れない。
- 呼び出される際に、引数として、「またステップ実行を続行する為の継続」が渡される(仮)。
- with-step-evalの返り値は、exprを評価した返り値、または、interval-procの返り値(仮)。
真面目に実装する場合
- 「implicit forceに関する妄想」( http://practical-scheme.net/wiliki/wiliki.cgi?nekoie#H-1cj0atu )と同じように、手続きの適用時にフックできるようにGaucheを改造する。
- ものすごい大変そう。とりあえずギブアップ。
- exprを評価する前に、exprをパーズして、ステップ数カウント&interval-proc呼び出し手続きを挟み込みまくる。
- パーズが大変そう。また、exprの内部にevalがあった場合に問題が発生。
- 速度が遅そう(但し、自分の今回の用途ではあまり速度は気にしなくてもいい)。
- 予めenvに束縛しておくR5RS手続き等を、事前に、ステップ数カウント&interval-proc呼び出し手続きをつけたものに、差し替えておく。
- 限定した機能しか提供しない場合(例えば、load等を除いたR5RS)はこれでok。Gaucheの機能全部とかは無理(モジュールのuseとかに対応できない)。
- exprに、シンボルではない、手続きの実体が含まれていた場合、その手続きはステップ数カウントをスルーしてしまう。
- この場合は、step-numとinterval-procはenvの中に含まれてしまうので、with-step-evalという名前にする必要すら無い。
- 他には?
真面目に実装しない場合
- SIGALRMを使ってエミュレート
- 秒単位でしか制御できない。
- シグナルに依存してしまう。
- 全然「ステップ実行」じゃない。
- スレッドとシグナルを使ってエミュレート
- SIGALRMを使うよりは正確だが……。
- 矢張り「ステップ実行」ではない。
- 別プロセス起動とシグナルを使ってエミュレート
- 矢張り「ステップ実行」ではない。
- cpu稼動秒数を見る事で、単なる経過秒数よりは正確さがマシになる?
- 他には?
とりあえず、今回はR5RS程度の機能しか提供しない筈なので、真面目3で実装する事にする。