diff options
Diffstat (limited to 'src/main/java/org')
4 files changed, 32 insertions, 13 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNode.java b/src/main/java/org/zwobble/couscous/ast/ClassNode.java index 322a32a..0d37130 100644 --- a/src/main/java/org/zwobble/couscous/ast/ClassNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ClassNode.java @@ -113,9 +113,12 @@ public class ClassNode implements TypeNode { @Override public Iterable<? extends Node> childNodes() { return Iterables.concat( + typeParameters, + staticConstructor, ExtraIterables.of(constructor), fields, - methods + methods, + innerTypes ); } diff --git a/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java b/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java index 3159d03..6a56a6b 100644 --- a/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java +++ b/src/main/java/org/zwobble/couscous/ast/InterfaceNode.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.ast; +import com.google.common.collect.Iterables; import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.types.ScalarType; import org.zwobble.couscous.types.Type; @@ -91,7 +92,13 @@ public class InterfaceNode implements TypeNode { @Override public Iterable<? extends Node> childNodes() { - return methods; + return Iterables.concat( + typeParameters, + staticConstructor, + fields, + methods, + innerTypes + ); } @Override diff --git a/src/main/java/org/zwobble/couscous/transforms/ClosureGenerator.java b/src/main/java/org/zwobble/couscous/transforms/ClosureGenerator.java index 68c0aa6..8c454d4 100644 --- a/src/main/java/org/zwobble/couscous/transforms/ClosureGenerator.java +++ b/src/main/java/org/zwobble/couscous/transforms/ClosureGenerator.java @@ -29,6 +29,7 @@ import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariable import static org.zwobble.couscous.types.Types.erasure; import static org.zwobble.couscous.util.Casts.tryCast; import static org.zwobble.couscous.util.ExtraIterables.lazyMap; +import static org.zwobble.couscous.util.ExtraIterables.only; import static org.zwobble.couscous.util.ExtraLists.*; public class ClosureGenerator { @@ -40,9 +41,7 @@ public class ClosureGenerator { findFreeTypeParameters(classNode)); InsertionOrderSet<ReferenceNode> freeVariables = InsertionOrderSet.copyOf(Iterables.filter( - findFreeVariables(ExtraLists.concat( - classNode.getFields(), - classNode.getMethods())), + findFreeVariables(ExtraLists.copyOf(classNode.childNodes())), // TODO: check this references work correctly in anonymous classes variable -> !isThisReference(classNode.getName(), variable))); InsertionOrderSet<CapturedVariable> capturedVariables = InsertionOrderSet.copyOf(transform( @@ -58,6 +57,8 @@ public class ClosureGenerator { throw new RuntimeException("Class has unexpected static constructor"); } + NodeTransformer transformer = replaceCaptureReferencesTransformer(classNode.getName(), capturedVariables); + ClassNode generatedClass = new ClassNode( classNode.getName(), // TODO: generate fresh type parameter and replace in body @@ -67,8 +68,9 @@ public class ClosureGenerator { list(), buildConstructor(scope, classNode.getName(), capturedVariables, classNode.getConstructor()), eagerMap(classNode.getMethods(), method -> - method.mapBody(body -> replaceCaptureReferences(classNode.getName(), body, capturedVariables))), - list() + method.mapBody(body -> transformer.transformStatements(body))), + // TODO: should just call replaceCaptureReferences over entire class? + eagerMap(classNode.getInnerTypes(), type -> only(transformer.transformTypeDeclaration(type))) ); return new GeneratedClosure(generatedClass, freeTypeParameters, freeVariables); } @@ -95,16 +97,14 @@ public class ClosureGenerator { }); } - private static List<StatementNode> replaceCaptureReferences( + private static NodeTransformer replaceCaptureReferencesTransformer( ScalarType className, - List<StatementNode> body, InsertionOrderSet<CapturedVariable> freeVariables) { Map<ExpressionNode, ExpressionNode> replacements = Maps.transformValues( Maps.uniqueIndex(freeVariables, variable -> variable.freeVariable), freeVariable -> captureAccess(className, freeVariable)); - NodeTransformer transformer = NodeTransformer.replaceExpressions(replacements); - return eagerFlatMap(body, transformer::transformStatement); + return NodeTransformer.replaceExpressions(replacements); } private static ConstructorNode buildConstructor( diff --git a/src/main/java/org/zwobble/couscous/transforms/HoistNestedTypes.java b/src/main/java/org/zwobble/couscous/transforms/HoistNestedTypes.java index 6c40af9..1cb74c8 100644 --- a/src/main/java/org/zwobble/couscous/transforms/HoistNestedTypes.java +++ b/src/main/java/org/zwobble/couscous/transforms/HoistNestedTypes.java @@ -29,6 +29,17 @@ public class HoistNestedTypes { private final Scope topScope = Scope.create().temporaryPrefix("_couscous_hoist_nested_types"); private List<TypeNode> hoistTypes(List<TypeNode> declarations) { + while (true) { + List<TypeNode> hoisted = hoistInnerTypes(declarations); + if (hoisted.size() == declarations.size()) { + return hoisted; + } else { + declarations = hoisted; + } + } + } + + private List<TypeNode> hoistInnerTypes(List<TypeNode> declarations) { List<HoistResult> hoistResults = eagerMap(declarations, declaration -> hoistInnerTypes(declaration)); Iterable<HoistedType> hoistedTypes = lazyFlatMap(hoistResults, hoisted -> hoisted.hoistedTypes); @@ -126,8 +137,6 @@ public class HoistNestedTypes { } private HoistedType hoistType(TypeNode typeNode) { - // TODO: we need to hoist inner types of the inner types, specifically *after* the initial hoist (to make closures easier to generate) - // TODO: can we remove duplication of scope creation with readTypeDeclaration()? Scope scope = topScope.enterClass(typeNode.getName()); return tryCast(ClassNode.class, typeNode) .flatMap(node -> { |
