generate boolean not

This commit is contained in:
Dmitry Jemerov
2011-04-08 18:57:54 +02:00
parent 5bebb848b6
commit 6c1bda7f5a
3 changed files with 63 additions and 8 deletions
@@ -643,6 +643,10 @@ public class ExpressionCodegen extends JetVisitor {
if (isNumberPrimitive(cls)) {
if (generateUnaryOp(op, asmType, expression.getBaseExpression())) return;
}
else if (isClass(cls, "Boolean") && op.getName().equals("not")) {
generateNot(expression);
return;
}
}
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
}
@@ -680,6 +684,13 @@ public class ExpressionCodegen extends JetVisitor {
return false;
}
private void generateNot(JetPrefixExpression expression) {
int oldStackSize = myStack.size();
gen(expression.getBaseExpression());
assert myStack.size() == oldStackSize+1;
myStack.set(myStack.size()-1, StackValue.not(myStack.get(myStack.size() - 1)));
}
private int generateIncrement(DeclarationDescriptor op, Type asmType, JetExpression operand) {
if (!(operand instanceof JetReferenceExpression)) {
throw new UnsupportedOperationException("cannot increment or decrement a non-lvalue");
@@ -36,6 +36,10 @@ public abstract class StackValue {
return new NumberCompare(opToken);
}
public static StackValue not(StackValue stackValue) {
return new Invert(stackValue);
}
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v);
private static void box(final Type type, InstructionAdapter v) {
@@ -74,6 +78,17 @@ public abstract class StackValue {
}
}
protected void putAsBoolean(InstructionAdapter v) {
Label ifTrue = new Label();
Label end = new Label();
condJump(ifTrue, false, v);
v.iconst(0);
v.goTo(end);
v.mark(ifTrue);
v.iconst(1);
v.mark(end);
}
public static class Local extends StackValue {
private final int index;
@@ -168,14 +183,7 @@ public abstract class StackValue {
if (type != Type.BOOLEAN_TYPE) {
throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type");
}
Label ifTrue = new Label();
Label end = new Label();
condJump(ifTrue, false, v);
v.iconst(0);
v.goTo(end);
v.mark(ifTrue);
v.iconst(1);
v.mark(end);
putAsBoolean(v);
}
@Override
@@ -219,4 +227,26 @@ public abstract class StackValue {
v.visitJumpInsn(opcode, label);
}
}
private static class Invert extends StackValue {
private StackValue myOperand;
private Invert(StackValue operand) {
super(operand.type);
myOperand = operand;
}
@Override
public void put(Type type, InstructionAdapter v) {
if (type != Type.BOOLEAN_TYPE) {
throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type");
}
putAsBoolean(v);
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
myOperand.condJump(label, !jumpIfFalse, v);
}
}
}
@@ -437,6 +437,20 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(6L, main.invoke(null, 2L));
}
public void testBooleanNot() throws Exception {
loadText("fun foo(b: Boolean): Boolean = !b");
final Method main = generateFunction();
assertEquals(true, main.invoke(null, false));
assertEquals(false, main.invoke(null, true));
}
public void testBooleanNotJump() throws Exception {
loadText("fun foo(a: Int) : Int = if (!(a < 5)) a else 0");
final Method main = generateFunction();
assertEquals(6, main.invoke(null, 6));
assertEquals(0, main.invoke(null, 4));
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text);
System.out.println(generateToText());