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/frontends/java/FreeVariables.java38
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/GeneratedClosure.java16
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java11
-rw-r--r--src/main/java/org/zwobble/couscous/types/Types.java10
4 files changed, 67 insertions, 8 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/FreeVariables.java b/src/main/java/org/zwobble/couscous/frontends/java/FreeVariables.java
index 00184b1..9e507dc 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/FreeVariables.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/FreeVariables.java
@@ -1,7 +1,10 @@
package org.zwobble.couscous.frontends.java;
import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.types.*;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -12,6 +15,41 @@ import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraStreams.toStream;
public class FreeVariables {
+ public static Set<TypeParameter> findFreeTypeParameters(Node node) {
+ // TODO: this assumes that *all* type parameters are free, which is often but not always true in inner types
+ Set<TypeParameter> freeTypeParameters = new HashSet<>();
+
+ NodeTransformer.builder().transformType(type -> {
+ type.accept(new Type.Visitor<Void>() {
+ @Override
+ public Void visit(ScalarType type) {
+ return null;
+ }
+
+ @Override
+ public Void visit(TypeParameter parameter) {
+ freeTypeParameters.add(parameter);
+ return null;
+ }
+
+ @Override
+ public Void visit(ParameterizedType type) {
+ type.getParameters().forEach(parameter -> parameter.accept(this));
+ return null;
+ }
+
+ @Override
+ public Void visit(BoundTypeParameter type) {
+ type.getValue().accept(this);
+ return null;
+ }
+ });
+ return type;
+ }).build().transform(node);
+
+ return freeTypeParameters;
+ }
+
public static List<ReferenceNode> findFreeVariables(List<? extends Node> body) {
Set<VariableDeclaration> declarations = body.stream()
.flatMap(FreeVariables::findDeclarations)
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/GeneratedClosure.java b/src/main/java/org/zwobble/couscous/frontends/java/GeneratedClosure.java
index b7059e2..9bad1d2 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/GeneratedClosure.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/GeneratedClosure.java
@@ -1,23 +1,28 @@
package org.zwobble.couscous.frontends.java;
+import com.google.common.collect.ImmutableList;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.ast.ConstructorCallNode;
import org.zwobble.couscous.ast.ExpressionNode;
import org.zwobble.couscous.ast.ReferenceNode;
import org.zwobble.couscous.types.ScalarType;
+import org.zwobble.couscous.types.TypeParameter;
import org.zwobble.couscous.util.InsertionOrderSet;
import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall;
+import static org.zwobble.couscous.types.Types.addTypeParameters;
import static org.zwobble.couscous.util.ExtraLists.concat;
import static org.zwobble.couscous.util.ExtraLists.list;
public class GeneratedClosure {
private final ClassNode classNode;
- private final InsertionOrderSet<ReferenceNode> captures;
+ private final InsertionOrderSet<TypeParameter> capturedTypes;
+ private final InsertionOrderSet<ReferenceNode> capturedVariables;
- public GeneratedClosure(ClassNode classNode, InsertionOrderSet<ReferenceNode> captures) {
+ public GeneratedClosure(ClassNode classNode, InsertionOrderSet<TypeParameter> capturedTypes, InsertionOrderSet<ReferenceNode> capturedVariables) {
this.classNode = classNode;
- this.captures = captures;
+ this.capturedTypes = capturedTypes;
+ this.capturedVariables = capturedVariables;
}
public ClassNode getClassNode() {
@@ -30,8 +35,9 @@ public class GeneratedClosure {
public ConstructorCallNode generateConstructor(Iterable<ExpressionNode> arguments) {
return constructorCall(
- getType(),
- concat(captures, arguments));
+ // TODO: tidy up type parameters to avoid copy
+ addTypeParameters(getType(), ImmutableList.copyOf(capturedTypes.asList())),
+ concat(capturedVariables, arguments));
}
private ScalarType getType() {
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 8353dac..e096429 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -11,7 +11,7 @@ import org.zwobble.couscous.ast.sugar.AnonymousClass;
import org.zwobble.couscous.ast.sugar.Lambda;
import org.zwobble.couscous.ast.sugar.TypeDeclarationBody;
import org.zwobble.couscous.ast.visitors.NodeTransformer;
-import org.zwobble.couscous.types.ScalarType;
+import org.zwobble.couscous.types.*;
import org.zwobble.couscous.types.Type;
import org.zwobble.couscous.util.ExtraLists;
import org.zwobble.couscous.util.InsertionOrderSet;
@@ -40,6 +40,7 @@ import static org.zwobble.couscous.ast.ReturnNode.returns;
import static org.zwobble.couscous.ast.StaticReceiver.staticReceiver;
import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference;
import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
+import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeTypeParameters;
import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariables;
import static org.zwobble.couscous.frontends.java.JavaMethods.signature;
import static org.zwobble.couscous.frontends.java.JavaTypes.*;
@@ -257,6 +258,9 @@ public class JavaReader {
Scope scope,
ClassNode classNode
) {
+ InsertionOrderSet<org.zwobble.couscous.types.TypeParameter> freeTypeParameters = InsertionOrderSet.copyOf(
+ findFreeTypeParameters(classNode));
+
InsertionOrderSet<ReferenceNode> freeVariables = InsertionOrderSet.copyOf(Iterables.filter(
findFreeVariables(ExtraLists.concat(
classNode.getFields(),
@@ -278,14 +282,15 @@ public class JavaReader {
ClassNode generatedClass = new ClassNode(
classNode.getName(),
- classNode.getTypeParameters(),
+ // TODO: generate fresh type parameter and replace in body
+ ExtraLists.concat(lazyMap(freeTypeParameters, parameter -> formalTypeParameter(parameter)), classNode.getTypeParameters()),
classNode.getSuperTypes(),
fields,
list(),
buildConstructor(scope, classNode.getName(), capturedVariables, classNode.getConstructor()),
eagerMap(classNode.getMethods(), method ->
method.mapBody(body -> replaceCaptureReferences(classNode.getName(), body, capturedVariables))));
- return new GeneratedClosure(generatedClass, freeVariables);
+ return new GeneratedClosure(generatedClass, freeTypeParameters, freeVariables);
}
private boolean isThisReference(ScalarType name, ReferenceNode reference) {
diff --git a/src/main/java/org/zwobble/couscous/types/Types.java b/src/main/java/org/zwobble/couscous/types/Types.java
index 505d9a7..5338eb3 100644
--- a/src/main/java/org/zwobble/couscous/types/Types.java
+++ b/src/main/java/org/zwobble/couscous/types/Types.java
@@ -1,7 +1,9 @@
package org.zwobble.couscous.types;
+import java.util.List;
import java.util.Map;
+import static org.zwobble.couscous.types.ParameterizedType.parameterizedType;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
import static org.zwobble.couscous.util.ExtraLists.list;
@@ -16,6 +18,14 @@ public class Types {
public static final ScalarType BOXED_BOOLEAN = ScalarType.of("java.lang.Boolean");
public static final ScalarType ARRAY = ScalarType.of("array");
+ public static Type addTypeParameters(ScalarType rawType, List<Type> typeParameters) {
+ if (typeParameters.isEmpty()) {
+ return rawType;
+ } else {
+ return parameterizedType(rawType, typeParameters);
+ }
+ }
+
public static Type array(Type elementType) {
return new ParameterizedType(ARRAY, list(elementType));
}