Skip to content

Commit

Permalink
Moves lambda body rewriting from Rewriter into LambdaRewriter. Remove…
Browse files Browse the repository at this point in the history
…s isCapturing field from LambdaExpression.

	Change on 2016/09/14 by kstanger <kstanger@google.com>

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=133143411
  • Loading branch information
kstanger authored and tomball committed Sep 16, 2016
1 parent 1d7b5ae commit 8fa7256
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 51 deletions.
Expand Up @@ -26,7 +26,6 @@ public class LambdaExpression extends FunctionalExpression {
private ChildList<VariableDeclaration> parameters = ChildList.create(VariableDeclaration.class,
this);
protected ChildLink<TreeNode> body = ChildLink.create(TreeNode.class, this);
private boolean isCapturing = false;

public LambdaExpression() {
}
Expand All @@ -35,7 +34,6 @@ public LambdaExpression(LambdaExpression other) {
super(other);
parameters.copyFrom(other.getParameters());
body.copyFrom(other.getBody());
isCapturing = other.isCapturing();
}

@Override
Expand Down Expand Up @@ -80,15 +78,6 @@ public LambdaExpression copy() {
return new LambdaExpression(this);
}

public boolean isCapturing() {
return isCapturing;
}

public LambdaExpression setIsCapturing(boolean isCapturing) {
this.isCapturing = isCapturing;
return this;
}

public LambdaExpression addParameter(VariableDeclaration param) {
parameters.add(param);
return this;
Expand Down
Expand Up @@ -159,7 +159,7 @@ public static void applyMutations(
ticker.tick("ConstantBranchPruner");

// Modify AST to be more compatible with Objective C
new Rewriter(outerResolver).run(unit);
new Rewriter().run(unit);
ticker.tick("Rewriter");

// Add abstract method stubs.
Expand All @@ -173,6 +173,10 @@ public static void applyMutations(
new EnhancedForRewriter().run(unit);
ticker.tick("EnhancedForRewriter");

// Before: Autoboxer - Must generate implementations so autoboxing can be applied to result.
new LambdaRewriter(outerResolver).run(unit);
ticker.tick("LambdaRewriter");

// Add auto-boxing conversions.
new Autoboxer().run(unit);
ticker.tick("Autoboxer");
Expand All @@ -181,9 +185,6 @@ public static void applyMutations(
new AnonymousClassConverter().run(unit);
ticker.tick("AnonymousClassConverter");

new LambdaRewriter().run(unit);
ticker.tick("LambdaRewriter");

new InnerClassExtractor(outerResolver, unit).run(unit);
ticker.tick("InnerClassExtractor");

Expand Down
Expand Up @@ -17,10 +17,13 @@
import com.google.devtools.j2objc.ast.Block;
import com.google.devtools.j2objc.ast.CastExpression;
import com.google.devtools.j2objc.ast.ClassInstanceCreation;
import com.google.devtools.j2objc.ast.Expression;
import com.google.devtools.j2objc.ast.ExpressionStatement;
import com.google.devtools.j2objc.ast.FieldDeclaration;
import com.google.devtools.j2objc.ast.FunctionalExpression;
import com.google.devtools.j2objc.ast.LambdaExpression;
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.ReturnStatement;
import com.google.devtools.j2objc.ast.SimpleName;
import com.google.devtools.j2objc.ast.SingleVariableDeclaration;
import com.google.devtools.j2objc.ast.TreeNode;
Expand All @@ -34,6 +37,7 @@
import com.google.devtools.j2objc.types.GeneratedVariableElement;
import com.google.devtools.j2objc.types.IOSMethodBinding;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.TypeUtil;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
Expand All @@ -48,6 +52,12 @@
*/
public class LambdaRewriter extends TreeVisitor {

private final OuterReferenceResolver outerResolver;

public LambdaRewriter(OuterReferenceResolver outerResolver) {
this.outerResolver = outerResolver;
}

@Override
public void endVisit(LambdaExpression node) {
TypeElement lambdaType = node.getTypeElement();
Expand All @@ -71,8 +81,7 @@ public void endVisit(LambdaExpression node) {
implBinding.setDeclaringClass(BindingConverter.unwrapTypeElement(lambdaType));
implBinding.removeModifiers(java.lang.reflect.Modifier.ABSTRACT);
MethodDeclaration implDecl = new MethodDeclaration(implBinding)
// Rewriter ensures that body is always a Block.
.setBody((Block) TreeUtil.remove(node.getBody()));
.setBody(getLambdaBody(node, fiMethod));
for (VariableDeclaration decl : node.getParameters()) {
implDecl.addParameter(new SingleVariableDeclaration(decl.getVariableElement()));
}
Expand All @@ -86,7 +95,7 @@ public void endVisit(LambdaExpression node) {
creation.setKey(node.getKey());

removeCastExpression(node);
if (node.isCapturing()) {
if (isCapturing(lambdaType)) {
node.replaceWith(creation);
} else {
// For non-capturing lambdas, create a static final instance.
Expand All @@ -98,6 +107,25 @@ public void endVisit(LambdaExpression node) {
}
}

private boolean isCapturing(TypeElement type) {
return outerResolver.getOuterField(type) != null
|| !outerResolver.getInnerFields(type).isEmpty();
}

private Block getLambdaBody(LambdaExpression node, ExecutableElement fiMethod) {
TreeNode body = TreeUtil.remove(node.getBody());
if (body instanceof Block) {
return (Block) body;
}
Block block = new Block();
if (TypeUtil.isVoid(fiMethod.getReturnType())) {
block.addStatement(new ExpressionStatement((Expression) body));
} else {
block.addStatement(new ReturnStatement((Expression) body));
}
return block;
}

private void removeCastExpression(FunctionalExpression node) {
TreeNode parent = node.getParent();
if (parent instanceof CastExpression) {
Expand Down
Expand Up @@ -22,17 +22,14 @@
import com.google.devtools.j2objc.ast.CastExpression;
import com.google.devtools.j2objc.ast.ClassInstanceCreation;
import com.google.devtools.j2objc.ast.Expression;
import com.google.devtools.j2objc.ast.ExpressionStatement;
import com.google.devtools.j2objc.ast.FieldAccess;
import com.google.devtools.j2objc.ast.FieldDeclaration;
import com.google.devtools.j2objc.ast.ForStatement;
import com.google.devtools.j2objc.ast.InfixExpression;
import com.google.devtools.j2objc.ast.LambdaExpression;
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.ParenthesizedExpression;
import com.google.devtools.j2objc.ast.PropertyAnnotation;
import com.google.devtools.j2objc.ast.QualifiedName;
import com.google.devtools.j2objc.ast.ReturnStatement;
import com.google.devtools.j2objc.ast.SimpleName;
import com.google.devtools.j2objc.ast.SingleVariableDeclaration;
import com.google.devtools.j2objc.ast.Statement;
Expand All @@ -56,7 +53,6 @@
import java.util.List;
import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
Expand All @@ -73,12 +69,6 @@
public class Rewriter extends TreeVisitor {

private Map<VariableElement, VariableElement> localRefs = new HashMap<>();
private final OuterReferenceResolver outerResolver;
private Map<ITypeBinding, Integer> lambdaCounts = new HashMap<>();

public Rewriter(OuterReferenceResolver outerResolver) {
this.outerResolver = outerResolver;
}

@Override
public boolean visit(MethodDeclaration node) {
Expand Down Expand Up @@ -339,29 +329,6 @@ private LinkedListMultimap<Integer, VariableDeclarationFragment> rewriteExtraDim
return newDeclarations;
}

@Override
public boolean visit(LambdaExpression node) {
if (!(node.getBody() instanceof Block)) {
// Add explicit blocks for lambdas with expression bodies.
Block block = new Block();
Statement statement;
Expression expression = (Expression) TreeUtil.remove(node.getBody());
if (BindingUtil.isVoid(
node.getTypeBinding().getFunctionalInterfaceMethod().getReturnType())) {
statement = new ExpressionStatement(expression);
} else {
statement = new ReturnStatement(expression);
}
block.addStatement(statement);
node.setBody(block);
}
// Resolve whether a lambda captures variables from the enclosing scope.
TypeElement uniqueLambdaType = node.getTypeElement();
node.setIsCapturing(outerResolver.getOuterField(uniqueLambdaType) != null
|| outerResolver.getInnerFields(uniqueLambdaType).size() != 0);
return true;
}

/**
* Verify, update property attributes. Accessor methods are not checked since a
* property annotation may apply to separate variables in a field declaration, so
Expand Down
Expand Up @@ -45,6 +45,10 @@ public static boolean isEnum(TypeMirror t) {
return getDeclaredTypeKind(t) == ElementKind.ENUM;
}

public static boolean isVoid(TypeMirror t) {
return t.getKind() == TypeKind.VOID;
}

// Ugly, but we can't have it actually implement IntersectionType or return TypeKind.INTERSECTION
// until Java 8.
public static boolean isIntersection(TypeMirror t) {
Expand Down

0 comments on commit 8fa7256

Please sign in to comment.