diff options
Diffstat (limited to 'src/main/java/org/zwobble')
| -rw-r--r-- | src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java | 37 | ||||
| -rw-r--r-- | src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java | 63 |
2 files changed, 69 insertions, 31 deletions
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<TypeName> superTypes; + private final List<FieldDeclarationNode> fields; + private final List<MethodNode> methods; + + public AnonymousClass( + Set<TypeName> superTypes, + List<FieldDeclarationNode> fields, + List<MethodNode> methods) + { + + this.superTypes = superTypes; + this.fields = fields; + this.methods = methods; + } + + public Set<TypeName> getSuperTypes() { + return superTypes; + } + + public List<FieldDeclarationNode> getFields() { + return fields; + } + + public List<MethodNode> 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<Scope, Lambda> 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<StatementNode> 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<TypeName> superTypes, - List<FieldDeclarationNode> declaredFields, - List<MethodNode> methods + AnonymousClass anonymousClass ) { - List<ReferenceNode> freeVariables = findFreeVariables(ExtraLists.concat(declaredFields, methods)); + List<ReferenceNode> freeVariables = findFreeVariables(ExtraLists.concat( + anonymousClass.getFields(), + anonymousClass.getMethods())); List<CapturedVariable> capturedVariables = ImmutableList.copyOf(transform( freeVariables, freeVariable -> new CapturedVariable(freeVariable, fieldForCapture(freeVariable)))); Iterable<FieldDeclarationNode> captureFields = transform(capturedVariables, capture -> capture.field); - List<FieldDeclarationNode> fields = ImmutableList.copyOf(concat(declaredFields, captureFields)); + List<FieldDeclarationNode> 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); } |
