aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-10-01 21:49:18 +0100
committerMichael Williamson <mike@zwobble.org>2015-10-01 21:49:18 +0100
commit30d2215800deafbdcfb134f1356777ec0139bb7a (patch)
treee687fa289e269bd91ab19b027d6d8a96b9c96b4d /src/main/java
parent8187130b8a8aabbcf983e530413d6969141d6da2 (diff)
Use normal method call exec in interpreter entry point
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/couscous/Project.java4
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ClassNode.java1
-rw-r--r--src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java12
-rw-r--r--src/main/java/org/zwobble/couscous/ast/LiteralNode.java4
-rw-r--r--src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Environment.java15
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Executor.java34
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Interpreter.java68
-rw-r--r--src/main/java/org/zwobble/couscous/values/ConcreteType.java59
9 files changed, 133 insertions, 68 deletions
diff --git a/src/main/java/org/zwobble/couscous/Project.java b/src/main/java/org/zwobble/couscous/Project.java
index 6afac6e..56b439f 100644
--- a/src/main/java/org/zwobble/couscous/Project.java
+++ b/src/main/java/org/zwobble/couscous/Project.java
@@ -1,7 +1,7 @@
package org.zwobble.couscous;
-import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.values.ConcreteType;
public interface Project {
- ClassNode findClass(String name);
+ ConcreteType<?> findClass(String name);
}
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNode.java b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
index ffa5165..6dd7b12 100644
--- a/src/main/java/org/zwobble/couscous/ast/ClassNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
@@ -9,6 +9,7 @@ import lombok.Value;
@Builder
@Value
public class ClassNode {
+ String name;
@Singular
List<MethodNode> methods;
}
diff --git a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
index da3a838..72a5f51 100644
--- a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
@@ -1,9 +1,21 @@
package org.zwobble.couscous.ast;
+import java.util.function.Supplier;
+
+import org.zwobble.couscous.values.ConcreteType;
+
+import lombok.AccessLevel;
+import lombok.Getter;
import lombok.Value;
@Value
public class FormalArgumentNode implements VariableNode {
int id;
+ @Getter(value=AccessLevel.NONE)
+ Supplier<ConcreteType<?>> type;
String name;
+
+ public ConcreteType<?> getType() {
+ return type.get();
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
index cc57aef..0869653 100644
--- a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java
@@ -10,6 +10,10 @@ import lombok.Value;
@Value
public class LiteralNode implements ExpressionNode {
+ public static LiteralNode literal(InterpreterValue value) {
+ return new LiteralNode(value);
+ }
+
public static LiteralNode literal(String value) {
return new LiteralNode(new StringValue(value));
}
diff --git a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java
index 390c37f..4f1e9ff 100644
--- a/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/StaticMethodCallNode.java
@@ -14,6 +14,10 @@ public class StaticMethodCallNode implements ExpressionNode {
return new StaticMethodCallNode(className, methodName, asList(arguments));
}
+ public static StaticMethodCallNode staticMethodCall(String className, String methodName, List<ExpressionNode> arguments) {
+ return new StaticMethodCallNode(className, methodName, arguments);
+ }
+
String className;
String methodName;
List<ExpressionNode> arguments;
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
index ea4a5e4..76aa56b 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
@@ -3,14 +3,16 @@ package org.zwobble.couscous.interpreter;
import java.util.HashMap;
import java.util.Map;
+import org.zwobble.couscous.Project;
import org.zwobble.couscous.values.ConcreteType;
-import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.InterpreterValue;
public class Environment {
- private Map<Integer, InterpreterValue> stackFrame;
+ private final Map<Integer, InterpreterValue> stackFrame;
+ private final Project project;
- public Environment(Map<Integer, InterpreterValue> stackFrame) {
+ public Environment(Project project, Map<Integer, InterpreterValue> stackFrame) {
+ this.project = project;
this.stackFrame = new HashMap<>(stackFrame);
}
@@ -23,10 +25,7 @@ public class Environment {
}
public ConcreteType<?> findClass(String className) {
- if (className == "java.lang.Integer") {
- return IntegerValue.TYPE;
- } else {
- throw new UnsupportedOperationException();
- }
+ // TODO: handle missing classes
+ return project.findClass(className);
}
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Executor.java b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
new file mode 100644
index 0000000..633bf6b
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
@@ -0,0 +1,34 @@
+package org.zwobble.couscous.interpreter;
+
+import java.util.Optional;
+
+import org.zwobble.couscous.ast.ExpressionStatementNode;
+import org.zwobble.couscous.ast.ReturnNode;
+import org.zwobble.couscous.ast.StatementNode;
+import org.zwobble.couscous.ast.visitors.StatementNodeVisitor;
+import org.zwobble.couscous.values.InterpreterValue;
+
+import static org.zwobble.couscous.interpreter.Evaluator.eval;
+
+public class Executor implements StatementNodeVisitor<Optional<InterpreterValue>> {
+ public static Optional<InterpreterValue> exec(Environment environment, StatementNode statement) {
+ return statement.accept(new Executor(environment));
+ }
+
+ private final Environment environment;
+
+ private Executor(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ public Optional<InterpreterValue> visit(ReturnNode returnNode) {
+ return Optional.of(eval(environment, returnNode.getValue()));
+ }
+
+ @Override
+ public Optional<InterpreterValue> visit(ExpressionStatementNode expressionStatement) {
+ eval(environment, expressionStatement.getExpression());
+ return Optional.empty();
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
index bc82fee..884a082 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
@@ -1,20 +1,17 @@
package org.zwobble.couscous.interpreter;
import java.util.List;
-import java.util.Optional;
-import java.util.stream.IntStream;
+import java.util.stream.Collectors;
import org.zwobble.couscous.Project;
-import org.zwobble.couscous.ast.ExpressionStatementNode;
-import org.zwobble.couscous.ast.MethodNode;
-import org.zwobble.couscous.ast.ReturnNode;
-import org.zwobble.couscous.ast.visitors.StatementNodeVisitor;
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.LiteralNode;
import org.zwobble.couscous.values.InterpreterValue;
-import static com.google.common.collect.Iterables.find;
-import static java.util.stream.Collectors.toMap;
+import com.google.common.collect.ImmutableMap;
+
+import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall;
import static org.zwobble.couscous.interpreter.Evaluator.eval;
-import static org.zwobble.couscous.values.UnitValue.UNIT;
import lombok.val;
@@ -26,52 +23,11 @@ public class Interpreter {
}
public InterpreterValue run(String className, String methodName, List<InterpreterValue> arguments) {
- val clazz = project.findClass(className);
- val method = find(clazz.getMethods(),
- method -> method.getName().equals(methodName));
- val environment = buildEnvironment(method, arguments);
-
- for (val statement : method.getBody()) {
- val result = statement.accept(new Executor(environment));
- if (result.isPresent()) {
- return result.get();
- }
- }
- return UNIT;
- }
-
- private Environment buildEnvironment(
- final MethodNode method,
- List<InterpreterValue> arguments) {
-
- if (method.getArguments().size() != arguments.size()) {
- throw new WrongNumberOfArguments(method.getArguments().size(), arguments.size());
- }
-
- val stackFrame = IntStream.range(0, method.getArguments().size())
- .boxed()
- .collect(toMap(
- index -> method.getArguments().get(index).getId(),
- index -> arguments.get(index)));
- return new Environment(stackFrame);
- }
-
- private class Executor implements StatementNodeVisitor<Optional<InterpreterValue>> {
- private Environment environment;
-
- public Executor(Environment environment) {
- this.environment = environment;
- }
-
- @Override
- public Optional<InterpreterValue> visit(ReturnNode returnNode) {
- return Optional.of(eval(environment, returnNode.getValue()));
- }
-
- @Override
- public Optional<InterpreterValue> visit(ExpressionStatementNode expressionStatement) {
- eval(environment, expressionStatement.getExpression());
- return Optional.empty();
- }
+ val argumentExpressions = arguments
+ .stream()
+ .<ExpressionNode>map(LiteralNode::literal)
+ .collect(Collectors.toList());
+ return eval(new Environment(project, ImmutableMap.of()),
+ staticMethodCall(className, methodName, argumentExpressions));
}
}
diff --git a/src/main/java/org/zwobble/couscous/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
index db5209e..6aea1db 100644
--- a/src/main/java/org/zwobble/couscous/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
@@ -5,14 +5,23 @@ import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.zwobble.couscous.Project;
+import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.interpreter.Arguments;
+import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.NoSuchMethod;
import org.zwobble.couscous.interpreter.UnexpectedValueType;
import org.zwobble.couscous.interpreter.WrongNumberOfArguments;
import com.google.common.collect.ImmutableMap;
+import static java.util.stream.Collectors.toMap;
+import static org.zwobble.couscous.interpreter.Executor.exec;
+
import lombok.val;
public class ConcreteType<T> {
@@ -47,15 +56,61 @@ public class ConcreteType<T> {
return new ConcreteType<T>(name, methods.build(), staticMethods.build());
}
}
+
+ public static ConcreteType<?> fromNode(ClassNode classNode) {
+ val staticMethods = classNode.getMethods()
+ .stream()
+ .filter(method -> method.isStatic())
+ .collect(toMap(
+ method -> method.getName(),
+ method -> {
+ Supplier<List<ConcreteType<?>>> argumentTypes = () -> method.getArguments()
+ .stream()
+ .<ConcreteType<?>>map(arg -> arg.getType())
+ .collect(Collectors.toList());
+ return new StaticMethodValue(argumentTypes, arguments -> {
+ val environment = buildEnvironment(method, arguments);
+
+ for (val statement : method.getBody()) {
+ val result = exec(environment, statement);
+ if (result.isPresent()) {
+ return result.get();
+ }
+ }
+ return UnitValue.UNIT;
+ });
+ }));
+ return new ConcreteType<Void>(
+ classNode.getName(),
+ ImmutableMap.of(),
+ staticMethods);
+ }
+
+ private static Environment buildEnvironment(
+ final MethodNode method,
+ Arguments arguments) {
+
+ val stackFrame = IntStream.range(0, method.getArguments().size())
+ .boxed()
+ .collect(toMap(
+ index -> method.getArguments().get(index).getId(),
+ index -> arguments.get(index)));
+ return new Environment(new Project() {
+ @Override
+ public ConcreteType<?> findClass(String name) {
+ throw new UnsupportedOperationException();
+ }
+ }, stackFrame);
+ }
private String name;
private Map<String, MethodValue<T>> methods;
- private ImmutableMap<String, StaticMethodValue> staticMethods;
+ private Map<String, StaticMethodValue> staticMethods;
public ConcreteType(
String name,
Map<String, MethodValue<T>> methods,
- ImmutableMap<String, StaticMethodValue> staticMethods) {
+ Map<String, StaticMethodValue> staticMethods) {
this.name = name;
this.methods = methods;
this.staticMethods = staticMethods;