From b32887bee01b81c8deebf8f02eac7c4b135b4156 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 8 Jan 2016 09:04:03 +0000 Subject: Add AnonymousClass to remove duplication of closure generation --- .../zwobble/couscous/ast/sugar/AnonymousClass.java | 37 +++++++++++++ .../couscous/frontends/java/JavaReader.java | 63 +++++++++++----------- 2 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java (limited to 'src/main/java') diff --git a/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java b/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java new file mode 100644 index 0000000..fea72be --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java @@ -0,0 +1,37 @@ +package org.zwobble.couscous.ast.sugar; + +import org.zwobble.couscous.ast.FieldDeclarationNode; +import org.zwobble.couscous.ast.MethodNode; +import org.zwobble.couscous.ast.TypeName; + +import java.util.List; +import java.util.Set; + +public class AnonymousClass { + private final Set superTypes; + private final List fields; + private final List methods; + + public AnonymousClass( + Set superTypes, + List fields, + List methods) + { + + this.superTypes = superTypes; + this.fields = fields; + this.methods = methods; + } + + public Set getSuperTypes() { + return superTypes; + } + + public List getFields() { + return fields; + } + + public List getMethods() { + return methods; + } +} 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 6c1f503..5602434 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import org.eclipse.jdt.core.dom.*; import org.zwobble.couscous.ast.*; +import org.zwobble.couscous.ast.sugar.AnonymousClass; import org.zwobble.couscous.ast.sugar.Lambda; import org.zwobble.couscous.util.ExtraLists; @@ -12,7 +13,6 @@ import java.nio.file.Path; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.function.Function; import static com.google.common.collect.Iterables.concat; @@ -62,26 +62,27 @@ public class JavaReader { } GeneratedClosure readExpressionMethodReference(Scope outerScope, ExpressionMethodReference expression) { - TypeName name = generateAnonymousName(expression); - Scope scope = outerScope.enterClass(name); - return generateClosure( - scope, - name, - expression.resolveTypeBinding().getFunctionalInterfaceMethod(), - new JavaExpressionMethodReferenceReader(this).toLambda(scope, expression)); + return readLambda( + outerScope, + expression, + scope -> new JavaExpressionMethodReferenceReader(this).toLambda(scope, expression)); } GeneratedClosure readLambda(Scope outerScope, LambdaExpression expression) { + return readLambda( + outerScope, + expression, + scope -> new JavaLambdaExpressionReader(this).toLambda(scope, expression)); + } + + private GeneratedClosure readLambda(Scope outerScope, Expression expression, Function lambda) { TypeName name = generateAnonymousName(expression); Scope scope = outerScope.enterClass(name); - return generateClosure( - scope, - name, - expression.resolveTypeBinding().getFunctionalInterfaceMethod(), - new JavaLambdaExpressionReader(this).toLambda(scope, expression)); + IMethodBinding functionalInterfaceMethod = expression.resolveTypeBinding().getFunctionalInterfaceMethod(); + return generateClosure(scope, name, toAnonymousClass(functionalInterfaceMethod, lambda.apply(scope))); } - GeneratedClosure generateClosure(Scope scope, TypeName name, IMethodBinding functionalInterfaceMethod, Lambda lambda) { + private AnonymousClass toAnonymousClass(IMethodBinding functionalInterfaceMethod, Lambda lambda) { MethodNode method = MethodNode.method( emptyList(), false, @@ -89,15 +90,10 @@ public class JavaReader { lambda.getFormalArguments(), lambda.getBody()); - GeneratedClosure closure = classWithCapture( - scope, - name, + return new AnonymousClass( superTypesAndSelf(functionalInterfaceMethod.getDeclaringClass()), - emptyList(), + list(), list(method)); - - classes.add(closure.getClassNode()); - return closure; } private List replaceCaptureReferences( @@ -150,12 +146,15 @@ public class JavaReader { TypeName className = generateAnonymousName(declaration); Scope scope = outerScope.enterClass(className); TypeDeclarationBody bodyDeclarations = readTypeDeclarationBody(scope, declaration.bodyDeclarations()); - GeneratedClosure closure = classWithCapture( - scope, - className, + AnonymousClass anonymousClass = new AnonymousClass( superTypes(declaration), bodyDeclarations.getFields(), bodyDeclarations.getMethods()); + return generateClosure(scope, className, anonymousClass); + } + + GeneratedClosure generateClosure(Scope scope, TypeName className, AnonymousClass anonymousClass) { + GeneratedClosure closure = classWithCapture(scope, className, anonymousClass); classes.add(closure.getClassNode()); return closure; } @@ -173,24 +172,26 @@ public class JavaReader { private GeneratedClosure classWithCapture( Scope scope, TypeName className, - Set superTypes, - List declaredFields, - List methods + AnonymousClass anonymousClass ) { - List freeVariables = findFreeVariables(ExtraLists.concat(declaredFields, methods)); + List freeVariables = findFreeVariables(ExtraLists.concat( + anonymousClass.getFields(), + anonymousClass.getMethods())); List capturedVariables = ImmutableList.copyOf(transform( freeVariables, freeVariable -> new CapturedVariable(freeVariable, fieldForCapture(freeVariable)))); Iterable captureFields = transform(capturedVariables, capture -> capture.field); - List fields = ImmutableList.copyOf(concat(declaredFields, captureFields)); + List fields = ImmutableList.copyOf(concat( + anonymousClass.getFields(), + captureFields)); ClassNode classNode = ClassNode.declareClass( className, - superTypes, + anonymousClass.getSuperTypes(), fields, buildConstructor(scope, className, capturedVariables), - eagerMap(methods, method -> + eagerMap(anonymousClass.getMethods(), method -> method.mapBody(body -> replaceCaptureReferences(className, body, capturedVariables)))); return new GeneratedClosure(classNode, freeVariables); } -- cgit v1.2.3