From d8e0031c6d73ba960505601d8e4b3c1933e584ea Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 31 Oct 2015 18:56:24 +0000 Subject: Support reading of unboxing --- .../zwobble/couscous/ast/StaticMethodCallNode.java | 17 ++++++++++ .../couscous/frontends/java/JavaReader.java | 14 ++++++++ .../tests/frontends/java/JavaReaderTests.java | 38 +++++++++++++++++++--- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java index 06c63da..b33e94c 100644 --- a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java @@ -4,6 +4,7 @@ import java.util.List; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; import org.zwobble.couscous.values.BooleanValue; +import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.InternalCouscousValue; import org.zwobble.couscous.values.ObjectValues; @@ -21,6 +22,14 @@ public class StaticMethodCallNode implements ExpressionNode { asList(value), ObjectValues.BOXED_INT); } + + public static ExpressionNode unboxInt(ExpressionNode value) { + return staticMethodCall( + InternalCouscousValue.REF, + "unboxInt", + asList(value), + IntegerValue.REF); + } public static ExpressionNode boxBoolean(ExpressionNode value) { return staticMethodCall( @@ -29,6 +38,14 @@ public class StaticMethodCallNode implements ExpressionNode { asList(value), ObjectValues.BOXED_BOOLEAN); } + + public static ExpressionNode unboxBoolean(ExpressionNode value) { + return staticMethodCall( + InternalCouscousValue.REF, + "unboxBoolean", + asList(value), + BooleanValue.REF); + } public static StaticMethodCallNode staticMethodCall( String className, 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 99d0268..a47c4e9 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -168,8 +168,12 @@ public class JavaReader { ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression); if (isIntegerBox(targetType, couscousExpression)) { return StaticMethodCallNode.boxInt(couscousExpression); + } else if (isIntegerUnbox(targetType, couscousExpression)) { + return StaticMethodCallNode.unboxInt(couscousExpression); } else if (isBooleanBox(targetType, couscousExpression)) { return StaticMethodCallNode.boxBoolean(couscousExpression); + } else if (isBooleanUnbox(targetType, couscousExpression)) { + return StaticMethodCallNode.unboxBoolean(couscousExpression); } else { return couscousExpression; } @@ -180,11 +184,21 @@ public class JavaReader { !targetType.equals(IntegerValue.REF); } + private static boolean isIntegerUnbox(TypeName targetType, ExpressionNode expression) { + return !expression.getType().equals(IntegerValue.REF) && + targetType.equals(IntegerValue.REF); + } + private static boolean isBooleanBox(TypeName targetType, ExpressionNode expression) { return expression.getType().equals(BooleanValue.REF) && !targetType.equals(BooleanValue.REF); } + private static boolean isBooleanUnbox(TypeName targetType, ExpressionNode expression) { + return !expression.getType().equals(BooleanValue.REF) && + targetType.equals(BooleanValue.REF); + } + private static ExpressionNode readExpressionWithoutBoxing(Expression expression) { switch (expression.getNodeType()) { case ASTNode.BOOLEAN_LITERAL: 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 cc95f0f..b8309b3 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 @@ -35,9 +35,11 @@ import static org.zwobble.couscous.ast.FieldDeclarationNode.field; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.MethodCallNode.not; +import static org.zwobble.couscous.ast.StaticMethodCallNode.boxBoolean; import static org.zwobble.couscous.ast.StaticMethodCallNode.boxInt; import static org.zwobble.couscous.ast.StaticMethodCallNode.same; import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall; +import static org.zwobble.couscous.ast.StaticMethodCallNode.unboxInt; import static org.zwobble.couscous.ast.TernaryConditionalNode.ternaryConditional; import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; @@ -250,7 +252,7 @@ public class JavaReaderTests { } @Test - public void integersAreBoxedIfAssignedToObjectVariable() { + public void valuesOfAssignmentsAreBoxedIfNecessary() { ClassNode classNode = readClass( "private Object value;" + "public Object getValue() {" + @@ -283,19 +285,45 @@ public class JavaReaderTests { } @Test - public void integersAreBoxedIfDeclaredAsObjectVariable() { + public void initialValueOfLocalVariableDeclarationsAreBoxedIfNecessary() { List statements = readStatements("Object x = 4;"); LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); - assertEquals(StaticMethodCallNode.boxInt(literal(4)), declaration.getInitialValue()); + assertEquals(boxInt(literal(4)), declaration.getInitialValue()); } @Test - public void booleansAreBoxedIfDeclaredAsObjectVariable() { + public void integersAreBoxedWhenTargetTypeIsObject() { + List statements = readStatements("Object x = 4;"); + + LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); + assertEquals(boxInt(literal(4)), declaration.getInitialValue()); + } + + @Test + public void booleansAreBoxedWhenTargetTypeIsObject() { List statements = readStatements("Object x = true;"); LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); - assertEquals(StaticMethodCallNode.boxBoolean(literal(true)), declaration.getInitialValue()); + assertEquals(boxBoolean(literal(true)), declaration.getInitialValue()); + } + + @Test + public void integersAreUnboxedIfTargetTypeIsPrimitive() { + List statements = readStatements("Integer x = 4; int y = x;"); + + LocalVariableDeclarationNode boxedDeclaration = (LocalVariableDeclarationNode) statements.get(0); + LocalVariableDeclarationNode unboxedDeclaration = (LocalVariableDeclarationNode) statements.get(1); + assertEquals(unboxInt(reference(boxedDeclaration)), unboxedDeclaration.getInitialValue()); + } + + @Test + public void booleansAreUnboxedIfTargetTypeIsPrimitive() { + List statements = readStatements("Boolean x = false; boolean y = x;"); + + LocalVariableDeclarationNode boxedDeclaration = (LocalVariableDeclarationNode) statements.get(0); + LocalVariableDeclarationNode unboxedDeclaration = (LocalVariableDeclarationNode) statements.get(1); + assertEquals(StaticMethodCallNode.unboxBoolean(reference(boxedDeclaration)), unboxedDeclaration.getInitialValue()); } @Test -- cgit v1.2.3