From 4e031ada69e27d9aa518ef00ebf532328ba23e79 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 29 Sep 2015 20:32:35 +0100 Subject: Create separate evaluator tests --- .../java/org/zwobble/couscous/ast/Assignment.java | 6 ++++++ .../java/org/zwobble/couscous/ast/LiteralNode.java | 2 +- .../zwobble/couscous/interpreter/Environment.java | 3 ++- .../zwobble/couscous/interpreter/Evaluator.java | 6 +++++- .../zwobble/couscous/interpreter/Interpreter.java | 13 +++++------ .../couscous/tests/interpreter/EvaluatorTests.java | 25 ++++++++++++++++++++++ .../tests/interpreter/InterpreterTests.java | 15 ++----------- 7 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java diff --git a/src/main/java/org/zwobble/couscous/ast/Assignment.java b/src/main/java/org/zwobble/couscous/ast/Assignment.java index aa7f89b..d8bdaaf 100644 --- a/src/main/java/org/zwobble/couscous/ast/Assignment.java +++ b/src/main/java/org/zwobble/couscous/ast/Assignment.java @@ -2,10 +2,16 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor; +import static org.zwobble.couscous.ast.VariableReferenceNode.reference; + import lombok.Value; @Value public class Assignment implements ExpressionNode { + public static Assignment assign(VariableNode target, ExpressionNode value) { + return new Assignment(reference(target), value); + } + VariableReferenceNode target; ExpressionNode value; diff --git a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java index 38688d8..594187d 100644 --- a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java +++ b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java @@ -9,7 +9,7 @@ import lombok.Value; @Value public class LiteralNode implements ExpressionNode { - public static LiteralNode of(String value) { + public static LiteralNode literal(String value) { return new LiteralNode(new StringValue(value)); } diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java index ef91916..a3b3871 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.interpreter; +import java.util.HashMap; import java.util.Map; import org.zwobble.couscous.values.InterpreterValue; @@ -8,7 +9,7 @@ public class Environment { private Map stackFrame; public Environment(Map stackFrame) { - this.stackFrame = stackFrame; + this.stackFrame = new HashMap<>(stackFrame); } public InterpreterValue get(int referentId) { diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java index 02acbe3..863ccb0 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java @@ -10,9 +10,13 @@ import org.zwobble.couscous.values.InterpreterValue; import lombok.val; public class Evaluator implements ExpressionNodeVisitor { + public static InterpreterValue eval(Environment environment, ExpressionNode expression) { + return new Evaluator(environment).eval(expression); + } + private final Environment environment; - public Evaluator(Environment environment) { + private Evaluator(Environment environment) { this.environment = environment; } diff --git a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java index d68f4df..bc82fee 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java @@ -13,6 +13,7 @@ import org.zwobble.couscous.values.InterpreterValue; import static com.google.common.collect.Iterables.find; import static java.util.stream.Collectors.toMap; +import static org.zwobble.couscous.interpreter.Evaluator.eval; import static org.zwobble.couscous.values.UnitValue.UNIT; import lombok.val; @@ -31,7 +32,7 @@ public class Interpreter { val environment = buildEnvironment(method, arguments); for (val statement : method.getBody()) { - val result = statement.accept(new Executor(new Evaluator(environment))); + val result = statement.accept(new Executor(environment)); if (result.isPresent()) { return result.get(); } @@ -56,20 +57,20 @@ public class Interpreter { } private class Executor implements StatementNodeVisitor> { - private Evaluator evaluator; + private Environment environment; - public Executor(Evaluator evaluator) { - this.evaluator = evaluator; + public Executor(Environment environment) { + this.environment = environment; } @Override public Optional visit(ReturnNode returnNode) { - return Optional.of(evaluator.eval(returnNode.getValue())); + return Optional.of(eval(environment, returnNode.getValue())); } @Override public Optional visit(ExpressionStatementNode expressionStatement) { - evaluator.eval(expressionStatement.getExpression()); + eval(environment, expressionStatement.getExpression()); return Optional.empty(); } } diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java new file mode 100644 index 0000000..075d9b3 --- /dev/null +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java @@ -0,0 +1,25 @@ +package org.zwobble.couscous.tests.interpreter; + +import org.junit.Test; +import org.zwobble.couscous.ast.FormalArgumentNode; +import org.zwobble.couscous.interpreter.Environment; +import org.zwobble.couscous.values.StringValue; + +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.LiteralNode.literal; +import static org.zwobble.couscous.interpreter.Evaluator.eval; + +import lombok.val; + +public class EvaluatorTests { + @Test + public void valueOfAssignmentExpressionIsNewValue() { + val arg = new FormalArgumentNode(42, "x"); + val environment = new Environment(ImmutableMap.of(arg.getId(), new StringValue("[initial value]"))); + val result = eval(environment, assign(arg, literal("[updated value]"))); + assertEquals(new StringValue("[updated value]"), result); + } +} 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 d3bc21c..54abd8a 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java @@ -31,7 +31,7 @@ public class InterpreterTests { @Test public void canReturnLiteralValue() { val method = staticMethod("hello") - .statement(new ReturnNode(LiteralNode.of("hello, world!"))); + .statement(new ReturnNode(LiteralNode.literal("hello, world!"))); val result = runMethod(method); assertEquals(new StringValue("hello, world!"), result); @@ -63,24 +63,13 @@ public class InterpreterTests { val arg = new FormalArgumentNode(42, "x"); val method = staticMethod("hello") .argument(arg) - .statement(new ExpressionStatementNode(new Assignment(reference(arg), LiteralNode.of("[updated value]")))) + .statement(new ExpressionStatementNode(new Assignment(reference(arg), LiteralNode.literal("[updated value]")))) .statement(new ReturnNode(reference(arg))); val result = runMethod(method, new StringValue("[initial value]")); assertEquals(new StringValue("[updated value]"), result); } - @Test - public void valueOfAssignmentExpressionIsNewValue() { - val arg = new FormalArgumentNode(42, "x"); - val method = staticMethod("hello") - .argument(arg) - .statement(new ReturnNode(new Assignment(reference(arg), LiteralNode.of("[updated value]")))); - val result = runMethod(method, new StringValue("[initial value]")); - - assertEquals(new StringValue("[updated value]"), result); - } - @Test public void methodWithNoStatementsReturnsUnit() { val method = staticMethod("hello"); -- cgit v1.2.3