def case working

This commit is contained in:
Robert Muir 2016-06-11 15:02:21 -04:00
parent 876f0a613e
commit 592042601f
4 changed files with 36 additions and 6 deletions

View File

@ -29,7 +29,6 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@ -321,14 +320,26 @@ public final class Def {
String call, Class<?>... captures) throws LambdaConversionException {
final FunctionRef ref;
if ("this".equals(type)) {
// user written method
Method interfaceMethod = clazz.struct.getFunctionalMethod();
if (interfaceMethod == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
"to [" + clazz.name + "], not a functional interface");
}
int arity = interfaceMethod.arguments.size();
// user written method
ref = null;
int arity = interfaceMethod.arguments.size() + captures.length;
final MethodHandle handle;
try {
MethodHandle accessor = lookup.findStaticGetter(lookup.lookupClass(),
"handle$" + call + "$" + arity,
MethodHandle.class);
handle = (MethodHandle) accessor.invokeExact();
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalArgumentException("Unknown call [" + call + "] with [" + arity + "] arguments.");
} catch (Throwable t) {
rethrow(t);
throw new AssertionError();
}
ref = new FunctionRef(clazz, interfaceMethod, handle, captures);
} else {
// whitelist lookup
ref = new FunctionRef(clazz, type, call, captures);

View File

@ -101,6 +101,27 @@ public class FunctionRef {
samMethodType = impl.getMethodType().dropParameterTypes(0, captures.length);
}
/**
* Creates a new FunctionRef (low level).
* <p>
* This will <b>not</b> set implMethodASM. It is for runtime use only.
*/
public FunctionRef(Definition.Type expected, Definition.Method method, MethodHandle impl, Class<?>... captures) {
// e.g. compareTo
invokedName = method.name;
// e.g. (Object)Comparator
invokedType = MethodType.methodType(expected.clazz, captures);
// e.g. (Object,Object)int
interfaceMethodType = method.getMethodType().dropParameterTypes(0, 1);
implMethod = impl;
implMethodASM = null;
// remove any prepended captured arguments for the 'natural' signature.
samMethodType = impl.type().dropParameterTypes(0, captures.length);
}
/**
* Looks up {@code type::call} from the whitelist, and returns a matching method.
*/

View File

@ -31,7 +31,6 @@ import org.objectweb.asm.Type;
import static org.elasticsearch.painless.WriterConstants.LAMBDA_BOOTSTRAP_HANDLE;
import java.lang.invoke.LambdaMetafactory;
import java.lang.reflect.Modifier;
/**
* Represents a function reference.

View File

@ -114,7 +114,6 @@ public class FunctionRefTests extends ScriptTestCase {
"List l = new ArrayList(); l.add(2); l.add(1); l.sort(this::mycompare); return l.get(0);"));
}
@AwaitsFix(bugUrl = "working on it")
public void testOwnStaticMethodReferenceDef() {
assertEquals(2, exec("int mycompare(int i, int j) { j - i } " +
"def l = new ArrayList(); l.add(2); l.add(1); l.sort(this::mycompare); return l.get(0);"));