diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-04-02 12:30:45 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-04-02 12:30:45 +0100 |
| commit | fb062e8c2e7dbdd683bced1782d71983cfd45cc1 (patch) | |
| tree | 538acac4df55196515d9bc7c099fc6d3d62d1fa4 /src | |
| parent | e1903b4a69ce9cd299e0b07f386b84c4473874aa (diff) | |
Add method for creating inner class instances
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java | 34 | ||||
| -rw-r--r-- | src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java | 44 |
2 files changed, 54 insertions, 24 deletions
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 86f044e..0154b1d 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -16,12 +16,15 @@ import static org.zwobble.couscous.ast.ArrayNode.array; import static org.zwobble.couscous.ast.CastNode.cast; import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; import static org.zwobble.couscous.ast.LiteralNode.literal; +import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall; import static org.zwobble.couscous.ast.OperationNode.operation; import static org.zwobble.couscous.ast.Operations.not; +import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference; import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator; import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; +import static org.zwobble.couscous.types.Types.erasure; import static org.zwobble.couscous.util.ExtraLists.*; import static org.zwobble.couscous.util.Fold.foldLeft; @@ -143,7 +146,7 @@ public class JavaExpressionReader { } private ExpressionNode readTypeLiteral(TypeLiteral expression) { - return literal(Types.erasure(typeOf(expression.getType()))); + return literal(erasure(typeOf(expression.getType()))); } private ExpressionNode readSimpleName(SimpleName expression) { @@ -162,8 +165,8 @@ public class JavaExpressionReader { boolean isStatic = Modifier.isStatic(binding.getModifiers()); Type classType = typeOf(binding.getDeclaringClass()); Receiver receiver = isStatic - ? new StaticReceiver(Types.erasure(classType)) - : new InstanceReceiver(ThisReferenceNode.thisReference(classType)); + ? new StaticReceiver(erasure(classType)) + : new InstanceReceiver(thisReference(classType)); return FieldAccessNode.fieldAccess( receiver, binding.getName(), @@ -172,14 +175,14 @@ public class JavaExpressionReader { } private static ExpressionNode readThisExpression(ThisExpression expression) { - return ThisReferenceNode.thisReference(typeOf(expression)); + return thisReference(typeOf(expression)); } private ExpressionNode readFieldAccess(FieldAccess expression) { IVariableBinding fieldBinding = expression.resolveFieldBinding(); boolean isStatic = Modifier.isStatic(fieldBinding.getModifiers()); Receiver receiver = isStatic - ? new StaticReceiver(Types.erasure(typeOf(fieldBinding.getDeclaringClass()))) + ? new StaticReceiver(erasure(typeOf(fieldBinding.getDeclaringClass()))) : new InstanceReceiver(readExpressionWithoutBoxing(expression.getExpression())); return FieldAccessNode.fieldAccess( @@ -207,15 +210,15 @@ public class JavaExpressionReader { Type receiverType = typeOf(methodBinding.getDeclaringClass()); if ((Modifier.isStatic(methodBinding.getModifiers()))) { return staticMethodCall( - Types.erasure(receiverType), + erasure(receiverType), methodName, arguments, signature); } else { ExpressionNode receiver = expression.getExpression() == null - ? ThisReferenceNode.thisReference(receiverType) + ? thisReference(receiverType) : readExpressionWithoutBoxing(expression.getExpression()); - return MethodCallNode.methodCall( + return methodCall( receiver, methodName, arguments, @@ -229,12 +232,25 @@ public class JavaExpressionReader { IMethodBinding constructor = expression.resolveConstructorBinding(); List<ExpressionNode> arguments = readArguments(constructor, javaArguments); - if (constructor.getDeclaringClass().isAnonymous()) { + ITypeBinding declaringClass = constructor.getDeclaringClass(); + if (declaringClass.isAnonymous()) { GeneratedClosure closure = javaReader.readAnonymousClass(scope, expression.getAnonymousClassDeclaration()); return constructorCall( closure.getType(), concat(captureArguments(closure), arguments)); + } else if (declaringClass.isNested() && !Modifier.isStatic(declaringClass.getModifiers())) { + if (expression.getExpression() == null) { + Type type = typeOf(declaringClass); + return methodCall( + thisReference(typeOf(declaringClass.getDeclaringClass())), + // TODO: remove duplication with JavaReader in name generation + "create_" + declaringClass.getName(), + arguments, + type); + } else { + throw new UnsupportedOperationException(); + } } else { return constructorCall(typeOf(expression), arguments); } 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 c63cbb3..82d9d78 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -17,21 +17,26 @@ import org.zwobble.couscous.util.InsertionOrderSet; import java.io.IOException; import java.nio.file.Path; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import static com.google.common.collect.Iterables.concat; -import static com.google.common.collect.Iterables.*; +import static com.google.common.collect.Iterables.transform; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static org.zwobble.couscous.ast.AnnotationNode.annotation; import static org.zwobble.couscous.ast.AssignmentNode.assignStatement; +import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; import static org.zwobble.couscous.ast.ConstructorNode.constructor; import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess; import static org.zwobble.couscous.ast.FieldDeclarationNode.field; import static org.zwobble.couscous.ast.FormalTypeParameterNode.formalTypeParameter; import static org.zwobble.couscous.ast.InstanceReceiver.instanceReceiver; +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; @@ -40,8 +45,8 @@ import static org.zwobble.couscous.frontends.java.JavaMethods.signature; import static org.zwobble.couscous.frontends.java.JavaTypes.*; 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.ExtraLists.*; -import static org.zwobble.couscous.util.ExtraMaps.lookup; public class JavaReader { public static List<TypeNode> readClassesFromFiles(List<Path> sourcePaths, List<Path> sourceFiles) throws IOException { @@ -72,7 +77,6 @@ public class JavaReader { private final ImmutableList.Builder<TypeNode> classes; private int anonymousClassCount = 0; private final Scope topScope = Scope.create(); - private final Map<ScalarType, InsertionOrderSet<ReferenceNode>> nestedClasses = new HashMap<>(); private JavaReader() { classes = ImmutableList.builder(); @@ -84,14 +88,7 @@ public class JavaReader { } private List<TypeNode> types() { - List<TypeNode> classes = this.classes.build(); - NodeTransformer transformer = NodeTransformer.builder() - .transformExpression(expression -> - tryCast(ConstructorCallNode.class, expression) - .flatMap(call -> lookup(nestedClasses, erasure(call.getType())).map(captures -> - new ConstructorCallNode(call.getType(), ExtraLists.concat(captures, call.getArguments()))))) - .build(); - return eagerMap(classes, classNode -> classNode.transform(transformer)); + return this.classes.build(); } private TypeNode readTypeDeclaration(TypeDeclaration type) { @@ -336,12 +333,12 @@ public class JavaReader { .ifPresent(field -> readField(body, scope, type, field)); tryCast(TypeDeclaration.class, declaration) - .ifPresent(typeDeclaration -> classes.add(readNestedTypeDeclaration(typeDeclaration))); + .ifPresent(typeDeclaration -> classes.add(readNestedTypeDeclaration(body, typeDeclaration))); } return body.build(); } - private TypeNode readNestedTypeDeclaration(TypeDeclaration typeDeclaration) { + private TypeNode readNestedTypeDeclaration(TypeDeclarationBody.Builder body, TypeDeclaration typeDeclaration) { TypeNode typeNode = readTypeDeclaration(typeDeclaration); // TODO: can we remove duplication of scope creation with readTypeDeclaration()? Scope scope = topScope.enterClass(typeNode.getName()); @@ -349,7 +346,24 @@ public class JavaReader { .filter(node -> !Modifier.isStatic(typeDeclaration.getModifiers())) .<TypeNode>map(node -> { GeneratedClosure closure = classWithCapture(scope, node); - nestedClasses.put(node.getName(), closure.getCaptures()); +// Type type = node.getTypeParameters().isEmpty() +// ? typeNode.getName() +// : parameterizedType(typeNode.getName(), eagerMap(node.getTypeParameters())); + Type type = typeNode.getName(); + // TODO: method type parameters + List<FormalArgumentNode> methodArguments = eagerMap( + node.getConstructor().getArguments(), + // TODO: use scope of outer class + argument -> scope.formalArgument(argument.getName(), argument.getType())); + List<ExpressionNode> constructorArguments = ExtraLists.concat( + closure.getCaptures(), + lazyMap(methodArguments, argument -> reference(argument))); + MethodNode method = MethodNode.builder("create_" + typeDeclaration.getName().getIdentifier()) + .arguments(methodArguments) + .returns(type) + .statement(returns(constructorCall(type, constructorArguments))) + .build(); + body.addMethod(method); return closure.getClassNode(); }) .orElse(typeNode); |
