aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-02-28 11:36:25 +0000
committerMichael Williamson <mike@zwobble.org>2016-02-28 11:36:25 +0000
commit4e4f98062c07afdeef14d4031ca69668649e5873 (patch)
tree6415aea98dc33ab50c490fbb3f812412f6dad8f0 /src/main
parentc588167505864bece6cbb2dc68814f7d967d9a6a (diff)
Introduce InterfaceNode
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/zwobble/couscous/Backend.java6
-rw-r--r--src/main/java/org/zwobble/couscous/CouscousCompiler.java8
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ClassNode.java9
-rw-r--r--src/main/java/org/zwobble/couscous/ast/InterfaceNode.java81
-rw-r--r--src/main/java/org/zwobble/couscous/ast/TypeNode.java10
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java6
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java8
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java20
-rw-r--r--src/main/java/org/zwobble/couscous/cli/CouscousCli.java3
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaFrontend.java11
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/JavaProject.java3
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java20
13 files changed, 146 insertions, 43 deletions
diff --git a/src/main/java/org/zwobble/couscous/Backend.java b/src/main/java/org/zwobble/couscous/Backend.java
index 4415593..1c68701 100644
--- a/src/main/java/org/zwobble/couscous/Backend.java
+++ b/src/main/java/org/zwobble/couscous/Backend.java
@@ -1,10 +1,10 @@
package org.zwobble.couscous;
+import org.zwobble.couscous.ast.TypeNode;
+
import java.io.IOException;
import java.util.List;
-import org.zwobble.couscous.ast.ClassNode;
-
public interface Backend {
- void compile(List<ClassNode> classes) throws IOException;
+ void compile(List<TypeNode> classes) throws IOException;
}
diff --git a/src/main/java/org/zwobble/couscous/CouscousCompiler.java b/src/main/java/org/zwobble/couscous/CouscousCompiler.java
index 9c909ac..4822d97 100644
--- a/src/main/java/org/zwobble/couscous/CouscousCompiler.java
+++ b/src/main/java/org/zwobble/couscous/CouscousCompiler.java
@@ -1,12 +1,12 @@
package org.zwobble.couscous;
+import org.zwobble.couscous.ast.TypeNode;
+import org.zwobble.couscous.frontends.java.JavaFrontend;
+
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
-import org.zwobble.couscous.ast.ClassNode;
-import org.zwobble.couscous.frontends.java.JavaFrontend;
-
public class CouscousCompiler {
private final JavaFrontend frontend;
private final Backend backend;
@@ -17,7 +17,7 @@ public class CouscousCompiler {
}
public void compileDirectory(List<Path> sourcePaths, Path path) throws IOException {
- List<ClassNode> classes = frontend.readSourceDirectory(sourcePaths, path);
+ List<TypeNode> classes = frontend.readSourceDirectory(sourcePaths, path);
backend.compile(classes);
}
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNode.java b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
index 0aaa8c1..5d6d5e2 100644
--- a/src/main/java/org/zwobble/couscous/ast/ClassNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/ClassNode.java
@@ -6,7 +6,7 @@ import org.zwobble.couscous.ast.visitors.NodeTransformer;
import java.util.List;
import java.util.Set;
-public class ClassNode implements Node {
+public class ClassNode implements TypeNode {
public static ClassNodeBuilder builder(TypeName name) {
return new ClassNodeBuilder(name);
}
@@ -45,11 +45,13 @@ public class ClassNode implements Node {
this.constructor = constructor;
methods = methodNodes;
}
-
+
+ @Override
public TypeName getName() {
return name;
}
+ @Override
public Set<TypeName> getSuperTypes() {
return superTypes;
}
@@ -65,7 +67,8 @@ public class ClassNode implements Node {
public ConstructorNode getConstructor() {
return constructor;
}
-
+
+ @Override
public List<MethodNode> getMethods() {
return methods;
}
diff --git a/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java b/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java
new file mode 100644
index 0000000..09d2d3a
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java
@@ -0,0 +1,81 @@
+package org.zwobble.couscous.ast;
+
+import org.zwobble.couscous.ast.visitors.NodeMapper;
+
+import java.util.List;
+import java.util.Set;
+
+public class InterfaceNode implements TypeNode {
+ public static InterfaceNode declareInterface(
+ TypeName name,
+ Set<TypeName> superTypes,
+ List<MethodNode> methods)
+ {
+ return new InterfaceNode(name, superTypes, methods);
+ }
+
+ private final TypeName name;
+ private final Set<TypeName> superTypes;
+ private final List<MethodNode> methods;
+
+ private InterfaceNode(
+ TypeName name,
+ Set<TypeName> superTypes,
+ List<MethodNode> methodNodes)
+ {
+ this.name = name;
+ this.superTypes = superTypes;
+ methods = methodNodes;
+ }
+
+ @Override
+ public TypeName getName() {
+ return name;
+ }
+
+ @Override
+ public Set<TypeName> getSuperTypes() {
+ return superTypes;
+ }
+
+ @Override
+ public List<MethodNode> getMethods() {
+ return methods;
+ }
+
+ @Override
+ public <T> T accept(NodeMapper<T> visitor) {
+ // TODO: implement this
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceNode(" +
+ "name=" + name +
+ ", superTypes=" + superTypes +
+ ", methods=" + methods +
+ ')';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InterfaceNode that = (InterfaceNode) o;
+
+ if (!name.equals(that.name)) return false;
+ if (!superTypes.equals(that.superTypes)) return false;
+ return methods.equals(that.methods);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + superTypes.hashCode();
+ result = 31 * result + methods.hashCode();
+ return result;
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/ast/TypeNode.java b/src/main/java/org/zwobble/couscous/ast/TypeNode.java
new file mode 100644
index 0000000..9946267
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/ast/TypeNode.java
@@ -0,0 +1,10 @@
+package org.zwobble.couscous.ast;
+
+import java.util.List;
+import java.util.Set;
+
+public interface TypeNode extends Node {
+ TypeName getName();
+ Set<TypeName> getSuperTypes();
+ List<MethodNode> getMethods();
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java
index 4ae7704..e98a526 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java
@@ -4,7 +4,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;
import org.zwobble.couscous.Backend;
-import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.TypeNode;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -30,7 +30,7 @@ public class CsharpBackend implements Backend {
}
@Override
- public void compile(List<ClassNode> classes) throws IOException {
+ public void compile(List<TypeNode> classes) throws IOException {
Files.write(
directoryPath.resolve("Program.cs"),
Iterables.concat(
@@ -50,7 +50,7 @@ public class CsharpBackend implements Backend {
}
}
- private String compileClass(ClassNode classNode) {
+ private String compileClass(TypeNode classNode) {
return CsharpSerializer.serialize(CsharpCodeGenerator.generateCode(classNode, namespace));
}
}
diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
index 731faeb..096bddd 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
@@ -3,7 +3,7 @@ package org.zwobble.couscous.backends.python;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Resources;
import org.zwobble.couscous.Backend;
-import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.TypeNode;
import java.io.File;
import java.io.IOException;
@@ -33,8 +33,8 @@ public class PythonBackend implements Backend {
}
@Override
- public void compile(List<ClassNode> classes) throws IOException {
- for (ClassNode classNode : classes) {
+ public void compile(List<TypeNode> classes) throws IOException {
+ for (TypeNode classNode : classes) {
compileClass(classNode);
}
for (String runtimeFile : RUNTIME_FILES) {
@@ -53,7 +53,7 @@ public class PythonBackend implements Backend {
return moduleName.replace(".", File.separator) + ".py";
}
- private void compileClass(ClassNode classNode) throws IOException {
+ private void compileClass(TypeNode classNode) throws IOException {
writeModule(
classNode.getName().getQualifiedName(),
serialize(generateCode(classNode)));
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 ef1aca2..2aafcca 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
@@ -38,22 +38,24 @@ import static org.zwobble.couscous.backends.python.ast.PythonWhileNode.pythonWhi
import static org.zwobble.couscous.util.ExtraLists.list;
public class PythonCodeGenerator {
- public static PythonModuleNode generateCode(ClassNode classNode) {
- Iterator<PythonImportNode> imports = generateImports(classNode).iterator();
+ public static PythonModuleNode generateCode(TypeNode typeNode) {
+ ClassNode classNode = (ClassNode) typeNode;
+
+ Iterator<PythonImportNode> imports = generateImports(typeNode).iterator();
PythonImportNode internalsImport = pythonImport(
- importPathToRoot(classNode),
+ importPathToRoot(typeNode),
list(pythonImportAlias("_couscous")));
PythonFunctionDefinitionNode constructor =
generateConstructor(classNode.getConstructor());
Iterable<PythonFunctionDefinitionNode> pythonMethods = transform(
- classNode.getMethods(),
+ typeNode.getMethods(),
PythonCodeGenerator::generateFunction);
PythonClassNode pythonClass = pythonClass(
- classNode.getSimpleName(),
+ typeNode.getName().getSimpleName(),
ImmutableList.copyOf(Iterables.concat(list(constructor), pythonMethods)));
List<PythonStatementNode> staticConstructor =
@@ -66,18 +68,18 @@ public class PythonCodeGenerator {
staticConstructor.iterator())));
}
- private static Stream<PythonImportNode> generateImports(ClassNode classNode) {
+ private static Stream<PythonImportNode> generateImports(TypeNode classNode) {
Set<TypeName> classes = findReferencedClasses(classNode);
return classes.stream()
.filter(name -> !name.equals(InternalCouscousValue.REF))
.map(name -> pythonImport(importPathToRoot(classNode) + name.getQualifiedName(), list(pythonImportAlias(name.getSimpleName()))));
}
- private static String importPathToRoot(ClassNode classNode) {
+ private static String importPathToRoot(TypeNode classNode) {
return Strings.repeat(".", packageDepth(classNode) + 1);
}
- private static int packageDepth(ClassNode classNode) {
+ private static int packageDepth(TypeNode classNode) {
int depth = 0;
final java.lang.String qualifiedName = classNode.getName().getQualifiedName();
for (int index = 0; index < qualifiedName.length(); index++) {
@@ -88,7 +90,7 @@ public class PythonCodeGenerator {
return depth;
}
- private static Set<TypeName> findReferencedClasses(ClassNode classNode) {
+ private static Set<TypeName> findReferencedClasses(TypeNode classNode) {
return NodeStructure.descendantNodes(classNode)
.flatMap(node -> node.accept(new NodeMapperWithDefault<Stream<TypeName>>(Stream.empty()) {
@Override
diff --git a/src/main/java/org/zwobble/couscous/cli/CouscousCli.java b/src/main/java/org/zwobble/couscous/cli/CouscousCli.java
index 561b3f5..8d4fce1 100644
--- a/src/main/java/org/zwobble/couscous/cli/CouscousCli.java
+++ b/src/main/java/org/zwobble/couscous/cli/CouscousCli.java
@@ -3,6 +3,7 @@ package org.zwobble.couscous.cli;
import org.apache.commons.cli.*;
import org.zwobble.couscous.Backend;
import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.TypeNode;
import org.zwobble.couscous.backends.python.PythonBackend;
import org.zwobble.couscous.frontends.java.JavaFrontend;
@@ -25,7 +26,7 @@ public class CouscousCli {
CommandLine arguments = parseArguments(rawArguments);
JavaFrontend frontend = new JavaFrontend();
- List<ClassNode> classNodes = eagerFlatMap(
+ List<TypeNode> classNodes = eagerFlatMap(
arguments.getArgList(),
path -> {
try {
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaFrontend.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaFrontend.java
index 5ab2678..51df264 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaFrontend.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaFrontend.java
@@ -1,10 +1,7 @@
package org.zwobble.couscous.frontends.java;
import com.google.common.collect.Multimaps;
-import org.zwobble.couscous.ast.ClassNode;
-import org.zwobble.couscous.ast.Node;
-import org.zwobble.couscous.ast.VariableDeclaration;
-import org.zwobble.couscous.ast.VariableNode;
+import org.zwobble.couscous.ast.*;
import java.io.IOException;
import java.nio.file.Files;
@@ -20,8 +17,8 @@ import static org.zwobble.couscous.util.ExtraLists.flatMap;
import static org.zwobble.couscous.util.ExtraStreams.toStream;
public class JavaFrontend {
- public List<ClassNode> readSourceDirectory(List<Path> sourcePaths, Path directoryPath) throws IOException {
- List<ClassNode> classNodes = flatMap(
+ public List<TypeNode> readSourceDirectory(List<Path> sourcePaths, Path directoryPath) throws IOException {
+ List<TypeNode> classNodes = flatMap(
findJavaFiles(directoryPath),
javaFile -> JavaReader.readClassFromFile(sourcePaths, javaFile));
ensureDeclarationsAreUnique(classNodes);
@@ -33,7 +30,7 @@ public class JavaFrontend {
.filter(path -> path.toFile().isFile() && path.toString().endsWith(".java"));
}
- private void ensureDeclarationsAreUnique(List<ClassNode> classNodes) {
+ private void ensureDeclarationsAreUnique(List<TypeNode> classNodes) {
List<VariableDeclaration> declarations = eagerFlatMap(classNodes, this::findDeclarations);
Multimaps.index(declarations, VariableDeclaration::getId)
.asMap()
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
index c85b4fb..6e7f3fc 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -37,7 +37,7 @@ import static org.zwobble.couscous.frontends.java.JavaTypes.*;
import static org.zwobble.couscous.util.ExtraLists.*;
public class JavaReader {
- public static List<ClassNode> readClassFromFile(List<Path> sourcePaths, Path sourcePath) throws IOException {
+ public static List<TypeNode> readClassFromFile(List<Path> sourcePaths, Path sourcePath) throws IOException {
CompilationUnit ast = new JavaParser().parseCompilationUnit(sourcePaths, sourcePath);
ImmutableList<IProblem> errors = ImmutableList.copyOf(filter(asList(ast.getProblems()), problem -> problem.isError()));
@@ -58,7 +58,7 @@ public class JavaReader {
error.getMessage();
}
- private final ImmutableList.Builder<ClassNode> classes;
+ private final ImmutableList.Builder<TypeNode> classes;
private int anonymousClassCount = 0;
private JavaReader() {
diff --git a/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java b/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
index bcb4db6..8038ce1 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
@@ -3,6 +3,7 @@ package org.zwobble.couscous.interpreter;
import java.util.List;
import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.TypeNode;
import org.zwobble.couscous.interpreter.values.BoxedIntegerInterpreterValue;
import org.zwobble.couscous.interpreter.values.ConcreteType;
import org.zwobble.couscous.interpreter.values.InternalCouscousInterpreterValue;
@@ -20,7 +21,7 @@ public class JavaProject {
.addClass(BoxedIntegerInterpreterValue.TYPE);
}
- public static Project of(List<ClassNode> classNodes) {
+ public static Project of(List<TypeNode> classNodes) {
Iterable<ConcreteType> concreteTypes = Iterables.transform(classNodes, ConcreteType::fromNode);
return builder()
.addClasses(concreteTypes)
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
index cf48d3c..98036f1 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
@@ -91,13 +91,21 @@ public class ConcreteType {
}
}
- public static ConcreteType fromNode(ClassNode classNode) {
+ public static ConcreteType fromNode(TypeNode typeNode) {
+ ClassNode classNode = (ClassNode)typeNode;
Map<String, FieldDeclarationNode> fields = classNode.getFields().stream()
.collect(toMap(
field -> field.getName(),
field -> field));
- MethodValue constructor = new MethodValue(getArgumentTypes(classNode.getConstructor().getArguments()), (environment, arguments) -> Executor.callMethod(environment, classNode.getConstructor(), Optional.of(arguments.getReceiver()), arguments.getPositionalArguments()));
- Map<MethodSignature, MethodValue> methods = classNode.getMethods()
+ MethodValue constructor = new MethodValue(
+ getArgumentTypes(classNode.getConstructor().getArguments()),
+ (environment, arguments) -> Executor.callMethod(
+ environment,
+ classNode.getConstructor(),
+ Optional.of(arguments.getReceiver()),
+ arguments.getPositionalArguments()));
+
+ Map<MethodSignature, MethodValue> methods = typeNode.getMethods()
.stream()
.filter(method -> !method.isStatic())
.collect(toMap(method -> method.signature(), method -> {
@@ -106,7 +114,7 @@ public class ConcreteType {
return Executor.callMethod(environment, method, Optional.of(arguments.getReceiver()), arguments.getPositionalArguments());
});
}));
- Map<MethodSignature, StaticMethodValue> staticMethods = classNode.getMethods()
+ Map<MethodSignature, StaticMethodValue> staticMethods = typeNode.getMethods()
.stream()
.filter(method -> method.isStatic())
.collect(toMap(method -> method.signature(), method -> {
@@ -116,8 +124,8 @@ public class ConcreteType {
});
}));
return new ConcreteType(
- classNode.getName(),
- classNode.getSuperTypes(),
+ typeNode.getName(),
+ typeNode.getSuperTypes(),
fields,
classNode.getStaticConstructor(),
constructor,