aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/JavaProject.java4
-rw-r--r--src/main/java/org/zwobble/couscous/ast/LiteralNode.java17
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java36
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java9
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Executor.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Interpreter.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java33
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/BooleanValue.java23
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java37
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/IntegerValue.java30
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java5
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java37
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java41
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StringValue.java34
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java29
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/UnitValue.java19
-rw-r--r--src/main/java/org/zwobble/couscous/values/BooleanValue.java20
-rw-r--r--src/main/java/org/zwobble/couscous/values/IntegerValue.java17
-rw-r--r--src/main/java/org/zwobble/couscous/values/PrimitiveValue.java5
-rw-r--r--src/main/java/org/zwobble/couscous/values/PrimitiveValueVisitor.java8
-rw-r--r--src/main/java/org/zwobble/couscous/values/PrimitiveValues.java17
-rw-r--r--src/main/java/org/zwobble/couscous/values/StringValue.java17
-rw-r--r--src/main/java/org/zwobble/couscous/values/UnitValue.java13
-rw-r--r--src/test/java/org/zwobble/couscous/tests/BackendTests.java12
-rw-r--r--src/test/java/org/zwobble/couscous/tests/MethodRunner.java4
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java12
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java25
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java35
28 files changed, 370 insertions, 177 deletions
diff --git a/src/main/java/org/zwobble/couscous/JavaProject.java b/src/main/java/org/zwobble/couscous/JavaProject.java
index a13399c..04ed53d 100644
--- a/src/main/java/org/zwobble/couscous/JavaProject.java
+++ b/src/main/java/org/zwobble/couscous/JavaProject.java
@@ -1,10 +1,10 @@
package org.zwobble.couscous;
-import org.zwobble.couscous.interpreter.values.IntegerValue;
+import org.zwobble.couscous.interpreter.values.IntegerInterpreterValue;
public class JavaProject {
public static MapBackedProject.Builder builder() {
return MapBackedProject.builder()
- .addClass(IntegerValue.TYPE);
+ .addClass(IntegerInterpreterValue.TYPE);
}
}
diff --git a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
index 6bc498a..05a599c 100644
--- a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
@@ -1,32 +1,31 @@
package org.zwobble.couscous.ast;
import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor;
-import org.zwobble.couscous.interpreter.values.BooleanValue;
-import org.zwobble.couscous.interpreter.values.IntegerValue;
-import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.interpreter.values.StringValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+
+import static org.zwobble.couscous.values.PrimitiveValues.value;
import lombok.Value;
@Value
public class LiteralNode implements ExpressionNode {
- public static LiteralNode literal(InterpreterValue value) {
+ public static LiteralNode literal(PrimitiveValue value) {
return new LiteralNode(value);
}
public static LiteralNode literal(String value) {
- return new LiteralNode(new StringValue(value));
+ return new LiteralNode(value(value));
}
public static LiteralNode literal(int value) {
- return new LiteralNode(new IntegerValue(value));
+ return new LiteralNode(value(value));
}
public static LiteralNode literal(boolean value) {
- return new LiteralNode(new BooleanValue(value));
+ return new LiteralNode(value(value));
}
- InterpreterValue value;
+ PrimitiveValue value;
@Override
public <T> T accept(ExpressionNodeVisitor<T> visitor) {
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 4c26a0a..eae713c 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
@@ -21,8 +21,11 @@ import org.zwobble.couscous.backends.python.ast.PythonExpressionNode;
import org.zwobble.couscous.backends.python.ast.PythonFunctionDefinitionNode;
import org.zwobble.couscous.backends.python.ast.PythonModuleNode;
import org.zwobble.couscous.backends.python.ast.PythonStatementNode;
-import org.zwobble.couscous.interpreter.values.IntegerValue;
-import org.zwobble.couscous.interpreter.values.StringValue;
+import org.zwobble.couscous.values.BooleanValue;
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValueVisitor;
+import org.zwobble.couscous.values.StringValue;
+import org.zwobble.couscous.values.UnitValue;
import static java.util.Arrays.asList;
import static org.zwobble.couscous.backends.python.ast.PythonClassNode.pythonClass;
@@ -81,14 +84,27 @@ public class PythonCodeGenerator {
private static class ExpressionGenerator implements ExpressionNodeVisitor<PythonExpressionNode> {
@Override
public PythonExpressionNode visit(LiteralNode literal) {
- // TODO: use visitor
- if (literal.getValue() instanceof IntegerValue) {
- return pythonIntegerLiteral(((IntegerValue)literal.getValue()).getValue());
- } else if (literal.getValue() instanceof StringValue) {
- return pythonStringLiteral(((StringValue)literal.getValue()).getValue());
- } else {
- throw new UnsupportedOperationException();
- }
+ return literal.getValue().accept(new PrimitiveValueVisitor<PythonExpressionNode>() {
+ @Override
+ public PythonExpressionNode visit(IntegerValue value) {
+ return pythonIntegerLiteral(value.getValue());
+ }
+
+ @Override
+ public PythonExpressionNode visit(StringValue value) {
+ return pythonStringLiteral(value.getValue());
+ }
+
+ @Override
+ public PythonExpressionNode visit(BooleanValue value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PythonExpressionNode visit(UnitValue unitValue) {
+ throw new UnsupportedOperationException();
+ }
+ });
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index 6b61b7f..9362698 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -11,8 +11,9 @@ import org.zwobble.couscous.ast.StaticMethodCallNode;
import org.zwobble.couscous.ast.TernaryConditionalNode;
import org.zwobble.couscous.ast.VariableReferenceNode;
import org.zwobble.couscous.ast.visitors.ExpressionNodeVisitor;
-import org.zwobble.couscous.interpreter.values.BooleanValue;
+import org.zwobble.couscous.interpreter.values.BooleanInterpreterValue;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
+import org.zwobble.couscous.interpreter.values.InterpreterValues;
import lombok.val;
@@ -33,7 +34,7 @@ public class Evaluator implements ExpressionNodeVisitor<InterpreterValue> {
@Override
public InterpreterValue visit(LiteralNode literal) {
- return literal.getValue();
+ return InterpreterValues.value(literal.getValue());
}
@Override
@@ -51,10 +52,10 @@ public class Evaluator implements ExpressionNodeVisitor<InterpreterValue> {
@Override
public InterpreterValue visit(TernaryConditionalNode ternaryConditional) {
val condition = eval(ternaryConditional.getCondition());
- if (!(condition instanceof BooleanValue)) {
+ if (!(condition instanceof BooleanInterpreterValue)) {
throw new ConditionMustBeBoolean(condition);
}
- val branch = ((BooleanValue)condition).getValue()
+ val branch = ((BooleanInterpreterValue)condition).getValue()
? ternaryConditional.getIfTrue()
: ternaryConditional.getIfFalse();
return eval(branch);
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Executor.java b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
index 2f12e0c..4ed4a04 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Executor.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
@@ -12,7 +12,7 @@ import org.zwobble.couscous.ast.StatementNode;
import org.zwobble.couscous.ast.VariableNode;
import org.zwobble.couscous.ast.visitors.StatementNodeVisitor;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.interpreter.values.UnitValue;
+import org.zwobble.couscous.interpreter.values.UnitInterpreterValue;
import static org.zwobble.couscous.interpreter.Evaluator.eval;
@@ -28,7 +28,7 @@ public class Executor implements StatementNodeVisitor<Optional<InterpreterValue>
return result.get();
}
}
- return UnitValue.UNIT;
+ return UnitInterpreterValue.UNIT;
}
private static Environment buildEnvironment(
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
index 39191ce..0c36d91 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
@@ -5,11 +5,11 @@ import java.util.stream.Collectors;
import org.zwobble.couscous.Project;
import org.zwobble.couscous.ast.ExpressionNode;
-import org.zwobble.couscous.ast.LiteralNode;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
import com.google.common.collect.ImmutableMap;
+import static org.zwobble.couscous.ast.LiteralNode.literal;
import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall;
import static org.zwobble.couscous.interpreter.Evaluator.eval;
@@ -25,7 +25,7 @@ public class Interpreter {
public InterpreterValue run(String className, String methodName, List<InterpreterValue> arguments) {
val argumentExpressions = arguments
.stream()
- .<ExpressionNode>map(LiteralNode::literal)
+ .<ExpressionNode>map(argument -> literal(argument.toPrimitiveValue().get()))
.collect(Collectors.toList());
return eval(new Environment(project, ImmutableMap.of()),
staticMethodCall(className, methodName, argumentExpressions));
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
new file mode 100644
index 0000000..4ab2d18
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
@@ -0,0 +1,33 @@
+package org.zwobble.couscous.interpreter.values;
+
+import java.util.Optional;
+
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Value;
+
+@Value
+public class BooleanInterpreterValue implements InterpreterValue {
+ private static final ConcreteType<BooleanInterpreterValue> TYPE = ConcreteType.<BooleanInterpreterValue>builder("Boolean")
+ .build();
+
+ @Getter(value = AccessLevel.NONE)
+ boolean value;
+
+ public boolean getValue() {
+ return value;
+ }
+
+ @Override
+ public ConcreteType<?> getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Optional<PrimitiveValue> toPrimitiveValue() {
+ return Optional.of(PrimitiveValues.value(value));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanValue.java
deleted file mode 100644
index 1837d6f..0000000
--- a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanValue.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.zwobble.couscous.interpreter.values;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.Value;
-
-@Value
-public class BooleanValue implements InterpreterValue {
- private static final ConcreteType<BooleanValue> TYPE = ConcreteType.<BooleanValue>builder("Boolean")
- .build();
-
- @Getter(value = AccessLevel.NONE)
- boolean value;
-
- public boolean getValue() {
- return value;
- }
-
- @Override
- public ConcreteType<?> getType() {
- return TYPE;
- }
-}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
new file mode 100644
index 0000000..c7d7be3
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
@@ -0,0 +1,37 @@
+package org.zwobble.couscous.interpreter.values;
+
+import java.util.Optional;
+
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
+import org.zwobble.couscous.values.StringValue;
+
+import static java.util.Arrays.asList;
+
+import lombok.Value;
+import lombok.val;
+
+@Value
+public class IntegerInterpreterValue implements InterpreterValue {
+ public static final ConcreteType<?> TYPE = ConcreteType.<IntegerInterpreterValue>builder(IntegerValue.REF)
+ .staticMethod("parseInt", asList(StringValue.REF),
+ (environment, arguments) -> {
+ val value = (StringInterpreterValue)arguments.get(0);
+ return new IntegerInterpreterValue(Integer.parseInt(value.getValue()));
+ })
+
+ .build();
+
+ int value;
+
+ @Override
+ public ConcreteType<?> getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Optional<PrimitiveValue> toPrimitiveValue() {
+ return Optional.of(PrimitiveValues.value(value));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerValue.java
deleted file mode 100644
index 89fd056..0000000
--- a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerValue.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.zwobble.couscous.interpreter.values;
-
-import org.zwobble.couscous.values.TypeReference;
-
-import static java.util.Arrays.asList;
-import static org.zwobble.couscous.values.TypeReference.typeRef;
-
-import lombok.Value;
-import lombok.val;
-
-@Value
-public class IntegerValue implements InterpreterValue {
- public static final TypeReference REF = typeRef("java.lang.Integer");
-
- public static final ConcreteType<?> TYPE = ConcreteType.<IntegerValue>builder(REF)
- .staticMethod("parseInt", asList(StringValue.REF),
- (environment, arguments) -> {
- val value = (StringValue)arguments.get(0);
- return new IntegerValue(Integer.parseInt(value.getValue()));
- })
-
- .build();
-
- int value;
-
- @Override
- public ConcreteType<?> getType() {
- return TYPE;
- }
-}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
index cf2aa5b..7696ff2 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
@@ -1,5 +1,10 @@
package org.zwobble.couscous.interpreter.values;
+import java.util.Optional;
+
+import org.zwobble.couscous.values.PrimitiveValue;
+
public interface InterpreterValue {
ConcreteType<?> getType();
+ Optional<PrimitiveValue> toPrimitiveValue();
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java
index ec2d97f..37a0669 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java
@@ -1,13 +1,44 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.values.BooleanValue;
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValueVisitor;
+import org.zwobble.couscous.values.StringValue;
+import org.zwobble.couscous.values.UnitValue;
+
public class InterpreterValues {
- public static final UnitValue UNIT = UnitValue.UNIT;
+ public static final UnitInterpreterValue UNIT = UnitInterpreterValue.UNIT;
public static InterpreterValue value(int value) {
- return new IntegerValue(value);
+ return new IntegerInterpreterValue(value);
}
public static InterpreterValue value(String value) {
- return new StringValue(value);
+ return new StringInterpreterValue(value);
+ }
+
+ public static InterpreterValue value(PrimitiveValue value) {
+ return value.accept(new PrimitiveValueVisitor<InterpreterValue>() {
+ @Override
+ public InterpreterValue visit(IntegerValue value) {
+ return new IntegerInterpreterValue(value.getValue());
+ }
+
+ @Override
+ public InterpreterValue visit(StringValue value) {
+ return new StringInterpreterValue(value.getValue());
+ }
+
+ @Override
+ public InterpreterValue visit(BooleanValue value) {
+ return new BooleanInterpreterValue(value.getValue());
+ }
+
+ @Override
+ public InterpreterValue visit(UnitValue unitValue) {
+ return UNIT;
+ }
+ });
}
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
new file mode 100644
index 0000000..f17cdd5
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
@@ -0,0 +1,41 @@
+package org.zwobble.couscous.interpreter.values;
+
+import java.util.Optional;
+
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
+import org.zwobble.couscous.values.StringValue;
+
+import static java.util.Arrays.asList;
+
+import lombok.Value;
+import lombok.val;
+
+@Value
+public class StringInterpreterValue implements InterpreterValue {
+ public static final ConcreteType<?> TYPE = ConcreteType.<StringInterpreterValue>builder(StringValue.REF)
+ .method("length", asList(),
+ (receiver, arguments) -> new IntegerInterpreterValue(receiver.value.length()))
+
+ .method("substring", asList(IntegerValue.REF, IntegerValue.REF),
+ (receiver, arguments) -> {
+ val startIndex = (IntegerInterpreterValue)arguments.get(0);
+ val endIndex = (IntegerInterpreterValue)arguments.get(1);
+ return new StringInterpreterValue(receiver.value.substring(startIndex.getValue(), endIndex.getValue()));
+ })
+
+ .build();
+
+ String value;
+
+ @Override
+ public ConcreteType<?> getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Optional<PrimitiveValue> toPrimitiveValue() {
+ return Optional.of(PrimitiveValues.value(value));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/StringValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/StringValue.java
deleted file mode 100644
index 43a4bde..0000000
--- a/src/main/java/org/zwobble/couscous/interpreter/values/StringValue.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.zwobble.couscous.interpreter.values;
-
-import org.zwobble.couscous.values.TypeReference;
-
-import static java.util.Arrays.asList;
-import static org.zwobble.couscous.values.TypeReference.typeRef;
-
-import lombok.Value;
-import lombok.val;
-
-@Value
-public class StringValue implements InterpreterValue {
- public static final TypeReference REF = typeRef("java.lang.String");
-
- public static final ConcreteType<?> TYPE = ConcreteType.<StringValue>builder(REF)
- .method("length", asList(),
- (receiver, arguments) -> new IntegerValue(receiver.value.length()))
-
- .method("substring", asList(IntegerValue.REF, IntegerValue.REF),
- (receiver, arguments) -> {
- val startIndex = (IntegerValue)arguments.get(0);
- val endIndex = (IntegerValue)arguments.get(1);
- return new StringValue(receiver.value.substring(startIndex.getValue(), endIndex.getValue()));
- })
-
- .build();
-
- String value;
-
- @Override
- public ConcreteType<?> getType() {
- return TYPE;
- }
-}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java
new file mode 100644
index 0000000..e34882b
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java
@@ -0,0 +1,29 @@
+package org.zwobble.couscous.interpreter.values;
+
+import java.util.Optional;
+
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
+
+import lombok.ToString;
+
+@ToString
+public class UnitInterpreterValue implements InterpreterValue {
+ private static final ConcreteType<?> TYPE = ConcreteType.<UnitInterpreterValue>builder("Unit")
+ .build();
+
+ public static final UnitInterpreterValue UNIT = new UnitInterpreterValue();
+
+ private UnitInterpreterValue() {
+ }
+
+ @Override
+ public ConcreteType<?> getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Optional<PrimitiveValue> toPrimitiveValue() {
+ return Optional.of(PrimitiveValues.UNIT);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/UnitValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/UnitValue.java
deleted file mode 100644
index 4e2eb2c..0000000
--- a/src/main/java/org/zwobble/couscous/interpreter/values/UnitValue.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.zwobble.couscous.interpreter.values;
-
-import lombok.ToString;
-
-@ToString
-public class UnitValue implements InterpreterValue {
- private static final ConcreteType<?> TYPE = ConcreteType.<UnitValue>builder("Unit")
- .build();
-
- public static final UnitValue UNIT = new UnitValue();
-
- private UnitValue() {
- }
-
- @Override
- public ConcreteType<?> getType() {
- return TYPE;
- }
-}
diff --git a/src/main/java/org/zwobble/couscous/values/BooleanValue.java b/src/main/java/org/zwobble/couscous/values/BooleanValue.java
new file mode 100644
index 0000000..e05c246
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/BooleanValue.java
@@ -0,0 +1,20 @@
+package org.zwobble.couscous.values;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Value;
+
+@Value
+public class BooleanValue implements PrimitiveValue {
+ @Getter(value = AccessLevel.NONE)
+ boolean value;
+
+ public boolean getValue() {
+ return value;
+ }
+
+ @Override
+ public <T> T accept(PrimitiveValueVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
new file mode 100644
index 0000000..71c7a41
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
@@ -0,0 +1,17 @@
+package org.zwobble.couscous.values;
+
+import static org.zwobble.couscous.values.TypeReference.typeRef;
+
+import lombok.Value;
+
+@Value
+public class IntegerValue implements PrimitiveValue {
+ public static final TypeReference REF = typeRef("java.lang.Integer");
+
+ int value;
+
+ @Override
+ public <T> T accept(PrimitiveValueVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java b/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java
new file mode 100644
index 0000000..2cfe40a
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/PrimitiveValue.java
@@ -0,0 +1,5 @@
+package org.zwobble.couscous.values;
+
+public interface PrimitiveValue {
+ <T> T accept(PrimitiveValueVisitor<T> visitor);
+}
diff --git a/src/main/java/org/zwobble/couscous/values/PrimitiveValueVisitor.java b/src/main/java/org/zwobble/couscous/values/PrimitiveValueVisitor.java
new file mode 100644
index 0000000..07047b8
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/PrimitiveValueVisitor.java
@@ -0,0 +1,8 @@
+package org.zwobble.couscous.values;
+
+public interface PrimitiveValueVisitor<T> {
+ T visit(IntegerValue value);
+ T visit(StringValue value);
+ T visit(BooleanValue value);
+ T visit(UnitValue unitValue);
+}
diff --git a/src/main/java/org/zwobble/couscous/values/PrimitiveValues.java b/src/main/java/org/zwobble/couscous/values/PrimitiveValues.java
new file mode 100644
index 0000000..f6420f0
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/PrimitiveValues.java
@@ -0,0 +1,17 @@
+package org.zwobble.couscous.values;
+
+public class PrimitiveValues {
+ public static final PrimitiveValue UNIT = UnitValue.UNIT;
+
+ public static PrimitiveValue value(String value) {
+ return new StringValue(value);
+ }
+
+ public static PrimitiveValue value(int value) {
+ return new IntegerValue(value);
+ }
+
+ public static PrimitiveValue value(boolean value) {
+ return new BooleanValue(value);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/values/StringValue.java b/src/main/java/org/zwobble/couscous/values/StringValue.java
new file mode 100644
index 0000000..256d6d1
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/StringValue.java
@@ -0,0 +1,17 @@
+package org.zwobble.couscous.values;
+
+import static org.zwobble.couscous.values.TypeReference.typeRef;
+
+import lombok.Value;
+
+@Value
+public class StringValue implements PrimitiveValue {
+ public static final TypeReference REF = typeRef("java.lang.String");
+
+ String value;
+
+ @Override
+ public <T> T accept(PrimitiveValueVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/values/UnitValue.java b/src/main/java/org/zwobble/couscous/values/UnitValue.java
new file mode 100644
index 0000000..14bf327
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/UnitValue.java
@@ -0,0 +1,13 @@
+package org.zwobble.couscous.values;
+
+public class UnitValue implements PrimitiveValue {
+ static final UnitValue UNIT = new UnitValue();
+
+ private UnitValue() {
+ }
+
+ @Override
+ public <T> T accept(PrimitiveValueVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/BackendTests.java b/src/test/java/org/zwobble/couscous/tests/BackendTests.java
index 216ede0..ce3fc7d 100644
--- a/src/test/java/org/zwobble/couscous/tests/BackendTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/BackendTests.java
@@ -4,14 +4,14 @@ import org.junit.Test;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.ast.ReturnNode;
-import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.interpreter.values.StringValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
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.MethodNode.staticMethod;
-import static org.zwobble.couscous.interpreter.values.UnitValue.UNIT;
+import static org.zwobble.couscous.values.PrimitiveValues.value;
import lombok.val;
@@ -21,7 +21,7 @@ public abstract class BackendTests {
val method = staticMethod("hello");
val result = runMethod(method);
- assertEquals(UNIT, result);
+ assertEquals(PrimitiveValues.UNIT, result);
}
@Test
@@ -30,10 +30,10 @@ public abstract class BackendTests {
.statement(new ReturnNode(literal("hello, world!")));
val result = runMethod(method);
- assertEquals(new StringValue("hello, world!"), result);
+ assertEquals(value("hello, world!"), result);
}
- protected InterpreterValue runMethod(MethodNode.MethodNodeBuilder methodBuilder, InterpreterValue... arguments) {
+ protected PrimitiveValue runMethod(MethodNode.MethodNodeBuilder methodBuilder, PrimitiveValue... arguments) {
val method = methodBuilder.build();
val className = "com.example.Program";
val classNode = ClassNode.builder(className)
diff --git a/src/test/java/org/zwobble/couscous/tests/MethodRunner.java b/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
index 8fc4cf1..ff9439c 100644
--- a/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
+++ b/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
@@ -3,8 +3,8 @@ package org.zwobble.couscous.tests;
import java.util.List;
import org.zwobble.couscous.ast.ClassNode;
-import org.zwobble.couscous.interpreter.values.InterpreterValue;
+import org.zwobble.couscous.values.PrimitiveValue;
public interface MethodRunner {
- InterpreterValue runMethod(ClassNode classNode, String methodName, List<InterpreterValue> arguments);
+ PrimitiveValue runMethod(ClassNode classNode, String methodName, List<PrimitiveValue> arguments);
}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
index 76893c8..6f171c3 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
@@ -8,18 +8,18 @@ import java.util.List;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.backends.python.PythonCompiler;
-import org.zwobble.couscous.interpreter.values.InterpreterValue;
import org.zwobble.couscous.tests.BackendTests;
import org.zwobble.couscous.tests.MethodRunner;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import static java.lang.Integer.parseInt;
import static java.util.Arrays.asList;
-import static org.zwobble.couscous.interpreter.values.InterpreterValues.UNIT;
-import static org.zwobble.couscous.interpreter.values.InterpreterValues.value;
import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively;
+import static org.zwobble.couscous.values.PrimitiveValues.value;
import lombok.SneakyThrows;
import lombok.val;
@@ -30,10 +30,10 @@ public class PythonCompilerTests extends BackendTests {
return new MethodRunner() {
@Override
@SneakyThrows
- public InterpreterValue runMethod(
+ public PrimitiveValue runMethod(
ClassNode classNode,
String methodName,
- List<InterpreterValue> arguments) {
+ List<PrimitiveValue> arguments) {
val compiler = new PythonCompiler();
val directoryPath = Files.createTempDirectory(null);
try {
@@ -51,7 +51,7 @@ public class PythonCompilerTests extends BackendTests {
if (exitCode != 0) {
throw new RuntimeException("stderr was: " + stderrOutput);
} else if (output.equals("None")) {
- return UNIT;
+ return PrimitiveValues.UNIT;
} else if (output.startsWith("'")) {
return value(output.substring(1, output.length() - 1));
} else {
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 bdd2590..3ed1b6d 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
@@ -14,8 +14,10 @@ import org.zwobble.couscous.interpreter.StackFrameBuilder;
import org.zwobble.couscous.interpreter.UnexpectedValueType;
import org.zwobble.couscous.interpreter.WrongNumberOfArguments;
import org.zwobble.couscous.interpreter.values.ConcreteType;
-import org.zwobble.couscous.interpreter.values.IntegerValue;
-import org.zwobble.couscous.interpreter.values.StringValue;
+import org.zwobble.couscous.interpreter.values.IntegerInterpreterValue;
+import org.zwobble.couscous.interpreter.values.StringInterpreterValue;
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.StringValue;
import com.google.common.collect.ImmutableMap;
@@ -27,6 +29,7 @@ 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.interpreter.values.InterpreterValues.value;
import static org.zwobble.couscous.tests.util.ExtraAsserts.assertThrows;
import lombok.val;
@@ -37,23 +40,23 @@ public class EvaluatorTests {
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());
+ new StackFrameBuilder().declare(arg, value("[initial value]")).build());
val result = eval(environment, assign(arg, literal("[updated value]")));
- assertEquals(new StringValue("[updated value]"), result);
+ assertEquals(new StringInterpreterValue("[updated value]"), result);
}
@Test
public void whenConditionIsTrueThenValueOfConditionalTernaryIsTrueBranch() {
val result = eval(emptyEnvironment(),
new TernaryConditionalNode(literal(true), literal("T"), literal("F")));
- assertEquals(new StringValue("T"), result);
+ assertEquals(new StringInterpreterValue("T"), result);
}
@Test
public void whenConditionIsFalseThenValueOfConditionalTernaryIsFalseBranch() {
val result = eval(emptyEnvironment(),
new TernaryConditionalNode(literal(false), literal("T"), literal("F")));
- assertEquals(new StringValue("F"), result);
+ assertEquals(new StringInterpreterValue("F"), result);
}
@Test
@@ -61,21 +64,21 @@ public class EvaluatorTests {
val exception = assertThrows(ConditionMustBeBoolean.class,
() -> eval(emptyEnvironment(),
new TernaryConditionalNode(literal(1), literal("T"), literal("F"))));
- assertEquals(new ConditionMustBeBoolean(new IntegerValue(1)), exception);
+ assertEquals(new ConditionMustBeBoolean(new IntegerInterpreterValue(1)), exception);
}
@Test
public void canCallMethodWithNoArgumentsOnBuiltin() {
val result = eval(emptyEnvironment(),
methodCall(literal("hello"), "length"));
- assertEquals(new IntegerValue(5), result);
+ assertEquals(new IntegerInterpreterValue(5), result);
}
@Test
public void canCallMethodWithArgumentsOnBuiltin() {
val result = eval(emptyEnvironment(),
methodCall(literal("hello"), "substring", literal(1), literal(4)));
- assertEquals(new StringValue("ell"), result);
+ assertEquals(new StringInterpreterValue("ell"), result);
}
@Test
@@ -106,7 +109,7 @@ public class EvaluatorTests {
public void canCallStaticMethod() {
val result = eval(emptyEnvironment(),
staticMethodCall("java.lang.Integer", "parseInt", literal("42")));
- assertEquals(new IntegerValue(42), result);
+ assertEquals(new IntegerInterpreterValue(42), result);
}
@Test
@@ -123,7 +126,7 @@ public class EvaluatorTests {
ImmutableMap.of());
val result = eval(environment,
staticMethodCall("com.example.Program", "main"));
- assertEquals(new IntegerValue(42), result);
+ assertEquals(new IntegerInterpreterValue(42), result);
}
private static Environment emptyEnvironment() {
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 3f2bbcd..09c3993 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java
@@ -1,6 +1,7 @@
package org.zwobble.couscous.tests.interpreter;
import java.util.List;
+import java.util.stream.Collectors;
import org.junit.Test;
import org.zwobble.couscous.MapBackedProject;
@@ -15,11 +16,12 @@ import org.zwobble.couscous.interpreter.UnexpectedValueType;
import org.zwobble.couscous.interpreter.VariableNotInScope;
import org.zwobble.couscous.interpreter.WrongNumberOfArguments;
import org.zwobble.couscous.interpreter.values.ConcreteType;
-import org.zwobble.couscous.interpreter.values.IntegerValue;
-import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.interpreter.values.StringValue;
+import org.zwobble.couscous.interpreter.values.InterpreterValues;
import org.zwobble.couscous.tests.BackendTests;
import org.zwobble.couscous.tests.MethodRunner;
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.StringValue;
import com.google.common.collect.ImmutableMap;
@@ -31,6 +33,7 @@ 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.PrimitiveValues.value;
import lombok.val;
@@ -41,9 +44,9 @@ public class InterpreterTests extends BackendTests {
val method = staticMethod("hello")
.argument(arg)
.statement(new ReturnNode(reference(arg)));
- val result = runMethod(method, new StringValue("hello, world!"));
+ val result = runMethod(method, value("hello, world!"));
- assertEquals(new StringValue("hello, world!"), result);
+ assertEquals(value("hello, world!"), result);
}
@Test
@@ -51,7 +54,7 @@ public class InterpreterTests extends BackendTests {
val method = staticMethod("hello");
val exception = assertThrows(WrongNumberOfArguments.class,
- () -> runMethod(method, new StringValue("hello, world!")));
+ () -> runMethod(method, value("hello, world!")));
assertEquals(new WrongNumberOfArguments(0, 1), exception);
}
@@ -63,9 +66,9 @@ public class InterpreterTests extends BackendTests {
.argument(arg)
.statement(new ExpressionStatementNode(new Assignment(reference(arg), LiteralNode.literal("[updated value]"))))
.statement(new ReturnNode(reference(arg)));
- val result = runMethod(method, new StringValue("[initial value]"));
+ val result = runMethod(method, value("[initial value]"));
- assertEquals(new StringValue("[updated value]"), result);
+ assertEquals(value("[updated value]"), result);
}
@Test
@@ -76,7 +79,7 @@ public class InterpreterTests extends BackendTests {
.statement(new ExpressionStatementNode(new Assignment(reference(arg), literal(0))));
val exception = assertThrows(UnexpectedValueType.class,
- () -> runMethod(method, new StringValue("")));
+ () -> runMethod(method, value("")));
assertEquals(new UnexpectedValueType(StringValue.REF, IntegerValue.REF), exception);
}
@@ -90,7 +93,7 @@ public class InterpreterTests extends BackendTests {
.statement(new ReturnNode(reference(localVariableDeclaration)));
val result = runMethod(method);
- assertEquals(new StringValue("[initial value]"), result);
+ assertEquals(value("[initial value]"), result);
}
@Test
@@ -103,7 +106,7 @@ public class InterpreterTests extends BackendTests {
.statement(new ReturnNode(reference(localVariableDeclaration)));
val result = runMethod(method);
- assertEquals(new StringValue("[updated value]"), result);
+ assertEquals(value("[updated value]"), result);
}
@Test
@@ -150,14 +153,18 @@ public class InterpreterTests extends BackendTests {
protected MethodRunner buildMethodRunner() {
return new MethodRunner() {
@Override
- public InterpreterValue runMethod(
+ public PrimitiveValue runMethod(
ClassNode classNode,
String methodName,
- List<InterpreterValue> arguments) {
+ List<PrimitiveValue> arguments) {
val interpreter = new Interpreter(new MapBackedProject(ImmutableMap.of(
classNode.getName(), ConcreteType.fromNode(classNode))));
+ val argumentValues = arguments.stream()
+ .map(InterpreterValues::value)
+ .collect(Collectors.toList());
- return interpreter.run(classNode.getName(), methodName, arguments);
+ return interpreter.run(classNode.getName(), methodName, argumentValues)
+ .toPrimitiveValue().get();
}
};
}