aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-11-15 13:40:21 +0000
committerMichael Williamson <mike@zwobble.org>2015-11-15 13:40:21 +0000
commit63956680fa5f6e61210e090036c797d94e4a340c (patch)
tree13680a800766d06f079720cedc21b5e24e7a4db5
parentb590542b4cb33e456a2d5e5922fbd68c391e681d (diff)
Handle boxing in infix expressions more accurately
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java22
-rw-r--r--src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java51
2 files changed, 62 insertions, 11 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
index dee5430..32662a6 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -327,10 +327,9 @@ public class JavaReader {
}
private static ExpressionNode readInfixExpression(InfixExpression expression) {
- TypeName operandType = typeOf(expression.getLeftOperand());
- if (operandType.equals(IntegerValue.REF)) {
+ if (isPrimitiveOperation(expression)) {
Operator operator = readOperator(expression.getOperator());
- return readOperation(
+ return readPrimitiveOperation(
operator,
expression.getLeftOperand(),
expression.getRightOperand());
@@ -347,6 +346,19 @@ public class JavaReader {
}
}
+ private static boolean isPrimitiveOperation(InfixExpression expression) {
+ TypeName leftOperandType = typeOf(expression.getLeftOperand());
+ TypeName rightOperandType = typeOf(expression.getRightOperand());
+ return isPrimitive(leftOperandType)
+ || isPrimitive(rightOperandType)
+ || (expression.getOperator() != InfixExpression.Operator.NOT_EQUALS
+ && expression.getOperator() != InfixExpression.Operator.EQUALS);
+ }
+
+ private static boolean isPrimitive(TypeName type) {
+ return type.equals(BooleanValue.REF) || type.equals(IntegerValue.REF);
+ }
+
private static ExpressionNode readPrefixExpression(PrefixExpression expression) {
Operator operator = readOperator(expression.getOperator());
return AssignmentNode.assign(
@@ -378,11 +390,11 @@ public class JavaReader {
left,
handleBoxing(
left.getType(),
- readOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide())));
+ readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide())));
}
}
- private static ExpressionNode readOperation(Operator operator, Expression leftJava, Expression rightJava) {
+ private static ExpressionNode readPrimitiveOperation(Operator operator, Expression leftJava, Expression rightJava) {
ExpressionNode left = readUnboxedExpression(leftJava);
ExpressionNode right = readUnboxedExpression(rightJava);
return MethodCallNode.methodCall(
diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
index c08035f..ad2f755 100644
--- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
@@ -2,7 +2,6 @@ package org.zwobble.couscous.tests.frontends.java;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Collections;
import java.util.List;
import org.junit.Test;
@@ -14,6 +13,7 @@ import org.zwobble.couscous.values.ObjectValues;
import org.zwobble.couscous.values.StringValue;
import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;
import static org.zwobble.couscous.ast.AnnotationNode.annotation;
import static org.zwobble.couscous.ast.AssignmentNode.assign;
@@ -168,14 +168,14 @@ public class JavaReaderTests {
public void canUseOperatorsOnReferences() {
assertEquals(
same(
- constructorCall(TypeName.of("java.lang.Object"), Collections.emptyList()),
- constructorCall(TypeName.of("java.lang.Object"), Collections.emptyList())),
+ constructorCall(TypeName.of("java.lang.Object"), emptyList()),
+ constructorCall(TypeName.of("java.lang.Object"), emptyList())),
readExpression("new Object() == new Object()"));
assertEquals(
not(same(
- constructorCall(TypeName.of("java.lang.Object"), Collections.emptyList()),
- constructorCall(TypeName.of("java.lang.Object"), Collections.emptyList()))),
+ constructorCall(TypeName.of("java.lang.Object"), emptyList()),
+ constructorCall(TypeName.of("java.lang.Object"), emptyList()))),
readExpression("new Object() != new Object()"));
}
@@ -216,7 +216,46 @@ public class JavaReaderTests {
lessThanOrEqual(literal(1), literal(2)),
readExpression("1 <= 2"));
}
-
+
+ @Test
+ public void equalityOperatorUnboxesIfExactlyOneOperandIsPrimitive() {
+ assertEquals(
+ equal(
+ literal(1),
+ unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))))),
+ readExpression("1 == new Integer(1)"));
+
+ assertEquals(
+ notEqual(
+ literal(1),
+ unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))))),
+ readExpression("1 != new Integer(1)"));
+ }
+
+ @Test
+ public void equalityOperatorDoesNotUnboxIfBothOperandsAreBoxed() {
+ assertEquals(
+ same(
+ constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))),
+ constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2)))),
+ readExpression("new Integer(1) == new Integer(2)"));
+
+ assertEquals(
+ not(same(
+ constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))),
+ constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2))))),
+ readExpression("new Integer(1) != new Integer(2)"));
+ }
+
+ @Test
+ public void integerOperatorUnboxesWhenBothOperandsAreBoxed() {
+ assertEquals(
+ integerAdd(
+ unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1)))),
+ unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2))))),
+ readExpression("new Integer(1) + new Integer(2)"));
+ }
+
@Test
public void canReadTernaryConditionals() {
assertEquals(