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/ast/ClassNodeBuilder.java6
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java18
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java49
3 files changed, 51 insertions, 22 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
index 80e8eab..75aa5a3 100644
--- a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
+++ b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
@@ -22,7 +22,11 @@ public class ClassNodeBuilder {
}
public ClassNodeBuilder field(String name, TypeName type) {
- this.fields.add(FieldDeclarationNode.field(name, type));
+ return field(FieldDeclarationNode.field(name, type));
+ }
+
+ public ClassNodeBuilder field(FieldDeclarationNode field) {
+ this.fields.add(field);
return this;
}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
index 83e321b..c864371 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
@@ -17,6 +17,8 @@ import static org.zwobble.couscous.ast.VariableDeclaration.var;
import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
+import static org.zwobble.couscous.util.ExtraLists.concat;
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
public class JavaExpressionReader {
private final JavaReader javaReader;
@@ -194,8 +196,11 @@ public class JavaExpressionReader {
List<ExpressionNode> arguments = readArguments(constructor, javaArguments);
if (constructor.getDeclaringClass().isAnonymous()) {
- TypeName anonymousClassName = javaReader.readAnonymousClass(expression.getAnonymousClassDeclaration());
- return constructorCall(anonymousClassName, arguments);
+ GeneratedClosure closure =
+ javaReader.readAnonymousClass(expression.getAnonymousClassDeclaration());
+ return constructorCall(
+ closure.getType(),
+ concat(captureArguments(closure), arguments));
} else {
return constructorCall(typeOf(expression), arguments);
}
@@ -205,10 +210,11 @@ public class JavaExpressionReader {
GeneratedClosure closure = javaReader.readLambda(expression);
return constructorCall(
closure.getType(),
- closure.getCaptures()
- .stream()
- .map(VariableReferenceNode::reference)
- .collect(Collectors.toList()));
+ captureArguments(closure));
+ }
+
+ private List<ExpressionNode> captureArguments(GeneratedClosure closure) {
+ return eagerMap(closure.getCaptures(), VariableReferenceNode::reference);
}
private List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) {
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 7d0e902..c8dc854 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -55,16 +55,7 @@ public class JavaReader {
lambda.getFormalArguments().stream(),
lambda.getBody().stream()).collect(Collectors.toList()));
- // TODO: rewrite the AST to reference field directly rather than assigning
- // This is especially bad since we use the same declaration in three places
- // (the original declaration, the captured field, and the local to alias the field)
- List<StatementNode> restoreCaptures = eagerMap(freeVariables, freeVariable ->
- localVariableDeclaration(
- freeVariable,
- fieldAccess(
- thisReference(TypeName.of(className)),
- freeVariable.getName(),
- freeVariable.getType())));
+ List<StatementNode> restoreCaptures = generateCaptureRestoration(className, freeVariables);
MethodNode method = MethodNode.method(
Collections.emptyList(),
@@ -82,6 +73,19 @@ public class JavaReader {
return new GeneratedClosure(classNode.getName(), freeVariables);
}
+ private List<StatementNode> generateCaptureRestoration(String className, List<VariableDeclaration> freeVariables) {
+ // TODO: rewrite the AST to reference field directly rather than assigning
+ // This is especially bad since we use the same declaration in three places
+ // (the original declaration, the captured field, and the local to alias the field)
+ return eagerMap(freeVariables, freeVariable ->
+ localVariableDeclaration(
+ freeVariable,
+ fieldAccess(
+ thisReference(TypeName.of(className)),
+ freeVariable.getName(),
+ freeVariable.getType())));
+ }
+
private ConstructorNode buildConstructor(TypeName type, List<VariableDeclaration> freeVariables) {
// TODO: generate fresh variables for captures
List<FormalArgumentNode> arguments = freeVariables.stream()
@@ -99,11 +103,26 @@ public class JavaReader {
return generateClassName(expression.resolveMethodBinding().getDeclaringClass());
}
- TypeName readAnonymousClass(AnonymousClassDeclaration declaration) {
- String name = generateClassName(declaration);
- ClassNode classNode = readTypeDeclarationBody(name, declaration.bodyDeclarations());
- classes.add(classNode);
- return classNode.getName();
+ GeneratedClosure readAnonymousClass(AnonymousClassDeclaration declaration) {
+ String className = generateClassName(declaration);
+ ClassNode classNode = readTypeDeclarationBody(className, declaration.bodyDeclarations());
+ List<VariableDeclaration> freeVariables = findFreeVariables(asList(classNode));
+ List<StatementNode> restoreCaptures = generateCaptureRestoration(className, freeVariables);
+
+ // TODO: map over methods rather than rebuilding entire class
+ ClassNodeBuilder classBuilder = new ClassNodeBuilder(className);
+ classBuilder.constructor(buildConstructor(TypeName.of(className), freeVariables));
+ classNode.getFields().forEach(classBuilder::field);
+ classNode.getMethods().forEach(method ->
+ classBuilder.method(MethodNode.method(
+ method.getAnnotations(),
+ method.isStatic(),
+ method.getName(),
+ method.getArguments(),
+ concat(restoreCaptures, method.getBody()))));
+
+ classes.add(classBuilder.build());
+ return new GeneratedClosure(classNode.getName(), freeVariables);
}
private String generateClassName(AnonymousClassDeclaration declaration) {