package akin.lang.nodes;
import java.util.ArrayList;
import akin.lang.*;
/**
A try-catch block.
*/
public class TryNode extends Node {
private Node body;
private ArrayList<CatchBlock> catchBlocks;
public TryNode(Node body) {
this.body = body;
catchBlocks = new ArrayList<CatchBlock>();
}
/**
Add a block to catch exception of type typeName. Storing the exception in
localName and evaluating body.
*/
public void addCatchBlock(String typeName, String localName, Node body) {
catchBlocks.add(new CatchBlock(typeName, localName, body));
}
public AkinObject eval(Context context) throws AkinException {
Context tryContext = context.makeChildContext();
try {
return body.eval(tryContext);
} catch (AkinException exception) {
// If there's an exception we run through all exception handler and run
// the first one that can handle the exception.
for (CatchBlock block : catchBlocks) {
ExceptionHandler handler = block.toExceptionHandler();
if (handler.handle(exception)) return handler.run(tryContext, exception);
}
// No catch block for this exception, rethrow. Can be catched from a parent
// context.
throw exception;
}
}
/**
One catch block.
*/
private class CatchBlock {
private String typeName;
private String localName;
private Node body;
public CatchBlock(String typeName, String localName, Node body) {
this.typeName = typeName;
this.localName = localName;
this.body = body;
}
public ExceptionHandler toExceptionHandler() {
return new ExceptionHandler(AkinRuntime.getRootClass(typeName), localName, body);
}
}
}