From f1601b2da0485048c94249277238c3b7a5160fc8 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Sun, 6 Oct 2013 03:52:09 +0400 Subject: [PATCH] Eval and Control separated --- src/org/jetbrains/eval4j/interpreter.kt | 74 +++++++++++++------------ 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/org/jetbrains/eval4j/interpreter.kt b/src/org/jetbrains/eval4j/interpreter.kt index 42ebcc573b4..fadaffee183 100644 --- a/src/org/jetbrains/eval4j/interpreter.kt +++ b/src/org/jetbrains/eval4j/interpreter.kt @@ -17,7 +17,7 @@ import org.objectweb.asm.Label class UnsupportedByteCodeException(message: String) : RuntimeException(message) -trait EvalStrategy { +trait Eval { fun loadClass(classType: Type): Value fun newInstance(classType: Type): Value fun checkCast(value: Value, targetType: Type): Value @@ -39,14 +39,16 @@ trait EvalStrategy { fun getLocalVariable(index: Int): Value fun setLocalVariable(index: Int, newValue: Value) +} +trait Control { fun jump(label: Label) fun returnValue(value: Value) fun throwException(value: Value) } -class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter(ASM4) { +class EvalInterpreter(private val eval: Eval, private val control: Control) : Interpreter(ASM4) { override fun newValue(`type`: Type?): Value? { if (`type` == null) { return NOT_A_VALUE @@ -95,7 +97,7 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { val sort = (cst as Type).getSort() when (sort) { - Type.OBJECT, Type.ARRAY -> evalStrategy.loadClass(cst) + Type.OBJECT, Type.ARRAY -> eval.loadClass(cst) Type.METHOD -> throw UnsupportedByteCodeException("Mothod handles are not supported") else -> throw UnsupportedByteCodeException("Illegal LDC constant " + cst) } @@ -105,8 +107,8 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter LabelValue((insn as JumpInsnNode).label.getLabel()) - GETSTATIC -> evalStrategy.getStaticField((insn as FieldInsnNode).desc) - NEW -> evalStrategy.newInstance(Type.getType((insn as TypeInsnNode).desc)) + GETSTATIC -> eval.getStaticField((insn as FieldInsnNode).desc) + NEW -> eval.newInstance(Type.getType((insn as TypeInsnNode).desc)) else -> throw UnsupportedByteCodeException("$insn") } } @@ -144,14 +146,14 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { val label = (insn as JumpInsnNode).label.getLabel() when (insn.getOpcode()) { - IFEQ -> if (value.int == 0) evalStrategy.jump(label) - IFNE -> if (value.int != 0) evalStrategy.jump(label) - IFLT -> if (value.int < 0) evalStrategy.jump(label) - IFGT -> if (value.int > 0) evalStrategy.jump(label) - IFLE -> if (value.int <= 0) evalStrategy.jump(label) - IFGE -> if (value.int >= 0) evalStrategy.jump(label) - IFNULL -> if (value.obj == null) evalStrategy.jump(label) - IFNONNULL -> if (value.obj != null) evalStrategy.jump(label) + IFEQ -> if (value.int == 0) control.jump(label) + IFNE -> if (value.int != 0) control.jump(label) + IFLT -> if (value.int < 0) control.jump(label) + IFGT -> if (value.int > 0) control.jump(label) + IFLE -> if (value.int <= 0) control.jump(label) + IFGE -> if (value.int >= 0) control.jump(label) + IFNULL -> if (value.obj == null) control.jump(label) + IFNONNULL -> if (value.obj != null) control.jump(label) } null } @@ -161,11 +163,11 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter throw UnsupportedByteCodeException("Switch is not supported yet") PUTSTATIC -> { - evalStrategy.setStaticField((insn as FieldInsnNode).desc, value) + eval.setStaticField((insn as FieldInsnNode).desc, value) null } - GETFIELD -> evalStrategy.getField(value, (insn as FieldInsnNode).desc) + GETFIELD -> eval.getField(value, (insn as FieldInsnNode).desc) NEWARRAY -> { val typeStr = when ((insn as IntInsnNode).operand) { @@ -179,27 +181,27 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter "[J" else -> throw AnalyzerException(insn, "Invalid array type") } - evalStrategy.newArray(Type.getType(typeStr), value.int) + eval.newArray(Type.getType(typeStr), value.int) } ANEWARRAY -> { val desc = (insn as TypeInsnNode).desc - evalStrategy.newArray(Type.getType("[" + Type.getObjectType(desc)), value.int) + eval.newArray(Type.getType("[" + Type.getObjectType(desc)), value.int) } - ARRAYLENGTH -> evalStrategy.getArrayLength(value) + ARRAYLENGTH -> eval.getArrayLength(value) ATHROW -> { - evalStrategy.throwException(value) + control.throwException(value) null } CHECKCAST -> { val targetType = Type.getObjectType((insn as TypeInsnNode).desc) - evalStrategy.checkCast(value, targetType) + eval.checkCast(value, targetType) } INSTANCEOF -> { val targetType = Type.getObjectType((insn as TypeInsnNode).desc) - boolean(evalStrategy.isInsetanceOf(value, targetType)) + boolean(eval.isInsetanceOf(value, targetType)) } // TODO: maybe just do nothing? @@ -213,7 +215,7 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter evalStrategy.getArrayElement(value1, value2) + AALOAD -> eval.getArrayElement(value1, value2) IADD -> int(value1.int + value2.int) ISUB -> int(value1.int - value2.int) @@ -293,21 +295,21 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { val label = (insn as JumpInsnNode).label.getLabel() when (insn.getOpcode()) { - IF_ICMPEQ -> if (value1.int == value2.int) evalStrategy.jump(label) - IF_ICMPNE -> if (value1.int != value2.int) evalStrategy.jump(label) - IF_ICMPLT -> if (value1.int < value2.int) evalStrategy.jump(label) - IF_ICMPGT -> if (value1.int > value2.int) evalStrategy.jump(label) - IF_ICMPLE -> if (value1.int <= value2.int) evalStrategy.jump(label) - IF_ICMPGE -> if (value1.int >= value2.int) evalStrategy.jump(label) + IF_ICMPEQ -> if (value1.int == value2.int) control.jump(label) + IF_ICMPNE -> if (value1.int != value2.int) control.jump(label) + IF_ICMPLT -> if (value1.int < value2.int) control.jump(label) + IF_ICMPGT -> if (value1.int > value2.int) control.jump(label) + IF_ICMPLE -> if (value1.int <= value2.int) control.jump(label) + IF_ICMPGE -> if (value1.int >= value2.int) control.jump(label) - IF_ACMPEQ -> if (value1.obj == value2.obj) evalStrategy.jump(label) - IF_ACMPNE -> if (value1.obj != value2.obj) evalStrategy.jump(label) + IF_ACMPEQ -> if (value1.obj == value2.obj) control.jump(label) + IF_ACMPNE -> if (value1.obj != value2.obj) control.jump(label) } null } PUTFIELD -> { - evalStrategy.setField(value1, (insn as FieldInsnNode).desc, value2) + eval.setField(value1, (insn as FieldInsnNode).desc, value2) null } @@ -318,7 +320,7 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { - evalStrategy.setArrayElement(value1, value2, value3) + eval.setArrayElement(value1, value2, value3) null } else -> throw UnsupportedByteCodeException("$insn") @@ -329,12 +331,12 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { val node = insn as MultiANewArrayInsnNode - evalStrategy.newMultiDimensionalArray(Type.getType(node.desc), values.map { v -> v.int }) + eval.newMultiDimensionalArray(Type.getType(node.desc), values.map { v -> v.int }) } INVOKEVIRTUAL, INVOKESPECIAL, INVOKEINTERFACE -> { val desc = (insn as MethodInsnNode).desc - evalStrategy.invokeMethod( + eval.invokeMethod( values[0], desc, values.subList(1, values.size()), @@ -342,7 +344,7 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter evalStrategy.invokeStaticMethod((insn as MethodInsnNode).desc, values) + INVOKESTATIC -> eval.invokeStaticMethod((insn as MethodInsnNode).desc, values) INVOKEDYNAMIC -> throw UnsupportedByteCodeException("INVOKEDYNAMIC is not supported") else -> throw UnsupportedByteCodeException("$insn") @@ -358,7 +360,7 @@ class EvalInterpreter(private val evalStrategy: EvalStrategy) : Interpreter { // TODO: coercion, maybe? - evalStrategy.returnValue(value) + control.returnValue(value) } else -> throw UnsupportedByteCodeException("$insn")