package org.dynjs.parser.ast;
import java.util.ArrayList;
import java.util.List;
import org.dynjs.exception.ThrowException;
import org.dynjs.parser.CodeVisitor;
import org.dynjs.parser.Statement;
import org.dynjs.parser.js.Position;
import org.dynjs.runtime.BasicBlock;
import org.dynjs.runtime.Completion;
import org.dynjs.runtime.ExecutionContext;
public class TryStatement extends BaseStatement {
private final Statement tryBlock;
private final CatchClause catchClause;
private final Statement finallyBlock;
public TryStatement(Position position, Statement tryBlock, CatchClause catchClause, Statement finallyBlock) {
super(position);
this.tryBlock = tryBlock;
this.catchClause = catchClause;
this.finallyBlock = finallyBlock;
}
public Statement getTryBlock() {
return this.tryBlock;
}
public CatchClause getCatchClause() {
return this.catchClause;
}
public Statement getFinallyBlock() {
return this.finallyBlock;
}
public List<FunctionDeclaration> getFunctionDeclarations() {
return this.tryBlock.getFunctionDeclarations();
}
public List<VariableDeclaration> getVariableDeclarations() {
List<VariableDeclaration> decls = new ArrayList<>();
decls.addAll(this.tryBlock.getVariableDeclarations());
if (this.catchClause != null) {
decls.addAll(this.catchClause.getVariableDeclarations());
}
return decls;
}
public int getSizeMetric() {
return 7;
}
@Override
public Completion interpret(ExecutionContext context, boolean debug) {
Completion b = null;
boolean finallyExecuted = false;
try {
b = invokeCompiledBlockStatement(context, "Try", getTryBlock());
} catch (ThrowException e) {
if (getCatchClause() != null) {
// BasicBlock catchBlock = new InterpretedStatement(statement.getCatchClause().getBlock(), strict);
BasicBlock catchBlock = compiledBlockStatement(context, "Catch", getCatchClause().getBlock());
try {
b = ((ExecutionContext) context).executeCatch(catchBlock, getCatchClause().getIdentifier(), e.getValue());
} catch (ThrowException e2) {
if (getFinallyBlock() != null) {
Completion f = invokeCompiledBlockStatement(context, "Finally", getFinallyBlock());
if (f.type == Completion.Type.NORMAL) {
if (b != null) {
return(b);
} else {
throw e2;
}
} else {
return(f);
}
} else {
throw e2;
}
}
}
if (getFinallyBlock() != null) {
finallyExecuted = true;
Completion f = invokeCompiledBlockStatement(context, "Finally", getFinallyBlock());
if (f.type == Completion.Type.NORMAL) {
if (b != null) {
return(b);
} else {
throw e;
}
} else {
return(f);
}
} else {
if (b != null) {
return(b);
} else {
throw e;
}
}
}
if (!finallyExecuted && getFinallyBlock() != null) {
Completion f = invokeCompiledBlockStatement(context, "Finally", getFinallyBlock());
if (f.type == Completion.Type.NORMAL) {
return(b);
} else {
return(f);
}
}
return b;
}
public String toIndentedString(String indent) {
StringBuilder buf = new StringBuilder();
buf.append(indent).append("try {\n");
buf.append(this.tryBlock.toIndentedString(indent + " "));
buf.append(indent).append("}\n");
if (this.catchClause != null) {
buf.append(this.catchClause.toIndentedString(indent + " "));
}
if (this.finallyBlock != null) {
buf.append(indent).append("finally {\n");
buf.append(this.finallyBlock.toIndentedString(indent + " "));
buf.append(indent).append("}");
}
return buf.toString();
}
@Override
public Object accept(Object context, CodeVisitor visitor, boolean strict) {
return visitor.visit(context, this, strict);
}
}