diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-10-05 18:10:32 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-10-05 18:10:32 +0100 |
| commit | 27ffd2d94482ccdcd10acbb1111ce0a0ddae6c01 (patch) | |
| tree | 83104ba83bba3ccfd2dbf0bb1f0d9afc1ea076dd | |
| parent | 9e850b3a09ceebf6140e77982b45abab0c57ad6c (diff) | |
Add types to expression nodes
14 files changed, 99 insertions, 14 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java b/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java index 861e847..8989ef3 100644 --- a/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java +++ b/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.TypeReference; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; @@ -19,4 +20,9 @@ public class AssignmentNode implements ExpressionNode { public <T> T accept(ExpressionNodeVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return value.getType(); + } } diff --git a/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java b/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java index 097377a..bc27a99 100644 --- a/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ExpressionNode.java @@ -1,7 +1,9 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.TypeReference; public interface ExpressionNode { + TypeReference getType(); <T> T accept(ExpressionNodeVisitor<T> visitor); } diff --git a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java index 05a599c..2d77cd4 100644 --- a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java +++ b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java @@ -1,31 +1,36 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.BooleanValue; +import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.PrimitiveValue; +import org.zwobble.couscous.values.StringValue; +import org.zwobble.couscous.values.TypeReference; import static org.zwobble.couscous.values.PrimitiveValues.value; import lombok.Value; -@Value +@Value(staticConstructor="of") public class LiteralNode implements ExpressionNode { public static LiteralNode literal(PrimitiveValue value) { - return new LiteralNode(value); + return new LiteralNode(value, value.getType()); } public static LiteralNode literal(String value) { - return new LiteralNode(value(value)); + return new LiteralNode(value(value), StringValue.REF); } public static LiteralNode literal(int value) { - return new LiteralNode(value(value)); + return new LiteralNode(value(value), IntegerValue.REF); } public static LiteralNode literal(boolean value) { - return new LiteralNode(value(value)); + return new LiteralNode(value(value), BooleanValue.REF); } PrimitiveValue value; + TypeReference type; @Override public <T> T accept(ExpressionNodeVisitor<T> visitor) { diff --git a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java index 09058fc..f240971 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java @@ -3,8 +3,7 @@ package org.zwobble.couscous.ast; import java.util.List; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; - -import static java.util.Arrays.asList; +import org.zwobble.couscous.values.TypeReference; import lombok.Value; @@ -13,9 +12,14 @@ public class MethodCallNode implements ExpressionNode { ExpressionNode receiver; String methodName; List<ExpressionNode> arguments; + TypeReference type; - public static MethodCallNode methodCall(ExpressionNode receiver, String methodName, ExpressionNode... arguments) { - return new MethodCallNode(receiver, methodName, asList(arguments)); + public static MethodCallNode methodCall( + ExpressionNode receiver, + String methodName, + List<ExpressionNode> arguments, + TypeReference type) { + return new MethodCallNode(receiver, methodName, arguments, type); } @Override diff --git a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java index 4f1e9ff..0228514 100644 --- a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java @@ -3,6 +3,7 @@ package org.zwobble.couscous.ast; import java.util.List; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.TypeReference; import static java.util.Arrays.asList; @@ -26,4 +27,9 @@ public class StaticMethodCallNode implements ExpressionNode { public <T> T accept(ExpressionNodeVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java b/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java index 0386a32..8b30024 100644 --- a/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java +++ b/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.TypeReference; import lombok.Value; @@ -14,4 +15,9 @@ public class TernaryConditionalNode implements ExpressionNode { public <T> T accept(ExpressionNodeVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return ifTrue.getType(); + } } diff --git a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java index afd3918..5499d50 100644 --- a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java +++ b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import org.zwobble.couscous.values.TypeReference; import lombok.Value; @@ -20,4 +21,9 @@ public class VariableReferenceNode implements ExpressionNode { public int getReferentId() { return referent.getId(); } + + @Override + public TypeReference getType() { + return referent.getType(); + } } diff --git a/src/main/java/org/zwobble/couscous/values/BooleanValue.java b/src/main/java/org/zwobble/couscous/values/BooleanValue.java index e05c246..76f828e 100644 --- a/src/main/java/org/zwobble/couscous/values/BooleanValue.java +++ b/src/main/java/org/zwobble/couscous/values/BooleanValue.java @@ -1,11 +1,15 @@ package org.zwobble.couscous.values; +import static org.zwobble.couscous.values.TypeReference.typeRef; + import lombok.AccessLevel; import lombok.Getter; import lombok.Value; @Value public class BooleanValue implements PrimitiveValue { + public static final TypeReference REF = typeRef("java.lang.Boolean"); + @Getter(value = AccessLevel.NONE) boolean value; @@ -17,4 +21,9 @@ public class BooleanValue implements PrimitiveValue { public <T> T accept(PrimitiveValueVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return REF; + } } diff --git a/src/main/java/org/zwobble/couscous/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/values/IntegerValue.java index 71c7a41..5c272a0 100644 --- a/src/main/java/org/zwobble/couscous/values/IntegerValue.java +++ b/src/main/java/org/zwobble/couscous/values/IntegerValue.java @@ -14,4 +14,9 @@ public class IntegerValue implements PrimitiveValue { public <T> T accept(PrimitiveValueVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return REF; + } } diff --git a/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java b/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java index 2cfe40a..56da066 100644 --- a/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java +++ b/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java @@ -2,4 +2,5 @@ package org.zwobble.couscous.values; public interface PrimitiveValue { <T> T accept(PrimitiveValueVisitor<T> visitor); + TypeReference getType(); } diff --git a/src/main/java/org/zwobble/couscous/values/StringValue.java b/src/main/java/org/zwobble/couscous/values/StringValue.java index 256d6d1..ba0b1b5 100644 --- a/src/main/java/org/zwobble/couscous/values/StringValue.java +++ b/src/main/java/org/zwobble/couscous/values/StringValue.java @@ -14,4 +14,9 @@ public class StringValue implements PrimitiveValue { public <T> T accept(PrimitiveValueVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return REF; + } } diff --git a/src/main/java/org/zwobble/couscous/values/UnitValue.java b/src/main/java/org/zwobble/couscous/values/UnitValue.java index 14bf327..b4f6974 100644 --- a/src/main/java/org/zwobble/couscous/values/UnitValue.java +++ b/src/main/java/org/zwobble/couscous/values/UnitValue.java @@ -1,6 +1,8 @@ package org.zwobble.couscous.values; public class UnitValue implements PrimitiveValue { + public static final TypeReference REF = TypeReference.typeRef("org.zwobble.couscous.runtime.Unit"); + static final UnitValue UNIT = new UnitValue(); private UnitValue() { @@ -10,4 +12,9 @@ public class UnitValue implements PrimitiveValue { public <T> T accept(PrimitiveValueVisitor<T> visitor) { return visitor.visit(this); } + + @Override + public TypeReference getType() { + return REF; + } } diff --git a/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java index 68e9761..c6b7ba2 100644 --- a/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java +++ b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java @@ -3,8 +3,10 @@ package org.zwobble.couscous.tests; import org.junit.Test; import org.zwobble.couscous.ast.ExpressionNode; import org.zwobble.couscous.ast.TernaryConditionalNode; +import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.PrimitiveValue; +import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.methodCall; @@ -35,7 +37,11 @@ public abstract class BackendEvalTests { @Test public void canCallMethodWithNoArgumentsOnBuiltin() { - val result = evalExpression(methodCall(literal("hello"), "length")); + val result = evalExpression(methodCall( + literal("hello"), + "length", + asList(), + IntegerValue.REF)); assertEquals(value(5), result); } 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 766cf3c..fab65ef 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java @@ -24,6 +24,7 @@ import org.zwobble.couscous.values.StringValue; import com.google.common.collect.ImmutableMap; +import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.ast.AssignmentNode.assign; import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; @@ -59,7 +60,11 @@ public class EvaluatorTests extends BackendEvalTests { @Test public void canCallMethodWithArgumentsOnBuiltin() { val result = eval(emptyEnvironment(), - methodCall(literal("hello"), "substring", literal(1), literal(4))); + methodCall( + literal("hello"), + "substring", + asList(literal(1), literal(4)), + StringValue.REF)); assertEquals(new StringInterpreterValue("ell"), result); } @@ -67,7 +72,11 @@ public class EvaluatorTests extends BackendEvalTests { public void errorIfMethodDoesNotExist() { val exception = assertThrows(NoSuchMethod.class, () -> eval(emptyEnvironment(), - methodCall(literal("hello"), "size"))); + methodCall( + literal("hello"), + "size", + asList(), + IntegerValue.REF))); assertEquals(new NoSuchMethod("size"), exception); } @@ -75,7 +84,11 @@ public class EvaluatorTests extends BackendEvalTests { public void errorIfWrongNumberOfArgumentsArePassed() { val exception = assertThrows(WrongNumberOfArguments.class, () -> eval(emptyEnvironment(), - methodCall(literal("hello"), "substring", literal(1)))); + methodCall( + literal("hello"), + "substring", + asList(literal(1)), + StringValue.REF))); assertEquals(new WrongNumberOfArguments(2, 1), exception); } @@ -83,7 +96,11 @@ public class EvaluatorTests extends BackendEvalTests { public void errorIfArgumentIsWrongType() { val exception = assertThrows(UnexpectedValueType.class, () -> eval(emptyEnvironment(), - methodCall(literal("hello"), "substring", literal(0), literal("")))); + methodCall( + literal("hello"), + "substring", + asList(literal(0), literal("")), + StringValue.REF))); assertEquals(new UnexpectedValueType(IntegerValue.REF, StringValue.REF), exception); } |
