From e1d8a9727e1a84ddfa5b38e8f8a433b7105bc6bd Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 10 Jan 2016 20:10:54 +0000 Subject: Implements casts in the interpreter --- .../zwobble/couscous/interpreter/Evaluator.java | 6 ++++- .../couscous/interpreter/InterpreterTypes.java | 2 +- .../zwobble/couscous/interpreter/InvalidCast.java | 22 ++++++++++++++++++ .../couscous/tests/interpreter/EvaluatorTests.java | 26 ++++++++++++++++++---- 4 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/interpreter/InvalidCast.java (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java index d90b78b..56ccca7 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java @@ -125,7 +125,11 @@ public class Evaluator implements ExpressionNodeMapper { @Override public InterpreterValue visit(CastNode cast) { - throw new UnsupportedOperationException(); + InterpreterValue value = eval(cast.getExpression()); + if (!InterpreterTypes.isSubType(cast.getType(), value.getType())) { + throw new InvalidCast(cast.getType(), value.getType().getName()); + } + return value; } private static boolean isIntegerBox(TypeCoercionNode typeCoercion) { diff --git a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java index 1e644c8..71f875d 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java +++ b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java @@ -16,7 +16,7 @@ public class InterpreterTypes { } } - private static boolean isSubType(TypeName superTypeName, ConcreteType subType) { + public static boolean isSubType(TypeName superTypeName, ConcreteType subType) { return superTypeName.equals(subType.getName()) || superTypeName.equals(ObjectValues.OBJECT) || diff --git a/src/main/java/org/zwobble/couscous/interpreter/InvalidCast.java b/src/main/java/org/zwobble/couscous/interpreter/InvalidCast.java new file mode 100644 index 0000000..1d89ad1 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/interpreter/InvalidCast.java @@ -0,0 +1,22 @@ +package org.zwobble.couscous.interpreter; + +import org.zwobble.couscous.ast.TypeName; + +public class InvalidCast extends RuntimeException { + private final TypeName expected; + private final TypeName actual; + + public InvalidCast(TypeName expected, TypeName actual) { + + this.expected = expected; + this.actual = actual; + } + + public TypeName getExpected() { + return expected; + } + + public TypeName getActual() { + return actual; + } +} diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java index d3c2a12..4d91cdb 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java @@ -1,8 +1,6 @@ package org.zwobble.couscous.tests.interpreter; -import java.util.List; -import java.util.Optional; - +import com.google.common.collect.ImmutableMap; import org.junit.Test; import org.zwobble.couscous.ast.ClassNode; import org.zwobble.couscous.ast.ExpressionNode; @@ -14,14 +12,17 @@ import org.zwobble.couscous.interpreter.values.InterpreterValue; import org.zwobble.couscous.interpreter.values.StringInterpreterValue; import org.zwobble.couscous.tests.BackendEvalTests; import org.zwobble.couscous.values.IntegerValue; +import org.zwobble.couscous.values.ObjectValues; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.StringValue; -import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Optional; import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.ast.AssignmentNode.assign; import static org.zwobble.couscous.ast.AssignmentNode.assignStatement; +import static org.zwobble.couscous.ast.CastNode.cast; import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess; import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; @@ -186,6 +187,23 @@ public class EvaluatorTests extends BackendEvalTests { assertEquals(new UnexpectedValueType(IntegerValue.REF, StringValue.REF), exception); } + + @Test + public void validCastPassesValueThrough() { + InterpreterValue value = eval( + emptyEnvironment(), + cast(literal("42"), ObjectValues.OBJECT)); + assertEquals(value("42"), value); + } + + @Test + public void errorIfCastIsNotValid() { + InvalidCast exception = assertThrows(InvalidCast.class, + () -> eval(emptyEnvironment(), + cast(literal(42), StringValue.REF))); + assertEquals(StringValue.REF, exception.getExpected()); + assertEquals(IntegerValue.REF, exception.getActual()); + } private static Environment emptyEnvironment() { return new Environment( -- cgit v1.2.3