aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-11-22 10:35:49 +0000
committerMichael Williamson <mike@zwobble.org>2015-11-22 10:35:57 +0000
commit0de2c3171f9ff0466a92ec7fc0271345e966b563 (patch)
tree52a0edb9d27352feefc646af3d3962c62e536aa4 /src
parent2ab857995fd7e38f08004cb361c4161ea0c48022 (diff)
Read lambdas with zero arguments and expression body
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java9
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java49
-rw-r--r--src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java50
3 files changed, 86 insertions, 22 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 e5cbf2d..f1af093 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
@@ -6,6 +6,7 @@ import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.ObjectValues;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -100,6 +101,9 @@ public class JavaExpressionReader {
case ASTNode.CLASS_INSTANCE_CREATION:
return readClassInstanceCreation((ClassInstanceCreation)expression);
+ case ASTNode.LAMBDA_EXPRESSION:
+ return readLambdaExpression((LambdaExpression)expression);
+
case ASTNode.INFIX_EXPRESSION:
return readInfixExpression((InfixExpression)expression);
@@ -198,6 +202,11 @@ public class JavaExpressionReader {
}
}
+ private ExpressionNode readLambdaExpression(LambdaExpression expression) {
+ TypeName anonymousClassName = javaReader.readLambda(expression);
+ return constructorCall(anonymousClassName, Collections.emptyList());
+ }
+
private List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) {
return IntStream.range(0, javaArguments.size())
.mapToObj(index -> readExpression(
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 2395f38..10cc6ec 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -2,16 +2,14 @@ package org.zwobble.couscous.frontends.java;
import com.google.common.collect.ImmutableList;
import org.eclipse.jdt.core.dom.*;
-import org.zwobble.couscous.ast.ClassNode;
-import org.zwobble.couscous.ast.ClassNodeBuilder;
-import org.zwobble.couscous.ast.StatementNode;
-import org.zwobble.couscous.ast.TypeName;
+import org.zwobble.couscous.ast.*;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
+import static org.zwobble.couscous.ast.ReturnNode.returns;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.cons;
import static org.zwobble.couscous.util.ExtraLists.ofType;
@@ -36,6 +34,33 @@ public class JavaReader {
return readTypeDeclarationBody(name, type.bodyDeclarations());
}
+ TypeName readLambda(LambdaExpression expression) {
+ IMethodBinding methodBinding = expression.resolveMethodBinding();
+ IMethodBinding functionalInterfaceMethod = expression.resolveTypeBinding().getFunctionalInterfaceMethod();
+ TypeName returnType = typeOf(functionalInterfaceMethod.getReturnType());
+
+ ClassNodeBuilder classBuilder = new ClassNodeBuilder(generateClassName(expression));
+ classBuilder.method(functionalInterfaceMethod.getName(), method -> {
+ ASTNode body = expression.getBody();
+ if ((body instanceof Expression)) {
+ method.statement(returns(expressionReader().readExpression(
+ returnType,
+ (Expression)body)));
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ return method;
+ });
+
+ ClassNode classNode = classBuilder.build();
+ classes.add(classNode);
+ return classNode.getName();
+ }
+
+ private String generateClassName(LambdaExpression expression) {
+ return generateClassName(expression.resolveMethodBinding().getDeclaringClass());
+ }
+
TypeName readAnonymousClass(AnonymousClassDeclaration declaration) {
String name = generateClassName(declaration);
ClassNode classNode = readTypeDeclarationBody(name, declaration.bodyDeclarations());
@@ -45,6 +70,10 @@ public class JavaReader {
private String generateClassName(AnonymousClassDeclaration declaration) {
ITypeBinding type = declaration.resolveBinding();
+ return generateClassName(type);
+ }
+
+ private String generateClassName(ITypeBinding type) {
while (type.isAnonymous()) {
type = type.getDeclaringClass();
}
@@ -63,20 +92,20 @@ public class JavaReader {
readField(field, classBuilder);
}
}
-
+
private void readField(FieldDeclaration field, ClassNodeBuilder classBuilder) {
for (Object fragment : field.fragments()) {
String name = ((VariableDeclarationFragment)fragment).getName().getIdentifier();
classBuilder.field(name, typeOf(field.getType()));
}
}
-
+
private void readMethods(List<MethodDeclaration> methods, ClassNodeBuilder classBuilder) {
for (MethodDeclaration method : methods) {
readMethod(classBuilder, method);
}
}
-
+
private void readMethod(ClassNodeBuilder classBuilder, MethodDeclaration method) {
if (method.isConstructor()) {
classBuilder.constructor(builder -> buildMethod(method, builder));
@@ -99,7 +128,7 @@ public class JavaReader {
Optional<TypeName> returnType = method.getReturnType2() == null
? Optional.empty()
: Optional.of(typeOf(method.getReturnType2()));
- JavaStatementReader statementReader = new JavaStatementReader(new JavaExpressionReader(this), returnType);
+ JavaStatementReader statementReader = new JavaStatementReader(expressionReader(), returnType);
for (Object statement : method.getBody().statements()) {
for (StatementNode intermediateStatement : statementReader.readStatement((Statement)statement)) {
builder.statement(intermediateStatement);
@@ -112,4 +141,8 @@ public class JavaReader {
TypeDeclaration type = (TypeDeclaration)ast.types().get(0);
return ast.getPackage().getName().getFullyQualifiedName() + "." + type.getName().getFullyQualifiedName();
}
+
+ private JavaExpressionReader expressionReader() {
+ return new JavaExpressionReader(this);
+ }
} \ No newline at end of file
diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
index e09f2af..5fd26c0 100644
--- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
@@ -153,6 +153,19 @@ public class JavaReaderTests {
constructorCall(TypeName.of("java.lang.String"), asList(literal("_"))),
readObjectExpression("new String(\"_\")"));
}
+
+ @Test
+ public void lambdaIsReadAsAnonymousClassCreation() {
+ assertEquals(
+ readClasses(generateMethodSource("void",
+ "java.util.function.Supplier<Integer> supplier = new java.util.function.Supplier<Integer>() {\n" +
+ " public Integer get() {\n" +
+ " return 42;\n" +
+ " }\n" +
+ "};")),
+ readClasses(generateMethodSource("void",
+ "java.util.function.Supplier<Integer> supplier = () -> 42;")));
+ }
@Test
public void argumentIsBoxedIfNecessary() {
@@ -604,21 +617,19 @@ public class JavaReaderTests {
}
private List<StatementNode> readStatements(String returnType, String statementsSource) {
- String javaClass =
- "public static " + returnType + " main() {" +
- statementsSource +
- "}";
-
+ String javaClass = generateMethodSource(returnType, statementsSource);
ClassNode classNode = readClass(javaClass);
return classNode.getMethods().get(0).getBody();
}
private ClassNode readClass(String classBody) {
- String javaClass =
- "package com.example;" +
- "public class Example {" +
- classBody +
- "}";
+ List<ClassNode> classes = readClasses(classBody);
+ assertThat(classes, hasSize(1));
+ return classes.get(0);
+ }
+
+ private List<ClassNode> readClasses(String classBody) {
+ String javaClass = generateClassSource(classBody);
try {
Path directoryPath = Files.createTempDirectory(null);
@@ -626,10 +637,8 @@ public class JavaReaderTests {
try {
Files.createDirectories(directoryPath.resolve("com/example"));
Files.write(sourcePath, asList(javaClass));
-
- List<ClassNode> classes = JavaReader.readClassFromFile(directoryPath, sourcePath);
- assertThat(classes, hasSize(1));
- return classes.get(0);
+
+ return JavaReader.readClassFromFile(directoryPath, sourcePath);
} finally {
deleteRecursively(directoryPath.toFile());
}
@@ -637,4 +646,17 @@ public class JavaReaderTests {
throw new RuntimeException(exception);
}
}
+
+ private String generateMethodSource(String returnType, String statementsSource) {
+ return "public static " + returnType + " main() {" +
+ statementsSource +
+ "}";
+ }
+
+ private String generateClassSource(String classBody) {
+ return "package com.example;" +
+ "public class Example {" +
+ classBody +
+ "}";
+ }
}