aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/couscous/JavaProject.java10
-rw-r--r--src/main/java/org/zwobble/couscous/MapBackedProject.java23
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ClassNode.java27
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Environment.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java2
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Executor.java38
-rw-r--r--src/main/java/org/zwobble/couscous/values/ConcreteType.java19
-rw-r--r--src/main/java/org/zwobble/couscous/values/IntegerValue.java2
-rw-r--r--src/main/java/org/zwobble/couscous/values/StaticMethodValue.java9
9 files changed, 94 insertions, 40 deletions
diff --git a/src/main/java/org/zwobble/couscous/JavaProject.java b/src/main/java/org/zwobble/couscous/JavaProject.java
new file mode 100644
index 0000000..49e9355
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/JavaProject.java
@@ -0,0 +1,10 @@
+package org.zwobble.couscous;
+
+import org.zwobble.couscous.values.IntegerValue;
+
+public class JavaProject {
+ public static MapBackedProject.MapBackedProjectBuilder builder() {
+ return MapBackedProject.builder()
+ .addClass("java.lang.Integer", IntegerValue.TYPE);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/MapBackedProject.java b/src/main/java/org/zwobble/couscous/MapBackedProject.java
new file mode 100644
index 0000000..66b3681
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/MapBackedProject.java
@@ -0,0 +1,23 @@
+package org.zwobble.couscous;
+
+import java.util.Map;
+
+import org.zwobble.couscous.values.ConcreteType;
+
+import lombok.Builder;
+import lombok.Singular;
+
+@Builder
+public class MapBackedProject implements Project {
+ @Singular(value="addClass")
+ private Map<String, ConcreteType<?>> classes;
+
+ public MapBackedProject(Map<String, ConcreteType<?>> classes) {
+ this.classes = classes;
+ }
+
+ @Override
+ public ConcreteType<?> findClass(String name) {
+ return classes.get(name);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNode.java b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
index 6dd7b12..72e57d2 100644
--- a/src/main/java/org/zwobble/couscous/ast/ClassNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
@@ -2,13 +2,36 @@ package org.zwobble.couscous.ast;
import java.util.List;
-import lombok.Builder;
+import com.google.common.collect.ImmutableList;
+
import lombok.Singular;
import lombok.Value;
-@Builder
@Value
public class ClassNode {
+ public static ClassNode.Builder builder(String name) {
+ return new Builder(name);
+ }
+
+ public static class Builder {
+ private final String name;
+ private final ImmutableList.Builder<MethodNode> methods;
+
+ public Builder(String name) {
+ this.name = name;
+ this.methods = ImmutableList.builder();
+ }
+
+ public Builder method(MethodNode method) {
+ this.methods.add(method);
+ return this;
+ }
+
+ public ClassNode build() {
+ return new ClassNode(name, methods.build());
+ }
+ }
+
String name;
@Singular
List<MethodNode> methods;
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
index 76aa56b..b4decd8 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
@@ -28,4 +28,8 @@ public class Environment {
// TODO: handle missing classes
return project.findClass(className);
}
+
+ public Environment withStackFrame(Map<Integer, InterpreterValue> stackFrame) {
+ return new Environment(project, stackFrame);
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index 5acef94..6287348 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -79,6 +79,6 @@ public class Evaluator implements ExpressionNodeVisitor<InterpreterValue> {
public InterpreterValue visit(StaticMethodCallNode staticMethodCall) {
val clazz = environment.findClass(staticMethodCall.getClassName());
val arguments = evalArguments(staticMethodCall.getArguments());
- return clazz.callStaticMethod(staticMethodCall.getMethodName(), arguments);
+ return clazz.callStaticMethod(environment, staticMethodCall.getMethodName(), arguments);
}
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Executor.java b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
index cbeeaa4..4002238 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Executor.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
@@ -1,20 +1,14 @@
package org.zwobble.couscous.interpreter;
-import java.util.List;
import java.util.Optional;
-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.ExpressionStatementNode;
import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.ast.ReturnNode;
import org.zwobble.couscous.ast.StatementNode;
import org.zwobble.couscous.ast.visitors.StatementNodeVisitor;
-import org.zwobble.couscous.values.ConcreteType;
import org.zwobble.couscous.values.InterpreterValue;
-import org.zwobble.couscous.values.StaticMethodValue;
import org.zwobble.couscous.values.UnitValue;
import static java.util.stream.Collectors.toMap;
@@ -23,25 +17,20 @@ import static org.zwobble.couscous.interpreter.Evaluator.eval;
import lombok.val;
public class Executor implements StatementNodeVisitor<Optional<InterpreterValue>> {
- public static StaticMethodValue callMethod(MethodNode 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();
- }
+ public static InterpreterValue callMethod(Environment environment, MethodNode method, Arguments arguments) {
+ val innerEnvironment = buildEnvironment(environment, method, arguments);
+
+ for (val statement : method.getBody()) {
+ val result = exec(innerEnvironment, statement);
+ if (result.isPresent()) {
+ return result.get();
}
- return UnitValue.UNIT;
- });
+ }
+ return UnitValue.UNIT;
}
private static Environment buildEnvironment(
+ final Environment environment,
final MethodNode method,
Arguments arguments) {
@@ -50,12 +39,7 @@ public class Executor implements StatementNodeVisitor<Optional<InterpreterValue>
.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);
+ return environment.withStackFrame(stackFrame);
}
public static Optional<InterpreterValue> exec(Environment environment, StatementNode statement) {
diff --git a/src/main/java/org/zwobble/couscous/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
index 7d296db..43016d1 100644
--- a/src/main/java/org/zwobble/couscous/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
@@ -3,11 +3,12 @@ package org.zwobble.couscous.values;
import java.util.List;
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 org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.interpreter.Arguments;
+import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.Executor;
import org.zwobble.couscous.interpreter.NoSuchMethod;
import org.zwobble.couscous.interpreter.UnexpectedValueType;
@@ -42,7 +43,7 @@ public class ConcreteType<T> {
public Builder<T> staticMethod(
String name,
Supplier<List<ConcreteType<?>>> argumentsTypes,
- Function<Arguments, InterpreterValue> method) {
+ BiFunction<Environment, Arguments, InterpreterValue> method) {
staticMethods.put(name, new StaticMethodValue(argumentsTypes, method));
return this;
}
@@ -58,7 +59,15 @@ public class ConcreteType<T> {
.filter(method -> method.isStatic())
.collect(toMap(
method -> method.getName(),
- Executor::callMethod));
+ method -> {
+ Supplier<List<ConcreteType<?>>> argumentTypes = () -> method.getArguments()
+ .stream()
+ .<ConcreteType<?>>map(arg -> arg.getType())
+ .collect(Collectors.toList());
+ return new StaticMethodValue(argumentTypes, (environment, arguments) -> {
+ return Executor.callMethod(environment, method, arguments);
+ });
+ }));
return new ConcreteType<Void>(
classNode.getName(),
ImmutableMap.of(),
@@ -88,9 +97,9 @@ public class ConcreteType<T> {
return method.apply((T)receiver, new Arguments(arguments));
}
- public InterpreterValue callStaticMethod(String methodName, List<InterpreterValue> arguments) {
+ public InterpreterValue callStaticMethod(Environment environment, String methodName, List<InterpreterValue> arguments) {
val method = findMethod(staticMethods, methodName, arguments);
- return method.apply(new Arguments(arguments));
+ return method.apply(environment, new Arguments(arguments));
}
private static <T extends Callable> T findMethod(Map<String, T> methods, String methodName, List<InterpreterValue> arguments) {
diff --git a/src/main/java/org/zwobble/couscous/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
index 1b20a01..76d0c59 100644
--- a/src/main/java/org/zwobble/couscous/values/IntegerValue.java
+++ b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
@@ -9,7 +9,7 @@ import lombok.val;
public class IntegerValue implements InterpreterValue {
public static final ConcreteType<?> TYPE = ConcreteType.<IntegerValue>builder("Integer")
.staticMethod("parseInt", () -> asList(StringValue.TYPE),
- arguments -> {
+ (environment, arguments) -> {
val value = (StringValue)arguments.get(0);
return new IntegerValue(Integer.parseInt(value.getValue()));
})
diff --git a/src/main/java/org/zwobble/couscous/values/StaticMethodValue.java b/src/main/java/org/zwobble/couscous/values/StaticMethodValue.java
index 15a70d3..80ace03 100644
--- a/src/main/java/org/zwobble/couscous/values/StaticMethodValue.java
+++ b/src/main/java/org/zwobble/couscous/values/StaticMethodValue.java
@@ -1,10 +1,11 @@
package org.zwobble.couscous.values;
import java.util.List;
-import java.util.function.Function;
+import java.util.function.BiFunction;
import java.util.function.Supplier;
import org.zwobble.couscous.interpreter.Arguments;
+import org.zwobble.couscous.interpreter.Environment;
import lombok.AccessLevel;
import lombok.Getter;
@@ -15,15 +16,15 @@ public class StaticMethodValue implements Callable {
@Getter(value=AccessLevel.NONE)
Supplier<List<ConcreteType<?>>> argumentTypes;
@Getter(value=AccessLevel.NONE)
- Function<Arguments, InterpreterValue> apply;
+ BiFunction<Environment, Arguments, InterpreterValue> apply;
@Override
public List<ConcreteType<?>> getArgumentTypes() {
return argumentTypes.get();
}
- public InterpreterValue apply(Arguments arguments) {
- return apply.apply(arguments);
+ public InterpreterValue apply(Environment environment, Arguments arguments) {
+ return apply.apply(environment, arguments);
}
}