スクリプト実行のキャンセル

Context.updateLine(int)

スクリプトが実行される間、Pnutsインタプリタは実行中の行番号を管理していて、エラーが発生するとその時点の行番号が表示されます。 実行中の行番号が変化するたびに呼び出される、Context.updateLine(int)メソッドを、Contextクラスのサブクラスでオーバーライドすることで、一行ごとに行う処理を定義することができます。したがって、このメソッドの中で例外を発生させれば、任意の条件でスクリプトの実行をキャンセルすることができるわけです。

この仕組みを利用してスクリプト実行をキャンセルする方法には、いくつかの前提があります。

バイトコードコンパイラによる実行では、デフォルトの設定では、行番号が変化しないかぎりContext.updateLine(int)メソッドは呼び出されません。もし、forループやwhileループが一行で書かれていた場合は、ループを抜けるまで実行をキャンセルできません。この問題を回避するためには、起動時プロパティpnuts.compiler.traceModeにtrueを指定し、式を評価するたびにこのメソッドが呼び出されるようにします。

ASTインタプリタによる実行では、実行中の行番号が変化しなくても、式を評価するたびにこのメソッドが呼び出されます。

次の例は、スクリプトの実行を約10秒後にキャンセルする例です。

public class MyContext extends Context {
  long endTime;

  public MyContext(long endTime){
    this.endTime = endTime;
  }
  protected void updateLine(int line){
    if (System.currentTimeMillis() > endTime){
      throw new Jump(null);  // return null
    }
  }
}
Context context = new MyContext(System.currentTimeMillis() + 10 * 1000)); // 10秒後
Pnuts.eval(式, context);

Pnuts.eval(String,Context)メソッドは、デフォルトの設定では、ASTインタプリタを使って式を評価するので、起動時プロパティpnuts.compiler.traceModeを設定する必要はありません。