diff --git a/modules/wyc/src/wyc/builder/CodeGenerator.java b/modules/wyc/src/wyc/builder/CodeGenerator.java index ff1de6a10e..c0b21b78aa 100644 --- a/modules/wyc/src/wyc/builder/CodeGenerator.java +++ b/modules/wyc/src/wyc/builder/CodeGenerator.java @@ -1341,10 +1341,8 @@ public void generateCondition(String target, Expr condition, Environment environ // true. In some cases, we could actually do better. For // example, !(x < 5) could be rewritten into x >= 5. - int r1 = generate(condition, environment, block, forest, context); - int r2 = environment.allocate(Type.T_BOOL); - block.add(Bytecode.Const(r2, Constant.V_BOOL(true)), attributes(condition)); - block.add(Bytecode.If(Type.T_BOOL, r1, r2, Bytecode.Comparator.EQ, target), attributes(condition)); + int result = generate(condition, environment, block, forest, context); + block.add(Bytecode.If(Type.T_BOOL, result, target), attributes(condition)); } else { syntaxError(errorMessage(INVALID_BOOLEAN_EXPRESSION), context, condition); @@ -1435,10 +1433,7 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm generateTypeCondition(target, v, environment, block, forest, context); } else { - - Bytecode.Comparator cop = OP2COP(bop, v, context); - - if (cop == Bytecode.Comparator.EQ && v.lhs instanceof Expr.LocalVariable && v.rhs instanceof Expr.Constant + if (bop == Expr.BOp.EQ && v.lhs instanceof Expr.LocalVariable && v.rhs instanceof Expr.Constant && ((Expr.Constant) v.rhs).value == Constant.V_NULL) { // this is a simple rewrite to enable type inference. Expr.LocalVariable lhs = (Expr.LocalVariable) v.lhs; @@ -1447,7 +1442,7 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm } int slot = environment.get(lhs.var); block.add(Bytecode.IfIs(v.srcType.raw(), slot, Type.T_NULL, target), attributes(v)); - } else if (cop == Bytecode.Comparator.NEQ && v.lhs instanceof Expr.LocalVariable + } else if (bop == Expr.BOp.NEQ && v.lhs instanceof Expr.LocalVariable && v.rhs instanceof Expr.Constant && ((Expr.Constant) v.rhs).value == Constant.V_NULL) { // this is a simple rewrite to enable type inference. String exitLabel = CodeUtils.freshLabel(); @@ -1460,9 +1455,8 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm block.add(Bytecode.Goto(target)); block.add(Bytecode.Label(exitLabel)); } else { - int lhs = generate(v.lhs, environment, block, forest, context); - int rhs = generate(v.rhs, environment, block, forest, context); - block.add(Bytecode.If(v.srcType.raw(), lhs, rhs, cop, target), attributes(v)); + int result = generate(v, environment, block, forest, context); + block.add(Bytecode.If(v.srcType.raw(), result, target), attributes(v)); } } } @@ -1949,10 +1943,8 @@ private int generate(Expr.Cast expr, Environment environment, CodeForest.Block b private int generate(Expr.BinOp v, Environment environment, CodeForest.Block block, CodeForest forest, Context context) throws Exception { - // could probably use a range test for this somehow - if (v.op == Expr.BOp.EQ || v.op == Expr.BOp.NEQ || v.op == Expr.BOp.LT || v.op == Expr.BOp.LTEQ - || v.op == Expr.BOp.GT || v.op == Expr.BOp.GTEQ || v.op == Expr.BOp.AND || v.op == Expr.BOp.OR) { + if(v.op == Expr.BOp.AND || v.op == Expr.BOp.OR) { String trueLabel = CodeUtils.freshLabel(); String exitLabel = CodeUtils.freshLabel(); generateCondition(trueLabel, v, environment, block, forest, context); @@ -1963,7 +1955,6 @@ private int generate(Expr.BinOp v, Environment environment, CodeForest.Block blo block.add(Bytecode.Const(target, Constant.V_BOOL(true)), attributes(v)); block.add(Bytecode.Label(exitLabel)); return target; - } else { Type result = v.result().raw(); int[] targets = new int[] { environment.allocate(result) }; @@ -1972,8 +1963,7 @@ private int generate(Expr.BinOp v, Environment environment, CodeForest.Block blo generate(v.rhs, environment, block, forest, context) }; - block.add(Bytecode.Operator(result, targets, operands, OP2BOP(v.op, v, context)), - attributes(v)); + block.add(Bytecode.Operator(result, targets, operands, OP2BOP(v.op, v, context)), attributes(v)); return targets[0]; } @@ -2070,6 +2060,18 @@ private Bytecode.OperatorKind OP2BOP(Expr.BOp bop, SyntacticElement elem, Contex return Bytecode.OperatorKind.DIV; case REM: return Bytecode.OperatorKind.REM; + case EQ: + return Bytecode.OperatorKind.EQ; + case NEQ: + return Bytecode.OperatorKind.NEQ; + case LT: + return Bytecode.OperatorKind.LT; + case LTEQ: + return Bytecode.OperatorKind.LTEQ; + case GT: + return Bytecode.OperatorKind.GT; + case GTEQ: + return Bytecode.OperatorKind.GTEQ; case BITWISEAND: return Bytecode.OperatorKind.BITWISEAND; case BITWISEOR: @@ -2087,27 +2089,6 @@ private Bytecode.OperatorKind OP2BOP(Expr.BOp bop, SyntacticElement elem, Contex return null; } - private Bytecode.Comparator OP2COP(Expr.BOp bop, SyntacticElement elem, Context context) { - switch (bop) { - case EQ: - return Bytecode.Comparator.EQ; - case NEQ: - return Bytecode.Comparator.NEQ; - case LT: - return Bytecode.Comparator.LT; - case LTEQ: - return Bytecode.Comparator.LTEQ; - case GT: - return Bytecode.Comparator.GT; - case GTEQ: - return Bytecode.Comparator.GTEQ; - default: - syntaxError(errorMessage(INVALID_BOOLEAN_EXPRESSION), context, elem); - } - // dead-code - return null; - } - @SuppressWarnings("incomplete-switch") private static Expr invert(Expr e) { if (e instanceof Expr.BinOp) { diff --git a/modules/wyil/src/wyil/checks/DefiniteAssignmentCheck.java b/modules/wyil/src/wyil/checks/DefiniteAssignmentCheck.java index 480b1ccc2f..317eeac21a 100755 --- a/modules/wyil/src/wyil/checks/DefiniteAssignmentCheck.java +++ b/modules/wyil/src/wyil/checks/DefiniteAssignmentCheck.java @@ -121,7 +121,7 @@ public HashSet propagate(CodeForest.Index index, Bytecode code, HashSet public Pair, HashSet> propagate(CodeForest.Index index, Bytecode.If igoto, HashSet in) { - if (!in.contains(igoto.operand(0)) || !in.contains(igoto.operand(1))) { + if (!in.contains(igoto.operand(0))) { syntaxError(errorMessage(VARIABLE_POSSIBLY_UNITIALISED), filename, forest.get(index).attribute(SourceLocation.class)); } diff --git a/modules/wyil/src/wyil/io/WyilFileReader.java b/modules/wyil/src/wyil/io/WyilFileReader.java index 491ed91c7a..732e3e8b1a 100644 --- a/modules/wyil/src/wyil/io/WyilFileReader.java +++ b/modules/wyil/src/wyil/io/WyilFileReader.java @@ -962,63 +962,68 @@ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types // ========================================================================= // Binary Operators // ========================================================================= - schemas[Bytecode.OPCODE_ifeq] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + schemas[Bytecode.OPCODE_if] = new Schema(Targets.ZERO, Operands.ONE, Types.ONE, Extras.TARGET){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.EQ, (String) extras[0]); + return Bytecode.If(types[0], operands[0], (String) extras[0]); } }; - schemas[Bytecode.OPCODE_ifne] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + + // ========================================================================= + // Binary Assignables + // ========================================================================= + schemas[Bytecode.OPCODE_add] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.NEQ, (String) extras[0]); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.ADD); } }; - schemas[Bytecode.OPCODE_iflt] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + schemas[Bytecode.OPCODE_sub] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.LT, (String) extras[0]); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.SUB); } }; - schemas[Bytecode.OPCODE_ifle] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + schemas[Bytecode.OPCODE_mul] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.LTEQ, (String) extras[0]); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.MUL); } }; - schemas[Bytecode.OPCODE_ifgt] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + schemas[Bytecode.OPCODE_div] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.GT, (String) extras[0]); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.DIV); } }; - schemas[Bytecode.OPCODE_ifge] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){ + schemas[Bytecode.OPCODE_rem] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.GTEQ, (String) extras[0]); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.REM); } }; - - // ========================================================================= - // Binary Assignables - // ========================================================================= - schemas[Bytecode.OPCODE_add] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + schemas[Bytecode.OPCODE_eq] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.ADD); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.EQ); } }; - schemas[Bytecode.OPCODE_sub] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + schemas[Bytecode.OPCODE_ne] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.SUB); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.NEQ); } }; - schemas[Bytecode.OPCODE_mul] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + schemas[Bytecode.OPCODE_lt] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.MUL); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.LT); } }; - schemas[Bytecode.OPCODE_div] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + schemas[Bytecode.OPCODE_le] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.DIV); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.LTEQ); } }; - schemas[Bytecode.OPCODE_rem] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + schemas[Bytecode.OPCODE_gt] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { - return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.REM); + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.GT); + } + }; + schemas[Bytecode.OPCODE_ge] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ + public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) { + return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.GTEQ); } }; schemas[Bytecode.OPCODE_bitwiseor] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){ diff --git a/modules/wyil/src/wyil/lang/Bytecode.java b/modules/wyil/src/wyil/lang/Bytecode.java index d2378da2dc..28019ffd2f 100755 --- a/modules/wyil/src/wyil/lang/Bytecode.java +++ b/modules/wyil/src/wyil/lang/Bytecode.java @@ -447,8 +447,8 @@ public static Return Return(Type[] types, int... operands) { return new Return(types, operands); } - public static If If(Type type, int leftOperand, int rightOperand, Comparator cop, String label) { - return new If(type, leftOperand, rightOperand, cop, label); + public static If If(Type type, int operand, String label) { + return new If(type, operand, label); } public static IfIs IfIs(Type type, int leftOperand, Type rightOperand, String label) { @@ -558,57 +558,87 @@ public String toString() { return "rem"; } }, - BITWISEOR(9) { + EQ(9) { + public String toString() { + return "eq"; + } + }, + NEQ(10) { + public String toString() { + return "ne"; + } + }, + LT(11) { + public String toString() { + return "lt"; + } + }, + LTEQ(12) { + public String toString() { + return "le"; + } + }, + GT(13) { + public String toString() { + return "gt"; + } + }, + GTEQ(14) { + public String toString() { + return "ge"; + } + }, + BITWISEOR(15) { public String toString() { return "or"; } }, - BITWISEXOR(10) { + BITWISEXOR(16) { public String toString() { return "xor"; } }, - BITWISEAND(11) { + BITWISEAND(17) { public String toString() { return "and"; } }, - LEFTSHIFT(12) { + LEFTSHIFT(18) { public String toString() { return "shl"; } }, - RIGHTSHIFT(13) { + RIGHTSHIFT(19) { public String toString() { return "shr"; } }, - ARRAYINDEX(14) { + ARRAYINDEX(20) { public String toString() { return "indexof"; } }, - ARRAYGENERATOR(15) { + ARRAYGENERATOR(21) { public String toString() { return "arraygen"; } }, - ARRAYCONSTRUCTOR(16) { + ARRAYCONSTRUCTOR(22) { public String toString() { return "array"; } }, - RECORDCONSTRUCTOR(17) { + RECORDCONSTRUCTOR(23) { public String toString() { return "record"; } }, - NEW(18) { + NEW(24) { public String toString() { return "new"; } }, - ASSIGN(19) { + ASSIGN(25) { public String toString() { return "assign"; } @@ -1190,11 +1220,8 @@ public String toString() { * */ public static final class If extends Branching { - public final Comparator op; - - private If(Type type, int leftOperand, int rightOperand, Comparator op, String target) { - super(target, new Type[] { type }, new int[0], leftOperand, rightOperand); - this.op = op; + private If(Type type, int operand, String target) { + super(target, new Type[] { type }, new int[0], operand); } public If relabel(Map labels) { @@ -1202,81 +1229,28 @@ public If relabel(Map labels) { if (nlabel == null) { return this; } else { - return If(types[0], operands[0], operands[1], op, nlabel); + return If(types[0], operands[0], nlabel); } } public int opcode() { - return OPCODE_ifeq + op.offset; + return OPCODE_if; } @Override public Bytecode clone(int[] nTargets, int[] nOperands) { - return If(types[0], nOperands[0], nOperands[1], op, destination()); - } - - public int hashCode() { - return super.hashCode() + op.hashCode(); + return If(types[0], nOperands[0], destination()); } public boolean equals(Object o) { - if (o instanceof If) { - If ig = (If) o; - return op == ig.op && super.equals(ig); - } - return false; + return o instanceof If && super.equals(o); } public String toString() { - return "if" + op + " %" + operands[0] + ", %" + operands[1] + " goto " + destination() + " : " + types[0]; + return "if" + " %" + operands[0] + " goto " + destination() + " : " + types[0]; } } - /** - * Represents a comparison operator (e.g. '==','!=',etc) that is provided to - * a IfGoto bytecode. - * - * @author David J. Pearce - * - */ - public enum Comparator { - EQ(0) { - public String toString() { - return "eq"; - } - }, - NEQ(1) { - public String toString() { - return "ne"; - } - }, - LT(2) { - public String toString() { - return "lt"; - } - }, - LTEQ(3) { - public String toString() { - return "le"; - } - }, - GT(4) { - public String toString() { - return "gt"; - } - }, - GTEQ(5) { - public String toString() { - return "ge"; - } - }; - public int offset; - - private Comparator(int offset) { - this.offset = offset; - } - }; - /** * Branches conditionally to the given label based on the result of a * runtime type test against a value from the operand register. More @@ -2254,12 +2228,7 @@ private static int[] append(int operand, int[] operands) { // Binary Operators public static final int BINARY_OPERATOR = UNARY_ASSIGNABLE+11; - public static final int OPCODE_ifeq = BINARY_OPERATOR+0; - public static final int OPCODE_ifne = BINARY_OPERATOR+1; - public static final int OPCODE_iflt = BINARY_OPERATOR+2; - public static final int OPCODE_ifle = BINARY_OPERATOR+3; - public static final int OPCODE_ifgt = BINARY_OPERATOR+4; - public static final int OPCODE_ifge = BINARY_OPERATOR+5; + public static final int OPCODE_if = BINARY_OPERATOR+0; // Binary Assignables public static final int BINARY_ASSIGNABLE = BINARY_OPERATOR+6; @@ -2273,20 +2242,26 @@ private static int[] append(int operand, int[] operands) { public static final int OPCODE_mul = BINARY_ASSIGNABLE+6; public static final int OPCODE_div = BINARY_ASSIGNABLE+7; public static final int OPCODE_rem = BINARY_ASSIGNABLE+8; - public static final int OPCODE_bitwiseor = BINARY_ASSIGNABLE+9; - public static final int OPCODE_bitwisexor = BINARY_ASSIGNABLE+10; - public static final int OPCODE_bitwiseand = BINARY_ASSIGNABLE+11; - public static final int OPCODE_lshr = BINARY_ASSIGNABLE+12; - public static final int OPCODE_rshr = BINARY_ASSIGNABLE+13; - public static final int OPCODE_arrayindex = BINARY_ASSIGNABLE+14; - public static final int OPCODE_arrygen = BINARY_ASSIGNABLE+15; - public static final int OPCODE_array = BINARY_ASSIGNABLE+16; - public static final int OPCODE_record = BINARY_ASSIGNABLE+17; - public static final int OPCODE_newobject = BINARY_ASSIGNABLE+18; - public static final int OPCODE_assign = BINARY_ASSIGNABLE+19; + public static final int OPCODE_eq = BINARY_ASSIGNABLE+9; + public static final int OPCODE_ne = BINARY_ASSIGNABLE+10; + public static final int OPCODE_lt = BINARY_ASSIGNABLE+11; + public static final int OPCODE_le = BINARY_ASSIGNABLE+12; + public static final int OPCODE_gt = BINARY_ASSIGNABLE+13; + public static final int OPCODE_ge = BINARY_ASSIGNABLE+14; + public static final int OPCODE_bitwiseor = BINARY_ASSIGNABLE+15; + public static final int OPCODE_bitwisexor = BINARY_ASSIGNABLE+16; + public static final int OPCODE_bitwiseand = BINARY_ASSIGNABLE+17; + public static final int OPCODE_lshr = BINARY_ASSIGNABLE+18; + public static final int OPCODE_rshr = BINARY_ASSIGNABLE+19; + public static final int OPCODE_arrayindex = BINARY_ASSIGNABLE+20; + public static final int OPCODE_arrygen = BINARY_ASSIGNABLE+21; + public static final int OPCODE_array = BINARY_ASSIGNABLE+22; + public static final int OPCODE_record = BINARY_ASSIGNABLE+23; + public static final int OPCODE_newobject = BINARY_ASSIGNABLE+24; + public static final int OPCODE_assign = BINARY_ASSIGNABLE+25; // Nary Assignables - public static final int NARY_ASSIGNABLE = BINARY_ASSIGNABLE+20; + public static final int NARY_ASSIGNABLE = BINARY_ASSIGNABLE+26; public static final int OPCODE_invoke = NARY_ASSIGNABLE+2; public static final int OPCODE_indirectinvoke = NARY_ASSIGNABLE+3; diff --git a/modules/wyil/src/wyil/lang/CodeUtils.java b/modules/wyil/src/wyil/lang/CodeUtils.java index bcabacbd88..287e8639e9 100644 --- a/modules/wyil/src/wyil/lang/CodeUtils.java +++ b/modules/wyil/src/wyil/lang/CodeUtils.java @@ -5,8 +5,6 @@ import java.util.HashMap; import java.util.Map; -import wyil.lang.Bytecode.Comparator; - public class CodeUtils { private static int _idx=0; @@ -48,30 +46,6 @@ public static int[] remapOperands(Map binding, int[] operands) } return nOperands; } - - /** - * Determine the inverse comparator, or null if no inverse exists. - * - * @param cop - * @return - */ - public static Bytecode.Comparator invert(Bytecode.Comparator cop) { - switch (cop) { - case EQ: - return Bytecode.Comparator.NEQ; - case NEQ: - return Bytecode.Comparator.EQ; - case LT: - return Bytecode.Comparator.GTEQ; - case LTEQ: - return Bytecode.Comparator.GT; - case GT: - return Bytecode.Comparator.LTEQ; - case GTEQ: - return Bytecode.Comparator.LT; - } - return null; - } /** * Construct a mapping from labels to their block indices within a root diff --git a/modules/wyil/src/wyil/util/interpreter/Interpreter.java b/modules/wyil/src/wyil/util/interpreter/Interpreter.java index fc998ad4b6..11c7dc9c66 100644 --- a/modules/wyil/src/wyil/util/interpreter/Interpreter.java +++ b/modules/wyil/src/wyil/util/interpreter/Interpreter.java @@ -474,35 +474,9 @@ private Object execute(Bytecode.Goto bytecode, Constant[] frame, Context context } private Object execute(Bytecode.If bytecode, Constant[] frame, Context context) { - Constant op1 = frame[bytecode.operand(0)]; - Constant op2 = frame[bytecode.operand(1)]; - boolean result; - switch (bytecode.op) { - // Handle cases which apply to all values - case EQ: - result = op1.equals(op2); - break; - case NEQ: - result = !op1.equals(op2); - break; - // Handle arithmetic cases - case LT: - result = lessThan(op1, op2, true, context); - break; - case LTEQ: - result = lessThan(op1, op2, false, context); - break; - case GT: - result = lessThan(op2, op1, true, context); - break; - case GTEQ: - result = lessThan(op2, op1, false, context); - break; - default: - return deadCode(context); - } - - if (result) { + Constant.Bool operand = checkType(frame[bytecode.operand(0)],context,Constant.Bool.class); + + if (operand.value) { // branch taken, so jump to destination label return context.getLabel(bytecode.destination()); } else { @@ -511,27 +485,6 @@ private Object execute(Bytecode.If bytecode, Constant[] frame, Context context) } } - private boolean elementOf(Constant lhs, Constant rhs, Context context) { - checkType(rhs, context, Constant.Array.class); - Constant.Array list = (Constant.Array) rhs; - return list.values.contains(lhs); - } - - private boolean lessThan(Constant lhs, Constant rhs, boolean isStrict, Context context) { - checkType(lhs, context, Constant.Integer.class); - checkType(rhs, context, Constant.Integer.class); - Constant.Integer lhs_i = (Constant.Integer) lhs; - Constant.Integer rhs_i = (Constant.Integer) rhs; - int result = lhs_i.compareTo(rhs_i); - // In the strict case, the lhs must be strictly below the rhs. In the - // non-strict case, they can be equal. - if (isStrict) { - return result < 0; - } else { - return result <= 0; - } - } - private Object execute(Bytecode.IfIs bytecode, Constant[] frame, Context context) { Type typeOperand = bytecode.type(1); Constant op = frame[bytecode.operand(0)]; diff --git a/modules/wyil/src/wyil/util/interpreter/StandardFunctions.java b/modules/wyil/src/wyil/util/interpreter/StandardFunctions.java index c3966c93d6..520f5f2634 100644 --- a/modules/wyil/src/wyil/util/interpreter/StandardFunctions.java +++ b/modules/wyil/src/wyil/util/interpreter/StandardFunctions.java @@ -30,6 +30,14 @@ public class StandardFunctions { standardFunctions[Bytecode.OPCODE_mul ] = new Multiply(); standardFunctions[Bytecode.OPCODE_div ] = new Divide(); standardFunctions[Bytecode.OPCODE_rem ] = new Remainder(); + + standardFunctions[Bytecode.OPCODE_eq ] = new Equal(); + standardFunctions[Bytecode.OPCODE_ne ] = new NotEqual(); + standardFunctions[Bytecode.OPCODE_lt ] = new LessThan(); + standardFunctions[Bytecode.OPCODE_le ] = new LessThanEqual(); + standardFunctions[Bytecode.OPCODE_gt ] = new GreaterThan(); + standardFunctions[Bytecode.OPCODE_ge ] = new GreaterThanEqual(); + standardFunctions[Bytecode.OPCODE_bitwiseor] = new BitwiseOr(); standardFunctions[Bytecode.OPCODE_bitwisexor] = new BitwiseXor(); standardFunctions[Bytecode.OPCODE_bitwiseand] = new BitwiseAnd(); @@ -128,7 +136,42 @@ public Constant apply(Constant[] operands, Context context) { return lhs.remainder(rhs); } } - + private static final class Equal implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return Constant.V_BOOL(operands[0].equals(operands[1])); + } + } + private static final class NotEqual implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return Constant.V_BOOL(!operands[0].equals(operands[1])); + } + } + private static final class LessThan implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return lessThan(operands[0],operands[1],true,context); + } + } + private static final class LessThanEqual implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return lessThan(operands[0],operands[1],false,context); + } + } + private static final class GreaterThan implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return lessThan(operands[1],operands[0],true,context); + } + } + private static final class GreaterThanEqual implements InternalFunction { + @Override + public Constant apply(Constant[] operands, Context context) { + return lessThan(operands[1],operands[0],false,context); + } + } // ==================================================================================== // Bytes // ==================================================================================== @@ -254,4 +297,25 @@ public Constant apply(Constant[] operands, Context context) { return Constant.V_RECORD(values); } } + + + // ==================================================================================== + // Helpers + // ==================================================================================== + private static Constant.Bool lessThan(Constant lhs, Constant rhs, boolean isStrict, Context context) { + checkType(lhs, context, Constant.Integer.class); + checkType(rhs, context, Constant.Integer.class); + Constant.Integer lhs_i = (Constant.Integer) lhs; + Constant.Integer rhs_i = (Constant.Integer) rhs; + int result = lhs_i.compareTo(rhs_i); + // In the strict case, the lhs must be strictly below the rhs. In the + // non-strict case, they can be equal. + if (isStrict) { + return Constant.V_BOOL(result < 0); + } else { + return Constant.V_BOOL(result <= 0); + } + + } + }