Cancelling Script Execution

Context.updateLine(int)

During a script execution, Pnuts interpreter keeps track of the line number, which will be displayed when an error occurs. Context.updateLine(int) method is called whenever the line number changes. By overriding the method in a subclass, it is possible to cancel script execution under arbitrary condition.

The cancellation by this mechanism has a couple of assumptions:

Bytecode generated by the compiler, by default, does not call Context.updateLine(int) method until the line number changes. If for-loop or while-loop is in a single line, it can't cancel the execution until the loop exits. To cope with this problem, the initial property pnuts.compiler.traceMode should be set true, so that the updateLine() method is called for every expression.

The AST interpreter calls the method for each expression, even if the expressions are at the same line.

The following code illustrates a way to cancel script execution when a timer expires.

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 seconds later
Pnuts.eval(expression, context);

Since Pnuts.eval(String,Context) method, by default, evaluates the specified expression with the AST interpreter, the property pnuts.compiler.traceMode does not have to be set.