diff options
Diffstat (limited to 'src')
16 files changed, 181 insertions, 135 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java b/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java index 0f1ab4f..c483bcd 100644 --- a/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java @@ -56,6 +56,11 @@ public interface ExpressionNode extends Node { public T visit(FieldAccessNode fieldAccess) { return visitor.visit(fieldAccess); } + + @Override + public T visit(TypeCoercionNode typeCoercion) { + return visitor.visit(typeCoercion); + } }); } diff --git a/src/main/java/org/zwobble/couscous/ast/Node.java b/src/main/java/org/zwobble/couscous/ast/Node.java index 7c4d347..c9eed67 100644 --- a/src/main/java/org/zwobble/couscous/ast/Node.java +++ b/src/main/java/org/zwobble/couscous/ast/Node.java @@ -61,6 +61,12 @@ public interface Node { } @Override + public Void visit(TypeCoercionNode typeCoercion) { + visitor.visit(typeCoercion); + return null; + } + + @Override public Void visit(ReturnNode returnNode) { visitor.visit(returnNode); return null; diff --git a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java index ccb9854..7c3b90b 100644 --- a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java @@ -10,6 +10,7 @@ import org.zwobble.couscous.values.InternalCouscousValue; import org.zwobble.couscous.values.ObjectValues; import static java.util.Arrays.asList; +import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.util.ExtraLists.eagerMap; public class StaticMethodCallNode implements ExpressionNode { @@ -18,35 +19,19 @@ public class StaticMethodCallNode implements ExpressionNode { } public static ExpressionNode boxInt(ExpressionNode value) { - return staticMethodCall( - InternalCouscousValue.REF, - "boxInt", - asList(value), - ObjectValues.BOXED_INT); + return typeCoercion(value, ObjectValues.BOXED_INT); } public static ExpressionNode unboxInt(ExpressionNode value) { - return staticMethodCall( - InternalCouscousValue.REF, - "unboxInt", - asList(value), - IntegerValue.REF); + return typeCoercion(value, IntegerValue.REF); } public static ExpressionNode boxBoolean(ExpressionNode value) { - return staticMethodCall( - InternalCouscousValue.REF, - "boxBoolean", - asList(value), - ObjectValues.BOXED_BOOLEAN); + return typeCoercion(value, ObjectValues.BOXED_BOOLEAN); } public static ExpressionNode unboxBoolean(ExpressionNode value) { - return staticMethodCall( - InternalCouscousValue.REF, - "unboxBoolean", - asList(value), - BooleanValue.REF); + return typeCoercion(value, BooleanValue.REF); } public static StaticMethodCallNode staticMethodCall( diff --git a/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java b/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java new file mode 100644 index 0000000..2c7b68e --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java @@ -0,0 +1,87 @@ +package org.zwobble.couscous.ast; + +import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.values.BooleanValue; +import org.zwobble.couscous.values.IntegerValue; + +import java.util.function.Function; + +public class TypeCoercionNode implements ExpressionNode { + public static TypeCoercionNode typeCoercion(ExpressionNode expression, TypeName type) { + return new TypeCoercionNode(expression, type); + } + + private final ExpressionNode expression; + private final TypeName type; + + private TypeCoercionNode(ExpressionNode expression, TypeName type) { + this.expression = expression; + this.type = type; + } + + public ExpressionNode getExpression() { + return expression; + } + + @Override + public TypeName getType() { + return type; + } + + public boolean isIntegerBox() { + return expression.getType().equals(IntegerValue.REF) && + !type.equals(IntegerValue.REF); + } + + public boolean isIntegerUnbox() { + return !expression.getType().equals(IntegerValue.REF) && + type.equals(IntegerValue.REF); + } + + public boolean isBooleanBox() { + return expression.getType().equals(BooleanValue.REF) && + !type.equals(BooleanValue.REF); + } + + public boolean isBooleanUnbox() { + return !expression.getType().equals(BooleanValue.REF) && + type.equals(BooleanValue.REF); + } + + @Override + public <T> T accept(ExpressionNodeMapper<T> visitor) { + return visitor.visit(this); + } + + @Override + public ExpressionNode replaceExpressions(Function<ExpressionNode, ExpressionNode> replace) { + return new TypeCoercionNode(replace.apply(expression), type); + } + + @Override + public String toString() { + return "TypeCoercionNode(" + + "expression=" + expression + + ", type=" + type + + ')'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TypeCoercionNode that = (TypeCoercionNode) o; + + if (!expression.equals(that.expression)) return false; + return type.equals(that.type); + + } + + @Override + public int hashCode() { + int result = expression.hashCode(); + result = 31 * result + type.hashCode(); + return result; + } +} diff --git a/src/main/java/org/zwobble/couscous/ast/structure/NodeStructure.java b/src/main/java/org/zwobble/couscous/ast/structure/NodeStructure.java index 47ba9b6..8b65f35 100644 --- a/src/main/java/org/zwobble/couscous/ast/structure/NodeStructure.java +++ b/src/main/java/org/zwobble/couscous/ast/structure/NodeStructure.java @@ -80,6 +80,11 @@ public class NodeStructure { } @Override + public Stream<? extends Node> visit(TypeCoercionNode typeCoercion) { + return Stream.of(typeCoercion.getExpression()); + } + + @Override public Stream<Node> visit(ReturnNode returnNode) { return Stream.of(returnNode.getValue()); } diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/ExpressionNodeMapper.java b/src/main/java/org/zwobble/couscous/ast/visitors/ExpressionNodeMapper.java index c1c3e88..87b8598 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/ExpressionNodeMapper.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/ExpressionNodeMapper.java @@ -1,14 +1,6 @@ package org.zwobble.couscous.ast.visitors; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; public interface ExpressionNodeMapper<T> { T visit(LiteralNode literal); @@ -20,4 +12,5 @@ public interface ExpressionNodeMapper<T> { T visit(StaticMethodCallNode staticMethodCall); T visit(ConstructorCallNode call); T visit(FieldAccessNode fieldAccess); + T visit(TypeCoercionNode typeCoercion); } diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapper.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapper.java index d38d7fa..4267c75 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapper.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapper.java @@ -12,6 +12,7 @@ public interface NodeMapper<T> { T visit(StaticMethodCallNode staticMethodCall); T visit(ConstructorCallNode call); T visit(FieldAccessNode fieldAccess); + T visit(TypeCoercionNode typeCoercion); T visit(ReturnNode returnNode); T visit(ExpressionStatementNode expressionStatement); diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapperWithDefault.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapperWithDefault.java index e4203e0..09cfcd3 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapperWithDefault.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeMapperWithDefault.java @@ -55,6 +55,11 @@ public class NodeMapperWithDefault<T> implements NodeMapper<T> { } @Override + public T visit(TypeCoercionNode typeCoercion) { + return defaultValue; + } + + @Override public T visit(ReturnNode returnNode) { return defaultValue; } diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java index 75e6da5..9f6be92 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java @@ -12,6 +12,7 @@ public interface NodeVisitor { void visit(StaticMethodCallNode staticMethodCall); void visit(ConstructorCallNode call); void visit(FieldAccessNode fieldAccess); + void visit(TypeCoercionNode typeCoercion); void visit(ReturnNode returnNode); void visit(ExpressionStatementNode expressionStatement); diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java index 913b1b7..ada7dea 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java @@ -261,6 +261,22 @@ public class PythonCodeGenerator { public PythonExpressionNode visit(FieldAccessNode fieldAccess) { return pythonAttributeAccess(generateExpression(fieldAccess.getLeft()), fieldAccess.getFieldName()); } + + @Override + public PythonExpressionNode visit(TypeCoercionNode typeCoercion) { + PythonExpressionNode value = generateExpression(typeCoercion.getExpression()); + if (typeCoercion.isIntegerBox()) { + return internalMethod("boxInt", asList(value)); + } else if (typeCoercion.isIntegerUnbox()) { + return internalMethod("unboxInt", asList(value)); + } else { + return value; + } + } + + private PythonExpressionNode internalMethod(String name, List<PythonExpressionNode> arguments) { + return pythonCall(pythonAttributeAccess(pythonVariableReference("_couscous"), name), arguments); + } } private static boolean isPrimitive(ExpressionNode value) { diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java index 6c49d4e..d9a55e3 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java @@ -30,7 +30,7 @@ public class JavaExpressionMethodReferenceReader { return lambda( formalArguments, - ImmutableList.of(returns(JavaExpressionReader.handleBoxing( + ImmutableList.of(returns(JavaExpressionReader.coerceExpression( typeOf(functionalInterfaceMethod.getReturnType()), generateValue(scope, expression, formalArguments))))); } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java index 367a34f..0e910a1 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -14,6 +14,7 @@ import static java.util.Arrays.asList; import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.not; +import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator; import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; import static org.zwobble.couscous.util.ExtraLists.concat; @@ -29,20 +30,14 @@ public class JavaExpressionReader { ExpressionNode readExpression(TypeName targetType, Expression expression) { ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression); - return handleBoxing(targetType, couscousExpression); + return coerceExpression(targetType, couscousExpression); } - static ExpressionNode handleBoxing(TypeName targetType, ExpressionNode couscousExpression) { - 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 { + static ExpressionNode coerceExpression(TypeName targetType, ExpressionNode couscousExpression) { + if (targetType.equals(couscousExpression.getType())) { return couscousExpression; + } else { + return typeCoercion(couscousExpression, targetType); } } @@ -56,26 +51,6 @@ public class JavaExpressionReader { } } - private static boolean isIntegerBox(TypeName targetType, ExpressionNode expression) { - return expression.getType().equals(IntegerValue.REF) && - !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); - } - ExpressionNode readExpressionWithoutBoxing(Expression expression) { switch (expression.getNodeType()) { case ASTNode.BOOLEAN_LITERAL: @@ -308,7 +283,7 @@ public class JavaExpressionReader { Operator operator = readOperator(expression.getOperator()); return AssignmentNode.assign( left, - handleBoxing( + coerceExpression( left.getType(), readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide()))); } diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java index 3e01f36..bee536a 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java @@ -1,23 +1,12 @@ package org.zwobble.couscous.interpreter; -import java.util.List; -import java.util.stream.Collectors; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ExpressionNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.visitors.AssignableExpressionNodeVisitor; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; -import org.zwobble.couscous.interpreter.values.BooleanInterpreterValue; -import org.zwobble.couscous.interpreter.values.ConcreteType; -import org.zwobble.couscous.interpreter.values.InterpreterValue; -import org.zwobble.couscous.interpreter.values.InterpreterValues; +import org.zwobble.couscous.interpreter.values.*; + +import java.util.List; +import java.util.stream.Collectors; public class Evaluator implements ExpressionNodeMapper<InterpreterValue> { public static InterpreterValue eval(Environment environment, ExpressionNode expression) { @@ -107,7 +96,21 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> { InterpreterValue left = eval(fieldAccess.getLeft()); return left.getField(fieldAccess.getFieldName()); } - + + @Override + public InterpreterValue visit(TypeCoercionNode typeCoercion) { + // TODO: check that the type coercion is valid + // TODO: boxing booleans + InterpreterValue value = eval(typeCoercion.getExpression()); + if (typeCoercion.isIntegerBox()) { + return ((IntegerInterpreterValue)value).box(); + } else if (typeCoercion.isIntegerUnbox()) { + return value.getField("value"); + } else { + return value; + } + } + private List<InterpreterValue> evalArguments(List<? extends ExpressionNode> arguments) { return arguments.stream() .map(argument -> eval(argument)) diff --git a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java index 3e10586..2c8dfeb 100644 --- a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java +++ b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.tests; +import org.junit.Test; import org.zwobble.couscous.CouscousCompiler; import org.zwobble.couscous.ast.TypeName; import org.zwobble.couscous.backends.python.PythonBackend; @@ -8,13 +9,12 @@ import org.zwobble.couscous.tests.backends.python.PythonMethodRunner; import org.zwobble.couscous.values.PrimitiveValue; import java.io.IOException; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively; -import static org.zwobble.couscous.values.PrimitiveValues.value; public class JavaToPythonTests extends CompilerTests { protected PrimitiveValue execProgram( diff --git a/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java b/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java index b9ca169..4366ac4 100644 --- a/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java +++ b/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java @@ -57,6 +57,7 @@ public class ValueObjectTests { {StaticMethodCallNode.class}, {TernaryConditionalNode.class}, {ThisReferenceNode.class}, + {TypeCoercionNode.class}, {TypeName.class}, {VariableDeclaration.class}, {VariableReferenceNode.class}, 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 0e929d8..2e61fe0 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 @@ -1,6 +1,5 @@ package org.zwobble.couscous.tests.frontends.java; -import org.junit.Ignore; import org.junit.Test; import org.zwobble.couscous.ast.*; import org.zwobble.couscous.frontends.java.JavaReader; @@ -33,6 +32,7 @@ import static org.zwobble.couscous.ast.ReturnNode.returns; import static org.zwobble.couscous.ast.StaticMethodCallNode.*; import static org.zwobble.couscous.ast.TernaryConditionalNode.ternaryConditional; import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference; +import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; import static org.zwobble.couscous.ast.WhileNode.whileLoop; import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively; @@ -40,7 +40,7 @@ import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively; public class JavaReaderTests { @Test public void canReadLiterals() { - assertEquals(literal("hello"), readObjectExpression("\"hello\"")); + assertEquals(literal("hello"), readExpression("String", "\"hello\"")); assertEquals(literal(true), readBooleanExpression("true")); assertEquals(literal(false), readBooleanExpression("false")); assertEquals(literal(42), readIntExpression("42")); @@ -51,7 +51,7 @@ public class JavaReaderTests { public void canReadThisReference() { assertEquals( thisReference(TypeName.of("com.example.Example")), - readExpressionInInstanceMethod("this")); + readExpressionInInstanceMethod("com.example.Example", "this")); } @Test @@ -153,7 +153,7 @@ public class JavaReaderTests { public void canReadConstructorCalls() { assertEquals( constructorCall(TypeName.of("java.lang.String"), asList(literal("_"))), - readObjectExpression("new String(\"_\")")); + readExpression("String", "new String(\"_\")")); } @Test @@ -207,10 +207,11 @@ public class JavaReaderTests { @Test public void argumentIsBoxedIfNecessary() { - StaticMethodCallNode expression = (StaticMethodCallNode) readObjectExpression( + StaticMethodCallNode expression = (StaticMethodCallNode) readExpression( + "String", "java.util.Objects.toString(42)"); assertEquals( - boxInt(literal(42)), + typeCoercion(literal(42), ObjectValues.OBJECT), expression.getArguments().get(0)); } @@ -286,14 +287,14 @@ public class JavaReaderTests { public void equalityOperatorDoesNotUnboxIfBothOperandsAreBoxed() { assertEquals( same( - constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))), - constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2)))), + typeCoercion(constructorCall(ObjectValues.BOXED_INT, asList(literal(1))), ObjectValues.OBJECT), + typeCoercion(constructorCall(ObjectValues.BOXED_INT, asList(literal(2))), ObjectValues.OBJECT)), readBooleanExpression("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))))), + typeCoercion(constructorCall(ObjectValues.BOXED_INT, asList(literal(1))), ObjectValues.OBJECT), + typeCoercion(constructorCall(ObjectValues.BOXED_INT, asList(literal(2))), ObjectValues.OBJECT))), readBooleanExpression("new Integer(1) != new Integer(2)")); } @@ -333,7 +334,7 @@ public class JavaReaderTests { } @Test - public void valuesOfAssignmentsAreBoxedIfNecessary() { + public void valuesOfAssignmentsAreTypeCoercedIfNecessary() { ClassNode classNode = readClass( "private Object value;" + "public Object getValue() {" + @@ -347,7 +348,7 @@ public class JavaReaderTests { thisReference(TypeName.of("com.example.Example")), "value", ObjectValues.OBJECT), - boxInt(literal(4))), + typeCoercion(literal(4), ObjectValues.OBJECT)), returnNode.getValue()); } @@ -366,45 +367,11 @@ public class JavaReaderTests { } @Test - public void initialValueOfLocalVariableDeclarationsAreBoxedIfNecessary() { + public void initialValueOfLocalVariableDeclarationsAreTypeCoercedIfNecessary() { List<StatementNode> statements = readStatements("Object x = 4;"); LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); - assertEquals(boxInt(literal(4)), declaration.getInitialValue()); - } - - @Test - public void integersAreBoxedWhenTargetTypeIsObject() { - List<StatementNode> statements = readStatements("Object x = 4;"); - - LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); - assertEquals(boxInt(literal(4)), declaration.getInitialValue()); - } - - @Test - public void booleansAreBoxedWhenTargetTypeIsObject() { - List<StatementNode> statements = readStatements("Object x = true;"); - - LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); - assertEquals(boxBoolean(literal(true)), declaration.getInitialValue()); - } - - @Test - public void integersAreUnboxedIfTargetTypeIsPrimitive() { - List<StatementNode> 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<StatementNode> 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()); + assertEquals(typeCoercion(literal(4), ObjectValues.OBJECT), declaration.getInitialValue()); } @Test @@ -621,9 +588,9 @@ public class JavaReaderTests { method.getBody()); } - private ExpressionNode readExpressionInInstanceMethod(String expressionSource) { + private ExpressionNode readExpressionInInstanceMethod(String returnType, String expressionSource) { String javaClass = - "public Object main() {" + + "public " + returnType + " main() {" + " return " + expressionSource + ";" + "}"; @@ -632,10 +599,6 @@ public class JavaReaderTests { return returnStatement.getValue(); } - private ExpressionNode readObjectExpression(String expressionSource) { - return readExpression("Object", expressionSource); - } - private ExpressionNode readBooleanExpression(String expressionSource) { return readExpression("boolean", expressionSource); } |
