7115046: Add AST node for lambda expressions

Add tree nodes for representing lambda expressions and update relevant visitors interfaces

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2011-11-24 13:36:20 +00:00
parent 469f89911f
commit 41a3a6c5d3
11 changed files with 165 additions and 0 deletions

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.source.tree;
import java.util.List;
/**
* A tree node for a lambda expression.
*
* For example:
* <pre>
* ()->{}
* (List<String> ls)->ls.size()
* (x,y)-> { return x + y; }
* </pre>
*/
public interface LambdaExpressionTree extends ExpressionTree {
/**
* Lambda expressions come in two forms: (i) expression lambdas, whose body
* is an expression, and (ii) statement lambdas, whose body is a block
*/
public enum BodyKind {
/** enum constant for expression lambdas */
EXPRESSION,
/** enum constant for statement lambdas */
STATEMENT;
}
List<? extends VariableTree> getParameters();
Tree getBody();
BodyKind getBodyKind();
}

View File

@ -186,6 +186,11 @@ public interface Tree {
*/
NEW_CLASS(NewClassTree.class),
/**
* Used for instances of {@link LambdaExpressionTree}.
*/
LAMBDA_EXPRESSION(LambdaExpressionTree.class),
/**
* Used for instances of {@link ParenthesizedTree}.
*/

View File

@ -85,6 +85,7 @@ public interface TreeVisitor<R,P> {
R visitModifiers(ModifiersTree node, P p);
R visitNewArray(NewArrayTree node, P p);
R visitNewClass(NewClassTree node, P p);
R visitLambdaExpression(LambdaExpressionTree node, P p);
R visitParenthesized(ParenthesizedTree node, P p);
R visitReturn(ReturnTree node, P p);
R visitMemberSelect(MemberSelectTree node, P p);

View File

@ -172,6 +172,10 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
return defaultAction(node, p);
}
public R visitLambdaExpression(LambdaExpressionTree node, P p) {
return defaultAction(node, p);
}
public R visitParenthesized(ParenthesizedTree node, P p) {
return defaultAction(node, p);
}

View File

@ -285,6 +285,12 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
return r;
}
public R visitLambdaExpression(LambdaExpressionTree node, P p) {
R r = scan(node.getParameters(), p);
r = scanAndReduce(node.getBody(), p, r);
return r;
}
public R visitParenthesized(ParenthesizedTree node, P p) {
return scan(node.getExpression(), p);
}

View File

@ -41,6 +41,7 @@ import com.sun.tools.javac.code.Scope.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.parser.EndPosTable;
import com.sun.source.tree.*;
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
@ -198,6 +199,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
NEWARRAY,
/** Lambda expression, of type Lambda.
*/
LAMBDA,
/** Parenthesized subexpressions, of type Parens.
*/
PARENS,
@ -1486,6 +1491,56 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
/**
* A lambda expression.
*/
public static class JCLambda extends JCExpression implements LambdaExpressionTree {
public List<JCVariableDecl> params;
public JCTree body;
public Type targetType;
public boolean canCompleteNormally = true;
public List<Type> inferredThrownTypes;
public JCLambda(List<JCVariableDecl> params,
JCTree body) {
this.params = params;
this.body = body;
}
@Override
public Tag getTag() {
return LAMBDA;
}
@Override
public void accept(Visitor v) {
v.visitLambda(this);
}
@Override
public <R, D> R accept(TreeVisitor<R, D> v, D d) {
return v.visitLambdaExpression(this, d);
}
public Kind getKind() {
return Kind.LAMBDA_EXPRESSION;
}
public JCTree getBody() {
return body;
}
public java.util.List<? extends VariableTree> getParameters() {
return params;
}
@Override
public JCLambda setType(Type type) {
super.setType(type);
return this;
}
@Override
public BodyKind getBodyKind() {
return body.hasTag(BLOCK) ?
BodyKind.STATEMENT :
BodyKind.EXPRESSION;
}
}
/**
* A parenthesized subexpression ( ... )
*/
@ -2271,6 +2326,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitApply(JCMethodInvocation that) { visitTree(that); }
public void visitNewClass(JCNewClass that) { visitTree(that); }
public void visitNewArray(JCNewArray that) { visitTree(that); }
public void visitLambda(JCLambda that) { visitTree(that); }
public void visitParens(JCParens that) { visitTree(that); }
public void visitAssign(JCAssign that) { visitTree(that); }
public void visitAssignop(JCAssignOp that) { visitTree(that); }

View File

@ -907,6 +907,17 @@ public class Pretty extends JCTree.Visitor {
}
}
public void visitLambda(JCLambda tree) {
try {
print("(");
printExprs(tree.params);
print(")->");
printExpr(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitParens(JCParens tree) {
try {
print("(");

View File

@ -271,6 +271,13 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
return M.at(t.pos).NewClass(encl, typeargs, clazz, args, def);
}
public JCTree visitLambdaExpression(LambdaExpressionTree node, P p) {
JCLambda t = (JCLambda) node;
List<JCVariableDecl> params = copy(t.params, p);
JCTree body = copy(t.body, p);
return M.at(t.pos).Lambda(params, body);
}
public JCTree visitParenthesized(ParenthesizedTree node, P p) {
JCParens t = (JCParens) node;
JCExpression expr = copy(t.expr, p);

View File

@ -351,6 +351,14 @@ public class TreeMaker implements JCTree.Factory {
return tree;
}
public JCLambda Lambda(List<JCVariableDecl> params,
JCTree body)
{
JCLambda tree = new JCLambda(params, body);
tree.pos = pos;
return tree;
}
public JCParens Parens(JCExpression expr) {
JCParens tree = new JCParens(expr);
tree.pos = pos;

View File

@ -212,6 +212,11 @@ public class TreeScanner extends Visitor {
scan(tree.elems);
}
public void visitLambda(JCLambda tree) {
scan(tree.body);
scan(tree.params);
}
public void visitParens(JCParens tree) {
scan(tree.expr);
}

View File

@ -282,6 +282,12 @@ public class TreeTranslator extends JCTree.Visitor {
result = tree;
}
public void visitLambda(JCLambda tree) {
tree.params = translate(tree.params);
tree.body = translate(tree.body);
result = tree;
}
public void visitNewArray(JCNewArray tree) {
tree.elemtype = translate(tree.elemtype);
tree.dims = translate(tree.dims);