ステップ実行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の返り値(仮)。


真面目に実装する場合

  1. 「implicit forceに関する妄想」( http://practical-scheme.net/wiliki/wiliki.cgi?nekoie#H-1cj0atu )と同じように、手続きの適用時にフックできるようにGaucheを改造する。
    • ものすごい大変そう。とりあえずギブアップ。
  2. exprを評価する前に、exprをパーズして、ステップ数カウント&interval-proc呼び出し手続きを挟み込みまくる。
    • パーズが大変そう。また、exprの内部にevalがあった場合に問題が発生。
    • 速度が遅そう(但し、自分の今回の用途ではあまり速度は気にしなくてもいい)。
  3. 予めenvに束縛しておくR5RS手続き等を、事前に、ステップ数カウント&interval-proc呼び出し手続きをつけたものに、差し替えておく。
    • 限定した機能しか提供しない場合(例えば、load等を除いたR5RS)はこれでok。Gaucheの機能全部とかは無理(モジュールのuseとかに対応できない)。
    • exprに、シンボルではない、手続きの実体が含まれていた場合、その手続きはステップ数カウントをスルーしてしまう。
    • この場合は、step-numとinterval-procはenvの中に含まれてしまうので、with-step-evalという名前にする必要すら無い。
  4. 他には?


真面目に実装しない場合

  1. SIGALRMを使ってエミュレート
    • 秒単位でしか制御できない。
    • シグナルに依存してしまう。
    • 全然「ステップ実行」じゃない。
  2. スレッドとシグナルを使ってエミュレート
    • SIGALRMを使うよりは正確だが……。
    • 矢張り「ステップ実行」ではない。
  3. 別プロセス起動とシグナルを使ってエミュレート
    • 矢張り「ステップ実行」ではない。
    • cpu稼動秒数を見る事で、単なる経過秒数よりは正確さがマシになる?
  4. 他には?


とりあえず、今回はR5RS程度の機能しか提供しない筈なので、真面目3で実装する事にする。