From cdf51cdb9b3f8cef5896315496f348d9f7220903 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 4 Oct 2015 20:57:00 +0100 Subject: Add separate notion of VariableDeclaration --- .../org/zwobble/couscous/ast/FormalArgumentNode.java | 10 ++++++---- .../couscous/ast/LocalVariableDeclarationNode.java | 14 +++++++++++--- .../org/zwobble/couscous/ast/VariableDeclaration.java | 12 ++++++++++++ .../java/org/zwobble/couscous/ast/VariableNode.java | 5 +---- .../zwobble/couscous/ast/VariableReferenceNode.java | 2 +- .../org/zwobble/couscous/interpreter/Environment.java | 7 ++++--- .../couscous/interpreter/StackFrameBuilder.java | 9 +++++---- .../couscous/tests/interpreter/EvaluatorTests.java | 5 +++-- .../couscous/tests/interpreter/InterpreterTests.java | 19 ++++++++++--------- 9 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java index 947a015..cd2cb86 100644 --- a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java +++ b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java @@ -4,9 +4,11 @@ import org.zwobble.couscous.values.TypeReference; import lombok.Value; -@Value +@Value(staticConstructor="formalArg") public class FormalArgumentNode implements VariableNode { - int id; - TypeReference type; - String name; + VariableDeclaration declaration; + + public TypeReference getType() { + return declaration.getType(); + } } diff --git a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java index 880a7fd..cf6c5f0 100644 --- a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java +++ b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java @@ -3,13 +3,21 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.StatementNodeVisitor; import org.zwobble.couscous.values.TypeReference; +import static org.zwobble.couscous.ast.VariableDeclaration.var; + import lombok.Value; @Value(staticConstructor="localVariableDeclaration") public class LocalVariableDeclarationNode implements VariableNode, StatementNode { - int id; - TypeReference type; - String name; + public static LocalVariableDeclarationNode localVariableDeclaration( + int id, + String name, + TypeReference type, + ExpressionNode initialValue) { + return localVariableDeclaration(var(id, name, type), initialValue); + } + + VariableDeclaration declaration; ExpressionNode initialValue; @Override diff --git a/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java b/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java new file mode 100644 index 0000000..3a60412 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java @@ -0,0 +1,12 @@ +package org.zwobble.couscous.ast; + +import org.zwobble.couscous.values.TypeReference; + +import lombok.Value; + +@Value(staticConstructor="var") +public class VariableDeclaration { + int id; + String name; + TypeReference type; +} diff --git a/src/main/java/org/zwobble/couscous/ast/VariableNode.java b/src/main/java/org/zwobble/couscous/ast/VariableNode.java index acfa29b..c526db1 100644 --- a/src/main/java/org/zwobble/couscous/ast/VariableNode.java +++ b/src/main/java/org/zwobble/couscous/ast/VariableNode.java @@ -1,8 +1,5 @@ package org.zwobble.couscous.ast; -import org.zwobble.couscous.values.TypeReference; - public interface VariableNode { - int getId(); - TypeReference getType(); + VariableDeclaration getDeclaration(); } diff --git a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java index 536a7c3..2410549 100644 --- a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java +++ b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java @@ -7,7 +7,7 @@ import lombok.Value; @Value public class VariableReferenceNode implements ExpressionNode { public static VariableReferenceNode reference(VariableNode variable) { - return new VariableReferenceNode(variable.getId()); + return new VariableReferenceNode(variable.getDeclaration().getId()); } int referentId; diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java index 21cfe04..6838ba5 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.Optional; import org.zwobble.couscous.Project; +import org.zwobble.couscous.ast.VariableDeclaration; import org.zwobble.couscous.ast.VariableNode; import org.zwobble.couscous.values.ConcreteType; import org.zwobble.couscous.values.InterpreterValue; @@ -20,7 +21,7 @@ public class Environment { private final Project project; private final Map stackFrame; - public Environment(Project project, Map> stackFrame) { + public Environment(Project project, Map> stackFrame) { this.project = project; this.stackFrame = stackFrame.entrySet() .stream() @@ -42,7 +43,7 @@ public class Environment { } public void put(VariableNode variable, InterpreterValue value) { - put(variable.getId(), value); + put(variable.getDeclaration().getId(), value); } public ConcreteType findClass(String className) { @@ -50,7 +51,7 @@ public class Environment { return project.findClass(className); } - public Environment withStackFrame(Map> stackFrame) { + public Environment withStackFrame(Map> stackFrame) { return new Environment(project, stackFrame); } diff --git a/src/main/java/org/zwobble/couscous/interpreter/StackFrameBuilder.java b/src/main/java/org/zwobble/couscous/interpreter/StackFrameBuilder.java index 658bf42..3b163f3 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/StackFrameBuilder.java +++ b/src/main/java/org/zwobble/couscous/interpreter/StackFrameBuilder.java @@ -2,6 +2,7 @@ package org.zwobble.couscous.interpreter; import java.util.Map; +import org.zwobble.couscous.ast.VariableDeclaration; import org.zwobble.couscous.ast.VariableNode; import org.zwobble.couscous.values.InterpreterValue; @@ -10,20 +11,20 @@ import com.google.common.collect.ImmutableMap; import java.util.Optional; public class StackFrameBuilder { - private final ImmutableMap.Builder> variables + private final ImmutableMap.Builder> variables = ImmutableMap.builder(); public StackFrameBuilder declare(VariableNode variable, InterpreterValue value) { - variables.put(variable, Optional.of(value)); + variables.put(variable.getDeclaration(), Optional.of(value)); return this; } public StackFrameBuilder declare(VariableNode variable) { - variables.put(variable, Optional.empty()); + variables.put(variable.getDeclaration(), Optional.empty()); return this; } - public Map> build() { + public Map> build() { return variables.build(); } } 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 ff74d1b..9575843 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java @@ -4,7 +4,6 @@ import org.junit.Test; import org.zwobble.couscous.JavaProject; import org.zwobble.couscous.MapBackedProject; import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.FormalArgumentNode; import org.zwobble.couscous.ast.MethodNode; import org.zwobble.couscous.ast.ReturnNode; import org.zwobble.couscous.ast.TernaryConditionalNode; @@ -22,9 +21,11 @@ import com.google.common.collect.ImmutableMap; import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.ast.Assignment.assign; +import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall; +import static org.zwobble.couscous.ast.VariableDeclaration.var; import static org.zwobble.couscous.interpreter.Evaluator.eval; import static org.zwobble.couscous.tests.util.ExtraAsserts.assertThrows; @@ -33,7 +34,7 @@ import lombok.val; public class EvaluatorTests { @Test public void valueOfAssignmentExpressionIsNewValue() { - val arg = new FormalArgumentNode(42, StringValue.REF, "x"); + val arg = formalArg(var(42, "x", StringValue.REF)); val environment = new Environment( new MapBackedProject(ImmutableMap.of()), new StackFrameBuilder().declare(arg, new StringValue("[initial value]")).build()); diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java index 6fe799f..d0c8976 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java @@ -5,7 +5,6 @@ import org.zwobble.couscous.MapBackedProject; import org.zwobble.couscous.ast.Assignment; import org.zwobble.couscous.ast.ClassNode; import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.FormalArgumentNode; import org.zwobble.couscous.ast.LiteralNode; import org.zwobble.couscous.ast.MethodNode; import org.zwobble.couscous.ast.ReturnNode; @@ -23,9 +22,11 @@ import com.google.common.collect.ImmutableMap; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration; import static org.zwobble.couscous.ast.MethodNode.staticMethod; +import static org.zwobble.couscous.ast.VariableDeclaration.var; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; import static org.zwobble.couscous.tests.util.ExtraAsserts.assertThrows; import static org.zwobble.couscous.values.UnitValue.UNIT; @@ -52,7 +53,7 @@ public class InterpreterTests { @Test public void canPassValueToMethod() { - val arg = new FormalArgumentNode(42, StringValue.REF, "x"); + val arg = formalArg(var(42, "x", StringValue.REF)); val method = staticMethod("hello") .argument(arg) .statement(new ReturnNode(reference(arg))); @@ -73,7 +74,7 @@ public class InterpreterTests { @Test public void canReassignValueToArgument() { - val arg = new FormalArgumentNode(42, StringValue.REF, "x"); + val arg = formalArg(var(42, "x", StringValue.REF)); val method = staticMethod("hello") .argument(arg) .statement(new ExpressionStatementNode(new Assignment(reference(arg), LiteralNode.literal("[updated value]")))) @@ -85,7 +86,7 @@ public class InterpreterTests { @Test public void errorIfTryingToAssignValueOfWrongTypeToVariable() { - val arg = new FormalArgumentNode(42, StringValue.REF, "x"); + val arg = formalArg(var(42, "x", StringValue.REF)); val method = staticMethod("hello") .argument(arg) .statement(new ExpressionStatementNode(new Assignment(reference(arg), literal(0)))); @@ -99,7 +100,7 @@ public class InterpreterTests { @Test public void canDeclareVariable() { val localVariableDeclaration = localVariableDeclaration( - 42, StringValue.REF, "x", LiteralNode.literal("[initial value]")); + 42, "x", StringValue.REF, LiteralNode.literal("[initial value]")); val method = staticMethod("hello") .statement(localVariableDeclaration) .statement(new ReturnNode(reference(localVariableDeclaration))); @@ -111,7 +112,7 @@ public class InterpreterTests { @Test public void canDeclareVariableAndThenAssignValues() { val localVariableDeclaration = localVariableDeclaration( - 42, StringValue.REF, "x", LiteralNode.literal("[initial value]")); + 42, "x", StringValue.REF, LiteralNode.literal("[initial value]")); val method = staticMethod("hello") .statement(localVariableDeclaration) .statement(new ExpressionStatementNode(new Assignment(reference(localVariableDeclaration), LiteralNode.literal("[updated value]")))) @@ -124,7 +125,7 @@ public class InterpreterTests { @Test public void errorIfTryingToAssignToVariableNotInScope() { val localVariableDeclaration = localVariableDeclaration( - 42, StringValue.REF, "x", literal("")); + 42, "x", StringValue.REF, literal("")); val method = staticMethod("hello") .statement(new ExpressionStatementNode(new Assignment(reference(localVariableDeclaration), LiteralNode.literal("[updated value]")))); @@ -137,7 +138,7 @@ public class InterpreterTests { @Test public void errorIfTryingToGetValueOfVariableNotInScope() { val localVariableDeclaration = localVariableDeclaration( - 42, StringValue.REF, "x", literal("")); + 42, "x", StringValue.REF, literal("")); val method = staticMethod("hello") .statement(new ReturnNode(reference(localVariableDeclaration))); @@ -150,7 +151,7 @@ public class InterpreterTests { @Test public void errorIfTryingToGetValueOfUnboundVariable() { val localVariableDeclaration = localVariableDeclaration( - 42, StringValue.REF, "x", literal("")); + 42, "x", StringValue.REF, literal("")); val method = staticMethod("hello") .statement(new ReturnNode(reference(localVariableDeclaration))) .statement(localVariableDeclaration); -- cgit v1.2.3