This commit is contained in:
Robert Muir 2016-06-20 08:24:41 -04:00
parent cd1a7b441c
commit 9111ed3e2c
2 changed files with 41 additions and 0 deletions

View File

@ -41,6 +41,29 @@ import java.util.Set;
import static org.elasticsearch.painless.WriterConstants.LAMBDA_BOOTSTRAP_HANDLE; import static org.elasticsearch.painless.WriterConstants.LAMBDA_BOOTSTRAP_HANDLE;
/**
* Lambda expression node.
* <p>
* This can currently only be the direct argument of a call (method/constructor).
* When the argument is of a known type, it uses
* <a href="http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html">
* Java's lambda translation</a>. However, if its a def call, then we don't have
* enough information, and have to defer this until link time. In that case a placeholder
* and all captures are pushed onto the stack and folded into the signature of the parent call.
* <p>
* For example:
* <br>
* {@code def list = new ArrayList(); int capture = 0; list.sort((x,y) -> x - y + capture)}
* <br>
* is converted into a call (pseudocode) such as:
* <br>
* {@code sort(list, lambda$0, capture)}
* <br>
* At link time, when we know the interface type, this is decomposed with MethodHandle
* combinators back into (pseudocode):
* <br>
* {@code sort(list, lambda$0(capture))}
*/
public class ELambda extends AExpression implements ILambda { public class ELambda extends AExpression implements ILambda {
final String name; final String name;
final FunctionReserved reserved; final FunctionReserved reserved;

View File

@ -85,6 +85,24 @@ public class LambdaTests extends ScriptTestCase {
public void testUnneededCurlyStatements() { public void testUnneededCurlyStatements() {
assertEquals(2, exec("int applyOne(IntFunction arg) { arg.apply(1) } applyOne(x -> { x + 1 })")); assertEquals(2, exec("int applyOne(IntFunction arg) { arg.apply(1) } applyOne(x -> { x + 1 })"));
} }
/** interface ignores return value */
public void testVoidReturn() {
assertEquals(2, exec("List list = new ArrayList(); "
+ "list.add(2); "
+ "List list2 = new ArrayList(); "
+ "list.forEach(x -> list2.add(x));"
+ "return list[0]"));
}
/** interface ignores return value */
public void testVoidReturnDef() {
assertEquals(2, exec("def list = new ArrayList(); "
+ "list.add(2); "
+ "List list2 = new ArrayList(); "
+ "list.forEach(x -> list2.add(x));"
+ "return list[0]"));
}
public void testTwoLambdas() { public void testTwoLambdas() {
assertEquals("testingcdefg", exec( assertEquals("testingcdefg", exec(