Support for throwing exceptions from Eval

This commit is contained in:
Andrey Breslav
2013-10-06 13:35:46 +04:00
parent 7559c3bd94
commit 3bae3e25b5
+52 -50
View File
@@ -24,6 +24,8 @@ trait InterpretationEventHandler {
fun exceptionCaught(currentState: Frame<Value>, currentInsn: AbstractInsnNode, exception: Value): InterpreterResult? fun exceptionCaught(currentState: Frame<Value>, currentInsn: AbstractInsnNode, exception: Value): InterpreterResult?
} }
class ThrownFromEvalException(val exception: Value): RuntimeException()
fun interpreterLoop( fun interpreterLoop(
ownerClassInternalName: String, ownerClassInternalName: String,
m: MethodNode, m: MethodNode,
@@ -41,70 +43,70 @@ fun interpreterLoop(
} }
val interpreter = SingleInstructionInterpreter(eval) val interpreter = SingleInstructionInterpreter(eval)
try {
var frame = initFrame(ownerClassInternalName, m, interpreter) var frame = initFrame(ownerClassInternalName, m, interpreter)
while (true) { while (true) {
// TODO try-catch-finally support // TODO try-catch-finally support
// TODO support exceptions thrown by eval
val insnOpcode = currentInsn.getOpcode() val insnOpcode = currentInsn.getOpcode()
val insnType = currentInsn.getType() val insnType = currentInsn.getType()
when (insnType) { when (insnType) {
AbstractInsnNode.LABEL, AbstractInsnNode.LABEL,
AbstractInsnNode.FRAME, AbstractInsnNode.FRAME,
AbstractInsnNode.LINE -> { AbstractInsnNode.LINE -> {
// skip to the next instruction // skip to the next instruction
}
else -> when (insnOpcode) {
GOTO -> {
goto((currentInsn as JumpInsnNode).label)
continue
} }
else -> when (insnOpcode) { RET -> {
GOTO -> { val varNode = currentInsn as VarInsnNode
val address = frame.getLocal(varNode.`var`)
goto((address as LabelValue).value)
continue
}
// TODO: switch
LOOKUPSWITCH -> UnsupportedByteCodeException("LOOKUPSWITCH is not supported yet")
TABLESWITCH -> UnsupportedByteCodeException("TABLESWITCH is not supported yet")
IRETURN, LRETURN, FRETURN, DRETURN, ARETURN -> return ValueReturned(frame.getStack(0)!!)
RETURN -> return ValueReturned(VOID_VALUE)
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL -> {
if (interpreter.checkUnaryCondition(frame.getStack(0)!!, insnOpcode)) {
goto((currentInsn as JumpInsnNode).label) goto((currentInsn as JumpInsnNode).label)
continue continue
} }
}
RET -> { IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE -> {
val varNode = currentInsn as VarInsnNode if (interpreter.checkBinaryCondition(frame.getStack(0)!!, frame.getStack(1)!!, insnOpcode)) {
val address = frame.getLocal(varNode.`var`) goto((currentInsn as JumpInsnNode).label)
goto((address as LabelValue).value)
continue continue
} }
// TODO: switch
LOOKUPSWITCH -> UnsupportedByteCodeException("LOOKUPSWITCH is not supported yet")
TABLESWITCH -> UnsupportedByteCodeException("TABLESWITCH is not supported yet")
IRETURN, LRETURN, FRETURN, DRETURN, ARETURN -> return ValueReturned(frame.getStack(0)!!)
RETURN -> return ValueReturned(VOID_VALUE)
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL -> {
if (interpreter.checkUnaryCondition(frame.getStack(0)!!, insnOpcode)) {
goto((currentInsn as JumpInsnNode).label)
continue
}
}
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE -> {
if (interpreter.checkBinaryCondition(frame.getStack(0)!!, frame.getStack(1)!!, insnOpcode)) {
goto((currentInsn as JumpInsnNode).label)
continue
}
}
// TODO: try/catch/finally
ATHROW -> return ExceptionThrown(frame.getStack(0)!!)
} }
// TODO: try/catch/finally
ATHROW -> return ExceptionThrown(frame.getStack(0)!!)
} }
frame.execute(currentInsn, interpreter)
val handled = instructionHandler(currentInsn)
if (handled != null) return handled
goto(currentInsn.getNext())
} }
}
catch (e: Throwable) { try {
throw e frame.execute(currentInsn, interpreter)
}
catch (e: ThrownFromEvalException) {
// TODO: try/catch.finaly
return ExceptionThrown(e.exception)
}
val handled = instructionHandler(currentInsn)
if (handled != null) return handled
goto(currentInsn.getNext())
} }
} }