Merge pull request #18748 from rmuir/painless_method_references
painless: method reference support
This commit is contained in:
commit
90f2aab9a9
|
@ -92,3 +92,8 @@ org.joda.time.DateTime#<init>(int, int, int, int, int, int)
|
|||
org.joda.time.DateTime#<init>(int, int, int, int, int, int, int)
|
||||
org.joda.time.DateTime#now()
|
||||
org.joda.time.DateTimeZone#getDefault()
|
||||
|
||||
@defaultMessage Don't use MethodHandles in slow ways, except in tests.
|
||||
java.lang.invoke.MethodHandle#invoke(java.lang.Object[])
|
||||
java.lang.invoke.MethodHandle#invokeWithArguments(java.lang.Object[])
|
||||
java.lang.invoke.MethodHandle#invokeWithArguments(java.util.List)
|
||||
|
|
|
@ -74,7 +74,7 @@ decltype
|
|||
;
|
||||
|
||||
funcref
|
||||
: TYPE REF ID
|
||||
: TYPE REF ( ID | NEW )
|
||||
;
|
||||
|
||||
declvar
|
||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.painless;
|
|||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.node.ANode;
|
||||
|
||||
/**
|
||||
* Used during the analysis phase to collect legal type casts and promotions
|
||||
|
|
|
@ -22,6 +22,9 @@ package org.elasticsearch.painless;
|
|||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.RuntimeClass;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.LambdaConversionException;
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
|
@ -155,7 +158,52 @@ public final class Def {
|
|||
}
|
||||
|
||||
/**
|
||||
* Looks up handle for a dynamic method call.
|
||||
* Looks up method entry for a dynamic method call.
|
||||
* <p>
|
||||
* A dynamic method call for variable {@code x} of type {@code def} looks like:
|
||||
* {@code x.method(args...)}
|
||||
* <p>
|
||||
* This method traverses {@code recieverClass}'s class hierarchy (including interfaces)
|
||||
* until it finds a matching whitelisted method. If one is not found, it throws an exception.
|
||||
* Otherwise it returns the matching method.
|
||||
* <p>
|
||||
* @param receiverClass Class of the object to invoke the method on.
|
||||
* @param name Name of the method.
|
||||
* @param arity arity of method
|
||||
* @return matching method to invoke. never returns null.
|
||||
* @throws IllegalArgumentException if no matching whitelisted method was found.
|
||||
*/
|
||||
static Method lookupMethodInternal(Class<?> receiverClass, String name, int arity) {
|
||||
Definition.MethodKey key = new Definition.MethodKey(name, arity);
|
||||
// check whitelist for matching method
|
||||
for (Class<?> clazz = receiverClass; clazz != null; clazz = clazz.getSuperclass()) {
|
||||
RuntimeClass struct = Definition.getRuntimeClass(clazz);
|
||||
|
||||
if (struct != null) {
|
||||
Method method = struct.methods.get(key);
|
||||
if (method != null) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
for (Class<?> iface : clazz.getInterfaces()) {
|
||||
struct = Definition.getRuntimeClass(iface);
|
||||
|
||||
if (struct != null) {
|
||||
Method method = struct.methods.get(key);
|
||||
if (method != null) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unable to find dynamic method [" + name + "] with [" + arity + "] arguments " +
|
||||
"for class [" + receiverClass.getCanonicalName() + "].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up handle for a dynamic method call, with lambda replacement
|
||||
* <p>
|
||||
* A dynamic method call for variable {@code x} of type {@code def} looks like:
|
||||
* {@code x.method(args...)}
|
||||
|
@ -166,41 +214,62 @@ public final class Def {
|
|||
* <p>
|
||||
* @param receiverClass Class of the object to invoke the method on.
|
||||
* @param name Name of the method.
|
||||
* @param type Callsite signature. Need not match exactly, except the number of parameters.
|
||||
* @param args args passed to callsite
|
||||
* @param recipe bitset marking functional parameters
|
||||
* @return pointer to matching method to invoke. never returns null.
|
||||
* @throws LambdaConversionException if a method reference cannot be converted to an functional interface
|
||||
* @throws IllegalArgumentException if no matching whitelisted method was found.
|
||||
*/
|
||||
static MethodHandle lookupMethod(Class<?> receiverClass, String name, MethodType type) {
|
||||
// we don't consider receiver an argument/counting towards arity
|
||||
type = type.dropParameterTypes(0, 1);
|
||||
Definition.MethodKey key = new Definition.MethodKey(name, type.parameterCount());
|
||||
// check whitelist for matching method
|
||||
for (Class<?> clazz = receiverClass; clazz != null; clazz = clazz.getSuperclass()) {
|
||||
RuntimeClass struct = Definition.getRuntimeClass(clazz);
|
||||
static MethodHandle lookupMethod(Lookup lookup, Class<?> receiverClass, String name,
|
||||
Object args[], long recipe) throws LambdaConversionException {
|
||||
Method method = lookupMethodInternal(receiverClass, name, args.length - 1);
|
||||
MethodHandle handle = method.handle;
|
||||
|
||||
if (struct != null) {
|
||||
Method method = struct.methods.get(key);
|
||||
if (method != null) {
|
||||
return method.handle;
|
||||
}
|
||||
}
|
||||
|
||||
for (final Class<?> iface : clazz.getInterfaces()) {
|
||||
struct = Definition.getRuntimeClass(iface);
|
||||
|
||||
if (struct != null) {
|
||||
Method method = struct.methods.get(key);
|
||||
if (method != null) {
|
||||
return method.handle;
|
||||
}
|
||||
if (recipe != 0) {
|
||||
MethodHandle filters[] = new MethodHandle[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
// its a functional reference, replace the argument with an impl
|
||||
if ((recipe & (1L << (i - 1))) != 0) {
|
||||
filters[i] = lookupReference(lookup, method.arguments.get(i - 1), (String) args[i]);
|
||||
}
|
||||
}
|
||||
handle = MethodHandles.filterArguments(handle, 0, filters);
|
||||
}
|
||||
|
||||
// no matching methods in whitelist found
|
||||
throw new IllegalArgumentException("Unable to find dynamic method [" + name + "] with signature [" + type + "] " +
|
||||
"for class [" + receiverClass.getCanonicalName() + "].");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/** Returns a method handle to an implementation of clazz, given method reference signature
|
||||
* @throws LambdaConversionException if a method reference cannot be converted to an functional interface
|
||||
*/
|
||||
private static MethodHandle lookupReference(Lookup lookup, Definition.Type clazz, String signature) throws LambdaConversionException {
|
||||
int separator = signature.indexOf('.');
|
||||
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
|
||||
final CallSite callSite;
|
||||
if (ref.needsBridges()) {
|
||||
callSite = LambdaMetafactory.altMetafactory(lookup,
|
||||
ref.invokedName,
|
||||
ref.invokedType,
|
||||
ref.samMethodType,
|
||||
ref.implMethod,
|
||||
ref.samMethodType,
|
||||
LambdaMetafactory.FLAG_BRIDGES,
|
||||
1,
|
||||
ref.interfaceMethodType);
|
||||
} else {
|
||||
callSite = LambdaMetafactory.altMetafactory(lookup,
|
||||
ref.invokedName,
|
||||
ref.invokedType,
|
||||
ref.samMethodType,
|
||||
ref.implMethod,
|
||||
ref.samMethodType,
|
||||
0);
|
||||
}
|
||||
// we could actually invoke and cache here (in non-capturing cases), but this is not a speedup.
|
||||
MethodHandle factory = callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz));
|
||||
return MethodHandles.dropArguments(factory, 0, Object.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks up handle for a dynamic field getter (field load)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.elasticsearch.painless;
|
||||
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
|
@ -66,14 +68,20 @@ public final class DefBootstrap {
|
|||
/** maximum number of types before we go megamorphic */
|
||||
static final int MAX_DEPTH = 5;
|
||||
|
||||
private final Lookup lookup;
|
||||
private final String name;
|
||||
private final int flavor;
|
||||
private final long recipe;
|
||||
int depth; // pkg-protected for testing
|
||||
|
||||
PIC(String name, MethodType type, int flavor) {
|
||||
PIC(Lookup lookup, String name, MethodType type, int flavor, long recipe) {
|
||||
super(type);
|
||||
this.lookup = lookup;
|
||||
this.name = name;
|
||||
this.flavor = flavor;
|
||||
this.recipe = recipe;
|
||||
assert recipe == 0 || flavor == METHOD_CALL;
|
||||
assert Long.bitCount(recipe) <= type.parameterCount();
|
||||
|
||||
final MethodHandle fallback = FALLBACK.bindTo(this)
|
||||
.asCollector(Object[].class, type.parameterCount())
|
||||
|
@ -93,10 +101,10 @@ public final class DefBootstrap {
|
|||
/**
|
||||
* Does a slow lookup against the whitelist.
|
||||
*/
|
||||
private static MethodHandle lookup(int flavor, Class<?> clazz, String name, MethodType type) {
|
||||
private MethodHandle lookup(int flavor, Class<?> clazz, String name, Object[] args, long recipe) throws Throwable {
|
||||
switch(flavor) {
|
||||
case METHOD_CALL:
|
||||
return Def.lookupMethod(clazz, name, type);
|
||||
return Def.lookupMethod(lookup, clazz, name, args, recipe);
|
||||
case LOAD:
|
||||
return Def.lookupGetter(clazz, name);
|
||||
case STORE:
|
||||
|
@ -115,11 +123,12 @@ public final class DefBootstrap {
|
|||
* Called when a new type is encountered (or, when we have encountered more than {@code MAX_DEPTH}
|
||||
* types at this call site and given up on caching).
|
||||
*/
|
||||
@SuppressForbidden(reason = "slow path")
|
||||
Object fallback(Object[] args) throws Throwable {
|
||||
final MethodType type = type();
|
||||
final Object receiver = args[0];
|
||||
final Class<?> receiverClass = receiver.getClass();
|
||||
final MethodHandle target = lookup(flavor, receiverClass, name, type).asType(type);
|
||||
final MethodHandle target = lookup(flavor, receiverClass, name, args, recipe).asType(type);
|
||||
|
||||
if (depth >= MAX_DEPTH) {
|
||||
// revert to a vtable call
|
||||
|
@ -161,8 +170,8 @@ public final class DefBootstrap {
|
|||
* <p>
|
||||
* see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokedynamic
|
||||
*/
|
||||
public static CallSite bootstrap(Lookup lookup, String name, MethodType type, int flavor) {
|
||||
return new PIC(name, type, flavor);
|
||||
public static CallSite bootstrap(Lookup lookup, String name, MethodType type, int flavor, long recipe) {
|
||||
return new PIC(lookup, name, type, flavor, recipe);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,18 +19,24 @@
|
|||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterator;
|
||||
|
||||
/**
|
||||
* The entire API for Painless. Also used as a whitelist for checking for legal
|
||||
|
@ -171,21 +177,6 @@ public final class Definition {
|
|||
}
|
||||
}
|
||||
|
||||
public static final class Constructor {
|
||||
public final String name;
|
||||
public final Struct owner;
|
||||
public final List<Type> arguments;
|
||||
public final org.objectweb.asm.commons.Method method;
|
||||
|
||||
private Constructor(String name, Struct owner, List<Type> arguments,
|
||||
org.objectweb.asm.commons.Method method) {
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
this.arguments = Collections.unmodifiableList(arguments);
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Method {
|
||||
public final String name;
|
||||
public final Struct owner;
|
||||
|
@ -287,12 +278,14 @@ public final class Definition {
|
|||
public final Class<?> clazz;
|
||||
public final org.objectweb.asm.Type type;
|
||||
|
||||
public final Map<MethodKey, Constructor> constructors;
|
||||
public final Map<MethodKey, Method> constructors;
|
||||
public final Map<MethodKey, Method> staticMethods;
|
||||
public final Map<MethodKey, Method> methods;
|
||||
|
||||
public final Map<String, Field> staticMembers;
|
||||
public final Map<String, Field> members;
|
||||
|
||||
private final SetOnce<Method> functionalMethod;
|
||||
|
||||
private Struct(final String name, final Class<?> clazz, final org.objectweb.asm.Type type) {
|
||||
this.name = name;
|
||||
|
@ -305,6 +298,8 @@ public final class Definition {
|
|||
|
||||
staticMembers = new HashMap<>();
|
||||
members = new HashMap<>();
|
||||
|
||||
functionalMethod = new SetOnce<Method>();
|
||||
}
|
||||
|
||||
private Struct(final Struct struct) {
|
||||
|
@ -318,6 +313,8 @@ public final class Definition {
|
|||
|
||||
staticMembers = Collections.unmodifiableMap(struct.staticMembers);
|
||||
members = Collections.unmodifiableMap(struct.members);
|
||||
|
||||
functionalMethod = struct.functionalMethod;
|
||||
}
|
||||
|
||||
private Struct freeze() {
|
||||
|
@ -343,6 +340,14 @@ public final class Definition {
|
|||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this class is a functional interface according to JLS, returns its method.
|
||||
* Otherwise returns null.
|
||||
*/
|
||||
public Method getFunctionalMethod() {
|
||||
return functionalMethod.get();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Cast {
|
||||
|
@ -439,6 +444,23 @@ public final class Definition {
|
|||
for (Map.Entry<String,List<String>> clazz : hierarchy.entrySet()) {
|
||||
copyStruct(clazz.getKey(), clazz.getValue());
|
||||
}
|
||||
// if someone declares an interface type, its still an Object
|
||||
for (Map.Entry<String,Struct> clazz : structsMap.entrySet()) {
|
||||
String name = clazz.getKey();
|
||||
Class<?> javaPeer = clazz.getValue().clazz;
|
||||
if (javaPeer.isInterface()) {
|
||||
copyStruct(name, Collections.singletonList("Object"));
|
||||
} else if (name.equals("def") == false && name.equals("Object") == false && javaPeer.isPrimitive() == false) {
|
||||
// but otherwise, unless its a primitive type, it really should
|
||||
assert hierarchy.get(name) != null : "class '" + name + "' does not extend Object!";
|
||||
assert hierarchy.get(name).contains("Object") : "class '" + name + "' does not extend Object!";
|
||||
}
|
||||
}
|
||||
// mark functional interfaces (or set null, to mark class is not)
|
||||
for (Struct clazz : structsMap.values()) {
|
||||
clazz.functionalMethod.set(computeFunctionalInterfaceMethod(clazz));
|
||||
}
|
||||
|
||||
// precompute runtime classes
|
||||
for (Struct struct : structsMap.values()) {
|
||||
addRuntimeClass(struct);
|
||||
|
@ -573,7 +595,7 @@ public final class Definition {
|
|||
"Owner struct [" + struct + "] not defined for constructor [" + name + "].");
|
||||
}
|
||||
|
||||
if (!name.matches("^[_a-zA-Z][_a-zA-Z0-9]*$")) {
|
||||
if (!name.matches("<init>")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid constructor name [" + name + "] with the struct [" + owner.name + "].");
|
||||
}
|
||||
|
@ -611,7 +633,18 @@ public final class Definition {
|
|||
}
|
||||
|
||||
final org.objectweb.asm.commons.Method asm = org.objectweb.asm.commons.Method.getMethod(reflect);
|
||||
final Constructor constructor = new Constructor(name, owner, Arrays.asList(args), asm);
|
||||
final Type returnType = getTypeInternal("void");
|
||||
final MethodHandle handle;
|
||||
|
||||
try {
|
||||
handle = MethodHandles.publicLookup().in(owner.clazz).unreflectConstructor(reflect);
|
||||
} catch (final IllegalAccessException exception) {
|
||||
throw new IllegalArgumentException("Constructor " +
|
||||
" not found for class [" + owner.clazz.getName() + "]" +
|
||||
" with arguments " + Arrays.toString(classes) + ".");
|
||||
}
|
||||
|
||||
final Method constructor = new Method(name, owner, returnType, Arrays.asList(args), asm, reflect.getModifiers(), handle);
|
||||
|
||||
owner.constructors.put(methodKey, constructor);
|
||||
}
|
||||
|
@ -653,7 +686,7 @@ public final class Definition {
|
|||
if (!elements[0].equals(className)) {
|
||||
throw new IllegalArgumentException("Constructors must return their own type");
|
||||
}
|
||||
addConstructorInternal(className, "new", args);
|
||||
addConstructorInternal(className, "<init>", args);
|
||||
} else {
|
||||
if (methodName.indexOf('/') >= 0) {
|
||||
String nameAndAlias[] = methodName.split("/");
|
||||
|
@ -720,7 +753,7 @@ public final class Definition {
|
|||
" method [" + name + "]" +
|
||||
" within the struct [" + owner.name + "].");
|
||||
}
|
||||
|
||||
|
||||
final org.objectweb.asm.commons.Method asm = org.objectweb.asm.commons.Method.getMethod(reflect);
|
||||
|
||||
MethodHandle handle;
|
||||
|
@ -821,11 +854,37 @@ public final class Definition {
|
|||
throw new ClassCastException("Child struct [" + child.name + "]" +
|
||||
" is not a super type of owner struct [" + owner.name + "] in copy.");
|
||||
}
|
||||
|
||||
|
||||
for (Map.Entry<MethodKey,Method> kvPair : child.methods.entrySet()) {
|
||||
MethodKey methodKey = kvPair.getKey();
|
||||
Method method = kvPair.getValue();
|
||||
if (owner.methods.get(methodKey) == null) {
|
||||
// sanity check, look for missing covariant/generic override
|
||||
if (owner.clazz.isInterface() && child.clazz == Object.class) {
|
||||
// ok
|
||||
} else if (child.clazz == Spliterator.OfPrimitive.class || child.clazz == PrimitiveIterator.class) {
|
||||
// ok, we rely on generics erasure for these (its guaranteed in the javadocs though!!!!)
|
||||
} else {
|
||||
try {
|
||||
Class<?> arguments[] = new Class<?>[method.arguments.size()];
|
||||
for (int i = 0; i < method.arguments.size(); i++) {
|
||||
arguments[i] = method.arguments.get(i).clazz;
|
||||
}
|
||||
java.lang.reflect.Method m = owner.clazz.getMethod(method.method.getName(), arguments);
|
||||
if (m.getReturnType() != method.rtn.clazz) {
|
||||
throw new IllegalStateException("missing covariant override for: " + m + " in " + owner.name);
|
||||
}
|
||||
if (m.isBridge() && !Modifier.isVolatile(method.modifiers)) {
|
||||
// its a bridge in the destination, but not in the source, but it might still be ok, check generics:
|
||||
java.lang.reflect.Method source = child.clazz.getMethod(method.method.getName(), arguments);
|
||||
if (!Arrays.equals(source.getGenericParameterTypes(), source.getParameterTypes())) {
|
||||
throw new IllegalStateException("missing generic override for: " + m + " in " + owner.name);
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
owner.methods.put(methodKey,
|
||||
new Method(method.name, owner, method.rtn, method.arguments, method.method, method.modifiers, method.handle));
|
||||
}
|
||||
|
@ -890,6 +949,50 @@ public final class Definition {
|
|||
|
||||
runtimeMap.put(struct.clazz, new RuntimeClass(methods, getters, setters));
|
||||
}
|
||||
|
||||
/** computes the functional interface method for a class, or returns null */
|
||||
private Method computeFunctionalInterfaceMethod(Struct clazz) {
|
||||
if (!clazz.clazz.isInterface()) {
|
||||
return null;
|
||||
}
|
||||
// if its marked with this annotation, we fail if the conditions don't hold (means whitelist bug)
|
||||
// otherwise, this annotation is pretty useless.
|
||||
boolean hasAnnotation = clazz.clazz.isAnnotationPresent(FunctionalInterface.class);
|
||||
List<java.lang.reflect.Method> methods = new ArrayList<>();
|
||||
for (java.lang.reflect.Method m : clazz.clazz.getMethods()) {
|
||||
// default interface methods don't count
|
||||
if (m.isDefault()) {
|
||||
continue;
|
||||
}
|
||||
// static methods don't count
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
// if its from Object, it doesn't count
|
||||
try {
|
||||
Object.class.getMethod(m.getName(), m.getParameterTypes());
|
||||
continue;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
// it counts
|
||||
}
|
||||
methods.add(m);
|
||||
}
|
||||
if (methods.size() != 1) {
|
||||
if (hasAnnotation) {
|
||||
throw new IllegalArgumentException("Class: " + clazz.name +
|
||||
" is marked with FunctionalInterface but doesn't fit the bill: " + methods);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// inspect the one method found from the reflection API, it should match the whitelist!
|
||||
java.lang.reflect.Method oneMethod = methods.get(0);
|
||||
Method painless = clazz.methods.get(new Definition.MethodKey(oneMethod.getName(), oneMethod.getParameterCount()));
|
||||
if (painless == null || painless.method.equals(org.objectweb.asm.commons.Method.getMethod(oneMethod)) == false) {
|
||||
throw new IllegalArgumentException("Class: " + clazz.name + " is functional but the functional " +
|
||||
"method is not whitelisted!");
|
||||
}
|
||||
return painless;
|
||||
}
|
||||
|
||||
private Type getTypeInternal(String name) {
|
||||
// simple types (e.g. 0 array dimensions) are a simple hash lookup for speed
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Reference to a function or lambda.
|
||||
* <p>
|
||||
* Once you have created one of these, you have "everything you need" to call LambdaMetaFactory
|
||||
* either statically from bytecode with invokedynamic, or at runtime from Java.
|
||||
*/
|
||||
public class FunctionRef {
|
||||
/** Function Object's method name */
|
||||
public final String invokedName;
|
||||
/** CallSite signature */
|
||||
public final MethodType invokedType;
|
||||
/** Implementation method */
|
||||
public final MethodHandle implMethod;
|
||||
/** Function Object's method signature */
|
||||
public final MethodType samMethodType;
|
||||
/** When bridging is required, request this bridge interface */
|
||||
public final MethodType interfaceMethodType;
|
||||
|
||||
/** ASM "Handle" to the method, for the constant pool */
|
||||
public final Handle implMethodASM;
|
||||
|
||||
/**
|
||||
* Creates a new FunctionRef.
|
||||
* @param expected interface type to implement.
|
||||
* @param type the left hand side of a method reference expression
|
||||
* @param call the right hand side of a method reference expression
|
||||
*/
|
||||
public FunctionRef(Definition.Type expected, String type, String call) {
|
||||
boolean isCtorReference = "new".equals(call);
|
||||
// check its really a functional interface
|
||||
// for e.g. Comparable
|
||||
Method method = expected.struct.getFunctionalMethod();
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
||||
"to [" + expected.name + "], not a functional interface");
|
||||
}
|
||||
// e.g. compareTo
|
||||
invokedName = method.name;
|
||||
// e.g. (Object)Comparator
|
||||
invokedType = MethodType.methodType(expected.clazz);
|
||||
// e.g. (Object,Object)int
|
||||
interfaceMethodType = method.handle.type().dropParameterTypes(0, 1);
|
||||
// lookup requested method
|
||||
Definition.Struct struct = Definition.getType(type).struct;
|
||||
final Definition.Method impl;
|
||||
// ctor ref
|
||||
if (isCtorReference) {
|
||||
impl = struct.constructors.get(new Definition.MethodKey("<init>", method.arguments.size()));
|
||||
} else {
|
||||
// look for a static impl first
|
||||
Definition.Method staticImpl = struct.staticMethods.get(new Definition.MethodKey(call, method.arguments.size()));
|
||||
if (staticImpl == null) {
|
||||
// otherwise a virtual impl
|
||||
impl = struct.methods.get(new Definition.MethodKey(call, method.arguments.size()-1));
|
||||
} else {
|
||||
impl = staticImpl;
|
||||
}
|
||||
}
|
||||
if (impl == null) {
|
||||
throw new IllegalArgumentException("Unknown reference [" + type + "::" + call + "] matching " +
|
||||
"[" + expected + "]");
|
||||
}
|
||||
|
||||
final int tag;
|
||||
if (isCtorReference) {
|
||||
tag = Opcodes.H_NEWINVOKESPECIAL;
|
||||
} else if (Modifier.isStatic(impl.modifiers)) {
|
||||
tag = Opcodes.H_INVOKESTATIC;
|
||||
} else {
|
||||
tag = Opcodes.H_INVOKEVIRTUAL;
|
||||
}
|
||||
implMethodASM = new Handle(tag, struct.type.getInternalName(), impl.name, impl.method.getDescriptor());
|
||||
implMethod = impl.handle;
|
||||
if (isCtorReference) {
|
||||
samMethodType = MethodType.methodType(interfaceMethodType.returnType(), impl.handle.type().parameterArray());
|
||||
} else if (Modifier.isStatic(impl.modifiers)) {
|
||||
samMethodType = impl.handle.type();
|
||||
} else {
|
||||
// ensure the receiver type is exact and not a superclass type
|
||||
samMethodType = impl.handle.type().changeParameterType(0, struct.clazz);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if you should ask LambdaMetaFactory to construct a bridge for the interface signature */
|
||||
public boolean needsBridges() {
|
||||
// currently if the interface differs, we ask for a bridge, but maybe we should do smarter checking?
|
||||
// either way, stuff will fail if its wrong :)
|
||||
return interfaceMethodType.equals(samMethodType) == false;
|
||||
}
|
||||
}
|
|
@ -40,7 +40,6 @@ import java.security.Permissions;
|
|||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -119,7 +119,7 @@ final class ScriptImpl implements ExecutableScript, LeafSearchScript {
|
|||
public Object run() {
|
||||
try {
|
||||
return executable.execute(variables, scorer, doc, aggregationValue);
|
||||
} catch (PainlessError | Exception t) {
|
||||
} catch (PainlessError | BootstrapMethodError | Exception t) {
|
||||
throw convertToScriptException(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.objectweb.asm.Type;
|
|||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.BitSet;
|
||||
|
@ -67,7 +68,7 @@ public final class WriterConstants {
|
|||
|
||||
/** dynamic callsite bootstrap signature */
|
||||
public final static MethodType DEF_BOOTSTRAP_TYPE =
|
||||
MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class);
|
||||
MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class, long.class);
|
||||
public final static Handle DEF_BOOTSTRAP_HANDLE =
|
||||
new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(DefBootstrap.class),
|
||||
"bootstrap", DEF_BOOTSTRAP_TYPE.toMethodDescriptorString());
|
||||
|
@ -106,7 +107,15 @@ public final class WriterConstants {
|
|||
public final static Method DEF_LTE_CALL = getAsmMethod(boolean.class, "lte", Object.class, Object.class);
|
||||
public final static Method DEF_GT_CALL = getAsmMethod(boolean.class, "gt" , Object.class, Object.class);
|
||||
public final static Method DEF_GTE_CALL = getAsmMethod(boolean.class, "gte", Object.class, Object.class);
|
||||
|
||||
|
||||
/** invokedynamic bootstrap for lambda expression/method references */
|
||||
public final static MethodType LAMBDA_BOOTSTRAP_TYPE =
|
||||
MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
|
||||
MethodType.class, Object[].class);
|
||||
public final static Handle LAMBDA_BOOTSTRAP_HANDLE =
|
||||
new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(LambdaMetafactory.class),
|
||||
"altMetafactory", LAMBDA_BOOTSTRAP_TYPE.toMethodDescriptorString());
|
||||
|
||||
/** dynamic invokedynamic bootstrap for indy string concats (Java 9+) */
|
||||
public final static Handle INDY_STRING_CONCAT_BOOTSTRAP_HANDLE;
|
||||
static {
|
||||
|
|
|
@ -1030,6 +1030,7 @@ class PainlessParser extends Parser {
|
|||
public TerminalNode TYPE() { return getToken(PainlessParser.TYPE, 0); }
|
||||
public TerminalNode REF() { return getToken(PainlessParser.REF, 0); }
|
||||
public TerminalNode ID() { return getToken(PainlessParser.ID, 0); }
|
||||
public TerminalNode NEW() { return getToken(PainlessParser.NEW, 0); }
|
||||
public FuncrefContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
|
@ -1044,6 +1045,7 @@ class PainlessParser extends Parser {
|
|||
public final FuncrefContext funcref() throws RecognitionException {
|
||||
FuncrefContext _localctx = new FuncrefContext(_ctx, getState());
|
||||
enterRule(_localctx, 18, RULE_funcref);
|
||||
int _la;
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
|
@ -1052,7 +1054,12 @@ class PainlessParser extends Parser {
|
|||
setState(171);
|
||||
match(REF);
|
||||
setState(172);
|
||||
match(ID);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==NEW || _la==ID) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
} else {
|
||||
consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
|
@ -2667,117 +2674,117 @@ class PainlessParser extends Parser {
|
|||
"\3\23\3\23\3\23\3\23\5\23\u0161\n\23\3\24\3\24\3\24\3\24\3\24\5\24\u0168"+
|
||||
"\n\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\7\26\u0172\n\26\f\26\16"+
|
||||
"\26\u0175\13\26\5\26\u0177\n\26\3\26\3\26\3\27\3\27\5\27\u017d\n\27\3"+
|
||||
"\27\2\3\34\30\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,\2\r\3\3\r"+
|
||||
"\r\3\2\66A\3\2\34\36\3\2\37 \3\2!#\3\2$\'\3\2(+\3\2\64\65\3\2BE\4\2\32"+
|
||||
"\33\37 \3\2LM\u01a5\2\61\3\2\2\2\4\u0084\3\2\2\2\6\u0088\3\2\2\2\b\u008a"+
|
||||
"\3\2\2\2\n\u0093\3\2\2\2\f\u0097\3\2\2\2\16\u0099\3\2\2\2\20\u009b\3\2"+
|
||||
"\2\2\22\u00a4\3\2\2\2\24\u00ac\3\2\2\2\26\u00b0\3\2\2\2\30\u00b5\3\2\2"+
|
||||
"\2\32\u00bc\3\2\2\2\34\u00c7\3\2\2\2\36\u0124\3\2\2\2 \u0148\3\2\2\2\""+
|
||||
"\u015a\3\2\2\2$\u0160\3\2\2\2&\u0167\3\2\2\2(\u0169\3\2\2\2*\u016d\3\2"+
|
||||
"\2\2,\u017c\3\2\2\2.\60\5\4\3\2/.\3\2\2\2\60\63\3\2\2\2\61/\3\2\2\2\61"+
|
||||
"\62\3\2\2\2\62\64\3\2\2\2\63\61\3\2\2\2\64\65\7\2\2\3\65\3\3\2\2\2\66"+
|
||||
"\67\7\16\2\2\678\7\t\2\289\5\34\17\29:\7\n\2\2:>\5\6\4\2;<\7\17\2\2<?"+
|
||||
"\5\6\4\2=?\6\3\2\2>;\3\2\2\2>=\3\2\2\2?\u0085\3\2\2\2@A\7\20\2\2AB\7\t"+
|
||||
"\2\2BC\5\34\17\2CF\7\n\2\2DG\5\6\4\2EG\5\n\6\2FD\3\2\2\2FE\3\2\2\2G\u0085"+
|
||||
"\3\2\2\2HI\7\21\2\2IJ\5\b\5\2JK\7\20\2\2KL\7\t\2\2LM\5\34\17\2MN\7\n\2"+
|
||||
"\2NO\5\32\16\2O\u0085\3\2\2\2PQ\7\22\2\2QS\7\t\2\2RT\5\f\7\2SR\3\2\2\2"+
|
||||
"ST\3\2\2\2TU\3\2\2\2UW\7\r\2\2VX\5\34\17\2WV\3\2\2\2WX\3\2\2\2XY\3\2\2"+
|
||||
"\2Y[\7\r\2\2Z\\\5\16\b\2[Z\3\2\2\2[\\\3\2\2\2\\]\3\2\2\2]`\7\n\2\2^a\5"+
|
||||
"\6\4\2_a\5\n\6\2`^\3\2\2\2`_\3\2\2\2a\u0085\3\2\2\2bc\7\22\2\2cd\7\t\2"+
|
||||
"\2de\5\22\n\2ef\7K\2\2fg\7\62\2\2gh\5\34\17\2hi\7\n\2\2ij\5\6\4\2j\u0085"+
|
||||
"\3\2\2\2kl\5\20\t\2lm\5\32\16\2m\u0085\3\2\2\2no\7\23\2\2o\u0085\5\32"+
|
||||
"\16\2pq\7\24\2\2q\u0085\5\32\16\2rs\7\25\2\2st\5\34\17\2tu\5\32\16\2u"+
|
||||
"\u0085\3\2\2\2vw\7\27\2\2wy\5\b\5\2xz\5\30\r\2yx\3\2\2\2z{\3\2\2\2{y\3"+
|
||||
"\2\2\2{|\3\2\2\2|\u0085\3\2\2\2}~\7\31\2\2~\177\5\34\17\2\177\u0080\5"+
|
||||
"\32\16\2\u0080\u0085\3\2\2\2\u0081\u0082\5\34\17\2\u0082\u0083\5\32\16"+
|
||||
"\2\u0083\u0085\3\2\2\2\u0084\66\3\2\2\2\u0084@\3\2\2\2\u0084H\3\2\2\2"+
|
||||
"\u0084P\3\2\2\2\u0084b\3\2\2\2\u0084k\3\2\2\2\u0084n\3\2\2\2\u0084p\3"+
|
||||
"\2\2\2\u0084r\3\2\2\2\u0084v\3\2\2\2\u0084}\3\2\2\2\u0084\u0081\3\2\2"+
|
||||
"\2\u0085\5\3\2\2\2\u0086\u0089\5\b\5\2\u0087\u0089\5\4\3\2\u0088\u0086"+
|
||||
"\3\2\2\2\u0088\u0087\3\2\2\2\u0089\7\3\2\2\2\u008a\u008e\7\5\2\2\u008b"+
|
||||
"\u008d\5\4\3\2\u008c\u008b\3\2\2\2\u008d\u0090\3\2\2\2\u008e\u008c\3\2"+
|
||||
"\2\2\u008e\u008f\3\2\2\2\u008f\u0091\3\2\2\2\u0090\u008e\3\2\2\2\u0091"+
|
||||
"\u0092\7\6\2\2\u0092\t\3\2\2\2\u0093\u0094\7\r\2\2\u0094\13\3\2\2\2\u0095"+
|
||||
"\u0098\5\20\t\2\u0096\u0098\5\34\17\2\u0097\u0095\3\2\2\2\u0097\u0096"+
|
||||
"\3\2\2\2\u0098\r\3\2\2\2\u0099\u009a\5\34\17\2\u009a\17\3\2\2\2\u009b"+
|
||||
"\u009c\5\22\n\2\u009c\u00a1\5\26\f\2\u009d\u009e\7\f\2\2\u009e\u00a0\5"+
|
||||
"\26\f\2\u009f\u009d\3\2\2\2\u00a0\u00a3\3\2\2\2\u00a1\u009f\3\2\2\2\u00a1"+
|
||||
"\u00a2\3\2\2\2\u00a2\21\3\2\2\2\u00a3\u00a1\3\2\2\2\u00a4\u00a9\7J\2\2"+
|
||||
"\u00a5\u00a6\7\7\2\2\u00a6\u00a8\7\b\2\2\u00a7\u00a5\3\2\2\2\u00a8\u00ab"+
|
||||
"\3\2\2\2\u00a9\u00a7\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa\23\3\2\2\2\u00ab"+
|
||||
"\u00a9\3\2\2\2\u00ac\u00ad\7J\2\2\u00ad\u00ae\7\63\2\2\u00ae\u00af\7K"+
|
||||
"\2\2\u00af\25\3\2\2\2\u00b0\u00b3\7K\2\2\u00b1\u00b2\7\66\2\2\u00b2\u00b4"+
|
||||
"\5\34\17\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b4\27\3\2\2\2\u00b5"+
|
||||
"\u00b6\7\30\2\2\u00b6\u00b7\7\t\2\2\u00b7\u00b8\7J\2\2\u00b8\u00b9\7K"+
|
||||
"\2\2\u00b9\u00ba\7\n\2\2\u00ba\u00bb\5\b\5\2\u00bb\31\3\2\2\2\u00bc\u00bd"+
|
||||
"\t\2\2\2\u00bd\33\3\2\2\2\u00be\u00bf\b\17\1\2\u00bf\u00c0\5 \21\2\u00c0"+
|
||||
"\u00c1\t\3\2\2\u00c1\u00c2\5\34\17\3\u00c2\u00c3\b\17\1\2\u00c3\u00c8"+
|
||||
"\3\2\2\2\u00c4\u00c5\5\36\20\2\u00c5\u00c6\b\17\1\2\u00c6\u00c8\3\2\2"+
|
||||
"\2\u00c7\u00be\3\2\2\2\u00c7\u00c4\3\2\2\2\u00c8\u0104\3\2\2\2\u00c9\u00ca"+
|
||||
"\f\16\2\2\u00ca\u00cb\t\4\2\2\u00cb\u00cc\5\34\17\17\u00cc\u00cd\b\17"+
|
||||
"\1\2\u00cd\u0103\3\2\2\2\u00ce\u00cf\f\r\2\2\u00cf\u00d0\t\5\2\2\u00d0"+
|
||||
"\u00d1\5\34\17\16\u00d1\u00d2\b\17\1\2\u00d2\u0103\3\2\2\2\u00d3\u00d4"+
|
||||
"\f\f\2\2\u00d4\u00d5\t\6\2\2\u00d5\u00d6\5\34\17\r\u00d6\u00d7\b\17\1"+
|
||||
"\2\u00d7\u0103\3\2\2\2\u00d8\u00d9\f\13\2\2\u00d9\u00da\t\7\2\2\u00da"+
|
||||
"\u00db\5\34\17\f\u00db\u00dc\b\17\1\2\u00dc\u0103\3\2\2\2\u00dd\u00de"+
|
||||
"\f\n\2\2\u00de\u00df\t\b\2\2\u00df\u00e0\5\34\17\13\u00e0\u00e1\b\17\1"+
|
||||
"\2\u00e1\u0103\3\2\2\2\u00e2\u00e3\f\t\2\2\u00e3\u00e4\7,\2\2\u00e4\u00e5"+
|
||||
"\5\34\17\n\u00e5\u00e6\b\17\1\2\u00e6\u0103\3\2\2\2\u00e7\u00e8\f\b\2"+
|
||||
"\2\u00e8\u00e9\7-\2\2\u00e9\u00ea\5\34\17\t\u00ea\u00eb\b\17\1\2\u00eb"+
|
||||
"\u0103\3\2\2\2\u00ec\u00ed\f\7\2\2\u00ed\u00ee\7.\2\2\u00ee\u00ef\5\34"+
|
||||
"\17\b\u00ef\u00f0\b\17\1\2\u00f0\u0103\3\2\2\2\u00f1\u00f2\f\6\2\2\u00f2"+
|
||||
"\u00f3\7/\2\2\u00f3\u00f4\5\34\17\7\u00f4\u00f5\b\17\1\2\u00f5\u0103\3"+
|
||||
"\2\2\2\u00f6\u00f7\f\5\2\2\u00f7\u00f8\7\60\2\2\u00f8\u00f9\5\34\17\6"+
|
||||
"\u00f9\u00fa\b\17\1\2\u00fa\u0103\3\2\2\2\u00fb\u00fc\f\4\2\2\u00fc\u00fd"+
|
||||
"\7\61\2\2\u00fd\u00fe\5\34\17\2\u00fe\u00ff\7\62\2\2\u00ff\u0100\5\34"+
|
||||
"\17\4\u0100\u0101\b\17\1\2\u0101\u0103\3\2\2\2\u0102\u00c9\3\2\2\2\u0102"+
|
||||
"\u00ce\3\2\2\2\u0102\u00d3\3\2\2\2\u0102\u00d8\3\2\2\2\u0102\u00dd\3\2"+
|
||||
"\2\2\u0102\u00e2\3\2\2\2\u0102\u00e7\3\2\2\2\u0102\u00ec\3\2\2\2\u0102"+
|
||||
"\u00f1\3\2\2\2\u0102\u00f6\3\2\2\2\u0102\u00fb\3\2\2\2\u0103\u0106\3\2"+
|
||||
"\2\2\u0104\u0102\3\2\2\2\u0104\u0105\3\2\2\2\u0105\35\3\2\2\2\u0106\u0104"+
|
||||
"\3\2\2\2\u0107\u0108\6\20\16\3\u0108\u0109\t\t\2\2\u0109\u0125\5 \21\2"+
|
||||
"\u010a\u010b\6\20\17\3\u010b\u010c\5 \21\2\u010c\u010d\t\t\2\2\u010d\u0125"+
|
||||
"\3\2\2\2\u010e\u010f\6\20\20\3\u010f\u0125\5 \21\2\u0110\u0111\6\20\21"+
|
||||
"\3\u0111\u0112\t\n\2\2\u0112\u0125\b\20\1\2\u0113\u0114\6\20\22\3\u0114"+
|
||||
"\u0115\7G\2\2\u0115\u0125\b\20\1\2\u0116\u0117\6\20\23\3\u0117\u0118\7"+
|
||||
"H\2\2\u0118\u0125\b\20\1\2\u0119\u011a\6\20\24\3\u011a\u011b\7I\2\2\u011b"+
|
||||
"\u0125\b\20\1\2\u011c\u011d\6\20\25\3\u011d\u011e\t\13\2\2\u011e\u0125"+
|
||||
"\5\36\20\2\u011f\u0120\7\t\2\2\u0120\u0121\5\22\n\2\u0121\u0122\7\n\2"+
|
||||
"\2\u0122\u0123\5\36\20\2\u0123\u0125\3\2\2\2\u0124\u0107\3\2\2\2\u0124"+
|
||||
"\u010a\3\2\2\2\u0124\u010e\3\2\2\2\u0124\u0110\3\2\2\2\u0124\u0113\3\2"+
|
||||
"\2\2\u0124\u0116\3\2\2\2\u0124\u0119\3\2\2\2\u0124\u011c\3\2\2\2\u0124"+
|
||||
"\u011f\3\2\2\2\u0125\37\3\2\2\2\u0126\u012a\5\"\22\2\u0127\u0129\5$\23"+
|
||||
"\2\u0128\u0127\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u0128\3\2\2\2\u012a\u012b"+
|
||||
"\3\2\2\2\u012b\u0149\3\2\2\2\u012c\u012a\3\2\2\2\u012d\u012e\5\22\n\2"+
|
||||
"\u012e\u0132\5&\24\2\u012f\u0131\5$\23\2\u0130\u012f\3\2\2\2\u0131\u0134"+
|
||||
"\3\2\2\2\u0132\u0130\3\2\2\2\u0132\u0133\3\2\2\2\u0133\u0149\3\2\2\2\u0134"+
|
||||
"\u0132\3\2\2\2\u0135\u0136\7\26\2\2\u0136\u013b\7J\2\2\u0137\u0138\7\7"+
|
||||
"\2\2\u0138\u0139\5\34\17\2\u0139\u013a\7\b\2\2\u013a\u013c\3\2\2\2\u013b"+
|
||||
"\u0137\3\2\2\2\u013c\u013d\3\2\2\2\u013d\u013b\3\2\2\2\u013d\u013e\3\2"+
|
||||
"\2\2\u013e\u0146\3\2\2\2\u013f\u0143\5&\24\2\u0140\u0142\5$\23\2\u0141"+
|
||||
"\u0140\3\2\2\2\u0142\u0145\3\2\2\2\u0143\u0141\3\2\2\2\u0143\u0144\3\2"+
|
||||
"\2\2\u0144\u0147\3\2\2\2\u0145\u0143\3\2\2\2\u0146\u013f\3\2\2\2\u0146"+
|
||||
"\u0147\3\2\2\2\u0147\u0149\3\2\2\2\u0148\u0126\3\2\2\2\u0148\u012d\3\2"+
|
||||
"\2\2\u0148\u0135\3\2\2\2\u0149!\3\2\2\2\u014a\u014b\6\22\26\3\u014b\u014c"+
|
||||
"\7\t\2\2\u014c\u014d\5\34\17\2\u014d\u014e\7\n\2\2\u014e\u014f\b\22\1"+
|
||||
"\2\u014f\u015b\3\2\2\2\u0150\u0151\6\22\27\3\u0151\u0152\7\t\2\2\u0152"+
|
||||
"\u0153\5\36\20\2\u0153\u0154\7\n\2\2\u0154\u015b\3\2\2\2\u0155\u015b\7"+
|
||||
"F\2\2\u0156\u015b\7K\2\2\u0157\u0158\7\26\2\2\u0158\u0159\7J\2\2\u0159"+
|
||||
"\u015b\5*\26\2\u015a\u014a\3\2\2\2\u015a\u0150\3\2\2\2\u015a\u0155\3\2"+
|
||||
"\2\2\u015a\u0156\3\2\2\2\u015a\u0157\3\2\2\2\u015b#\3\2\2\2\u015c\u015d"+
|
||||
"\6\23\30\3\u015d\u0161\5&\24\2\u015e\u015f\6\23\31\3\u015f\u0161\5(\25"+
|
||||
"\2\u0160\u015c\3\2\2\2\u0160\u015e\3\2\2\2\u0161%\3\2\2\2\u0162\u0163"+
|
||||
"\7\13\2\2\u0163\u0164\7M\2\2\u0164\u0168\5*\26\2\u0165\u0166\7\13\2\2"+
|
||||
"\u0166\u0168\t\f\2\2\u0167\u0162\3\2\2\2\u0167\u0165\3\2\2\2\u0168\'\3"+
|
||||
"\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5\34\17\2\u016b\u016c\7\b\2\2\u016c"+
|
||||
")\3\2\2\2\u016d\u0176\7\t\2\2\u016e\u0173\5,\27\2\u016f\u0170\7\f\2\2"+
|
||||
"\u0170\u0172\5,\27\2\u0171\u016f\3\2\2\2\u0172\u0175\3\2\2\2\u0173\u0171"+
|
||||
"\3\2\2\2\u0173\u0174\3\2\2\2\u0174\u0177\3\2\2\2\u0175\u0173\3\2\2\2\u0176"+
|
||||
"\u016e\3\2\2\2\u0176\u0177\3\2\2\2\u0177\u0178\3\2\2\2\u0178\u0179\7\n"+
|
||||
"\2\2\u0179+\3\2\2\2\u017a\u017d\5\34\17\2\u017b\u017d\5\24\13\2\u017c"+
|
||||
"\u017a\3\2\2\2\u017c\u017b\3\2\2\2\u017d-\3\2\2\2!\61>FSW[`{\u0084\u0088"+
|
||||
"\u008e\u0097\u00a1\u00a9\u00b3\u00c7\u0102\u0104\u0124\u012a\u0132\u013d"+
|
||||
"\u0143\u0146\u0148\u015a\u0160\u0167\u0173\u0176\u017c";
|
||||
"\27\2\3\34\30\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,\2\16\4\2"+
|
||||
"\26\26KK\3\3\r\r\3\2\66A\3\2\34\36\3\2\37 \3\2!#\3\2$\'\3\2(+\3\2\64\65"+
|
||||
"\3\2BE\4\2\32\33\37 \3\2LM\u01a5\2\61\3\2\2\2\4\u0084\3\2\2\2\6\u0088"+
|
||||
"\3\2\2\2\b\u008a\3\2\2\2\n\u0093\3\2\2\2\f\u0097\3\2\2\2\16\u0099\3\2"+
|
||||
"\2\2\20\u009b\3\2\2\2\22\u00a4\3\2\2\2\24\u00ac\3\2\2\2\26\u00b0\3\2\2"+
|
||||
"\2\30\u00b5\3\2\2\2\32\u00bc\3\2\2\2\34\u00c7\3\2\2\2\36\u0124\3\2\2\2"+
|
||||
" \u0148\3\2\2\2\"\u015a\3\2\2\2$\u0160\3\2\2\2&\u0167\3\2\2\2(\u0169\3"+
|
||||
"\2\2\2*\u016d\3\2\2\2,\u017c\3\2\2\2.\60\5\4\3\2/.\3\2\2\2\60\63\3\2\2"+
|
||||
"\2\61/\3\2\2\2\61\62\3\2\2\2\62\64\3\2\2\2\63\61\3\2\2\2\64\65\7\2\2\3"+
|
||||
"\65\3\3\2\2\2\66\67\7\16\2\2\678\7\t\2\289\5\34\17\29:\7\n\2\2:>\5\6\4"+
|
||||
"\2;<\7\17\2\2<?\5\6\4\2=?\6\3\2\2>;\3\2\2\2>=\3\2\2\2?\u0085\3\2\2\2@"+
|
||||
"A\7\20\2\2AB\7\t\2\2BC\5\34\17\2CF\7\n\2\2DG\5\6\4\2EG\5\n\6\2FD\3\2\2"+
|
||||
"\2FE\3\2\2\2G\u0085\3\2\2\2HI\7\21\2\2IJ\5\b\5\2JK\7\20\2\2KL\7\t\2\2"+
|
||||
"LM\5\34\17\2MN\7\n\2\2NO\5\32\16\2O\u0085\3\2\2\2PQ\7\22\2\2QS\7\t\2\2"+
|
||||
"RT\5\f\7\2SR\3\2\2\2ST\3\2\2\2TU\3\2\2\2UW\7\r\2\2VX\5\34\17\2WV\3\2\2"+
|
||||
"\2WX\3\2\2\2XY\3\2\2\2Y[\7\r\2\2Z\\\5\16\b\2[Z\3\2\2\2[\\\3\2\2\2\\]\3"+
|
||||
"\2\2\2]`\7\n\2\2^a\5\6\4\2_a\5\n\6\2`^\3\2\2\2`_\3\2\2\2a\u0085\3\2\2"+
|
||||
"\2bc\7\22\2\2cd\7\t\2\2de\5\22\n\2ef\7K\2\2fg\7\62\2\2gh\5\34\17\2hi\7"+
|
||||
"\n\2\2ij\5\6\4\2j\u0085\3\2\2\2kl\5\20\t\2lm\5\32\16\2m\u0085\3\2\2\2"+
|
||||
"no\7\23\2\2o\u0085\5\32\16\2pq\7\24\2\2q\u0085\5\32\16\2rs\7\25\2\2st"+
|
||||
"\5\34\17\2tu\5\32\16\2u\u0085\3\2\2\2vw\7\27\2\2wy\5\b\5\2xz\5\30\r\2"+
|
||||
"yx\3\2\2\2z{\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\u0085\3\2\2\2}~\7\31\2\2~\177"+
|
||||
"\5\34\17\2\177\u0080\5\32\16\2\u0080\u0085\3\2\2\2\u0081\u0082\5\34\17"+
|
||||
"\2\u0082\u0083\5\32\16\2\u0083\u0085\3\2\2\2\u0084\66\3\2\2\2\u0084@\3"+
|
||||
"\2\2\2\u0084H\3\2\2\2\u0084P\3\2\2\2\u0084b\3\2\2\2\u0084k\3\2\2\2\u0084"+
|
||||
"n\3\2\2\2\u0084p\3\2\2\2\u0084r\3\2\2\2\u0084v\3\2\2\2\u0084}\3\2\2\2"+
|
||||
"\u0084\u0081\3\2\2\2\u0085\5\3\2\2\2\u0086\u0089\5\b\5\2\u0087\u0089\5"+
|
||||
"\4\3\2\u0088\u0086\3\2\2\2\u0088\u0087\3\2\2\2\u0089\7\3\2\2\2\u008a\u008e"+
|
||||
"\7\5\2\2\u008b\u008d\5\4\3\2\u008c\u008b\3\2\2\2\u008d\u0090\3\2\2\2\u008e"+
|
||||
"\u008c\3\2\2\2\u008e\u008f\3\2\2\2\u008f\u0091\3\2\2\2\u0090\u008e\3\2"+
|
||||
"\2\2\u0091\u0092\7\6\2\2\u0092\t\3\2\2\2\u0093\u0094\7\r\2\2\u0094\13"+
|
||||
"\3\2\2\2\u0095\u0098\5\20\t\2\u0096\u0098\5\34\17\2\u0097\u0095\3\2\2"+
|
||||
"\2\u0097\u0096\3\2\2\2\u0098\r\3\2\2\2\u0099\u009a\5\34\17\2\u009a\17"+
|
||||
"\3\2\2\2\u009b\u009c\5\22\n\2\u009c\u00a1\5\26\f\2\u009d\u009e\7\f\2\2"+
|
||||
"\u009e\u00a0\5\26\f\2\u009f\u009d\3\2\2\2\u00a0\u00a3\3\2\2\2\u00a1\u009f"+
|
||||
"\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\21\3\2\2\2\u00a3\u00a1\3\2\2\2\u00a4"+
|
||||
"\u00a9\7J\2\2\u00a5\u00a6\7\7\2\2\u00a6\u00a8\7\b\2\2\u00a7\u00a5\3\2"+
|
||||
"\2\2\u00a8\u00ab\3\2\2\2\u00a9\u00a7\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa"+
|
||||
"\23\3\2\2\2\u00ab\u00a9\3\2\2\2\u00ac\u00ad\7J\2\2\u00ad\u00ae\7\63\2"+
|
||||
"\2\u00ae\u00af\t\2\2\2\u00af\25\3\2\2\2\u00b0\u00b3\7K\2\2\u00b1\u00b2"+
|
||||
"\7\66\2\2\u00b2\u00b4\5\34\17\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2"+
|
||||
"\2\u00b4\27\3\2\2\2\u00b5\u00b6\7\30\2\2\u00b6\u00b7\7\t\2\2\u00b7\u00b8"+
|
||||
"\7J\2\2\u00b8\u00b9\7K\2\2\u00b9\u00ba\7\n\2\2\u00ba\u00bb\5\b\5\2\u00bb"+
|
||||
"\31\3\2\2\2\u00bc\u00bd\t\3\2\2\u00bd\33\3\2\2\2\u00be\u00bf\b\17\1\2"+
|
||||
"\u00bf\u00c0\5 \21\2\u00c0\u00c1\t\4\2\2\u00c1\u00c2\5\34\17\3\u00c2\u00c3"+
|
||||
"\b\17\1\2\u00c3\u00c8\3\2\2\2\u00c4\u00c5\5\36\20\2\u00c5\u00c6\b\17\1"+
|
||||
"\2\u00c6\u00c8\3\2\2\2\u00c7\u00be\3\2\2\2\u00c7\u00c4\3\2\2\2\u00c8\u0104"+
|
||||
"\3\2\2\2\u00c9\u00ca\f\16\2\2\u00ca\u00cb\t\5\2\2\u00cb\u00cc\5\34\17"+
|
||||
"\17\u00cc\u00cd\b\17\1\2\u00cd\u0103\3\2\2\2\u00ce\u00cf\f\r\2\2\u00cf"+
|
||||
"\u00d0\t\6\2\2\u00d0\u00d1\5\34\17\16\u00d1\u00d2\b\17\1\2\u00d2\u0103"+
|
||||
"\3\2\2\2\u00d3\u00d4\f\f\2\2\u00d4\u00d5\t\7\2\2\u00d5\u00d6\5\34\17\r"+
|
||||
"\u00d6\u00d7\b\17\1\2\u00d7\u0103\3\2\2\2\u00d8\u00d9\f\13\2\2\u00d9\u00da"+
|
||||
"\t\b\2\2\u00da\u00db\5\34\17\f\u00db\u00dc\b\17\1\2\u00dc\u0103\3\2\2"+
|
||||
"\2\u00dd\u00de\f\n\2\2\u00de\u00df\t\t\2\2\u00df\u00e0\5\34\17\13\u00e0"+
|
||||
"\u00e1\b\17\1\2\u00e1\u0103\3\2\2\2\u00e2\u00e3\f\t\2\2\u00e3\u00e4\7"+
|
||||
",\2\2\u00e4\u00e5\5\34\17\n\u00e5\u00e6\b\17\1\2\u00e6\u0103\3\2\2\2\u00e7"+
|
||||
"\u00e8\f\b\2\2\u00e8\u00e9\7-\2\2\u00e9\u00ea\5\34\17\t\u00ea\u00eb\b"+
|
||||
"\17\1\2\u00eb\u0103\3\2\2\2\u00ec\u00ed\f\7\2\2\u00ed\u00ee\7.\2\2\u00ee"+
|
||||
"\u00ef\5\34\17\b\u00ef\u00f0\b\17\1\2\u00f0\u0103\3\2\2\2\u00f1\u00f2"+
|
||||
"\f\6\2\2\u00f2\u00f3\7/\2\2\u00f3\u00f4\5\34\17\7\u00f4\u00f5\b\17\1\2"+
|
||||
"\u00f5\u0103\3\2\2\2\u00f6\u00f7\f\5\2\2\u00f7\u00f8\7\60\2\2\u00f8\u00f9"+
|
||||
"\5\34\17\6\u00f9\u00fa\b\17\1\2\u00fa\u0103\3\2\2\2\u00fb\u00fc\f\4\2"+
|
||||
"\2\u00fc\u00fd\7\61\2\2\u00fd\u00fe\5\34\17\2\u00fe\u00ff\7\62\2\2\u00ff"+
|
||||
"\u0100\5\34\17\4\u0100\u0101\b\17\1\2\u0101\u0103\3\2\2\2\u0102\u00c9"+
|
||||
"\3\2\2\2\u0102\u00ce\3\2\2\2\u0102\u00d3\3\2\2\2\u0102\u00d8\3\2\2\2\u0102"+
|
||||
"\u00dd\3\2\2\2\u0102\u00e2\3\2\2\2\u0102\u00e7\3\2\2\2\u0102\u00ec\3\2"+
|
||||
"\2\2\u0102\u00f1\3\2\2\2\u0102\u00f6\3\2\2\2\u0102\u00fb\3\2\2\2\u0103"+
|
||||
"\u0106\3\2\2\2\u0104\u0102\3\2\2\2\u0104\u0105\3\2\2\2\u0105\35\3\2\2"+
|
||||
"\2\u0106\u0104\3\2\2\2\u0107\u0108\6\20\16\3\u0108\u0109\t\n\2\2\u0109"+
|
||||
"\u0125\5 \21\2\u010a\u010b\6\20\17\3\u010b\u010c\5 \21\2\u010c\u010d\t"+
|
||||
"\n\2\2\u010d\u0125\3\2\2\2\u010e\u010f\6\20\20\3\u010f\u0125\5 \21\2\u0110"+
|
||||
"\u0111\6\20\21\3\u0111\u0112\t\13\2\2\u0112\u0125\b\20\1\2\u0113\u0114"+
|
||||
"\6\20\22\3\u0114\u0115\7G\2\2\u0115\u0125\b\20\1\2\u0116\u0117\6\20\23"+
|
||||
"\3\u0117\u0118\7H\2\2\u0118\u0125\b\20\1\2\u0119\u011a\6\20\24\3\u011a"+
|
||||
"\u011b\7I\2\2\u011b\u0125\b\20\1\2\u011c\u011d\6\20\25\3\u011d\u011e\t"+
|
||||
"\f\2\2\u011e\u0125\5\36\20\2\u011f\u0120\7\t\2\2\u0120\u0121\5\22\n\2"+
|
||||
"\u0121\u0122\7\n\2\2\u0122\u0123\5\36\20\2\u0123\u0125\3\2\2\2\u0124\u0107"+
|
||||
"\3\2\2\2\u0124\u010a\3\2\2\2\u0124\u010e\3\2\2\2\u0124\u0110\3\2\2\2\u0124"+
|
||||
"\u0113\3\2\2\2\u0124\u0116\3\2\2\2\u0124\u0119\3\2\2\2\u0124\u011c\3\2"+
|
||||
"\2\2\u0124\u011f\3\2\2\2\u0125\37\3\2\2\2\u0126\u012a\5\"\22\2\u0127\u0129"+
|
||||
"\5$\23\2\u0128\u0127\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u0128\3\2\2\2\u012a"+
|
||||
"\u012b\3\2\2\2\u012b\u0149\3\2\2\2\u012c\u012a\3\2\2\2\u012d\u012e\5\22"+
|
||||
"\n\2\u012e\u0132\5&\24\2\u012f\u0131\5$\23\2\u0130\u012f\3\2\2\2\u0131"+
|
||||
"\u0134\3\2\2\2\u0132\u0130\3\2\2\2\u0132\u0133\3\2\2\2\u0133\u0149\3\2"+
|
||||
"\2\2\u0134\u0132\3\2\2\2\u0135\u0136\7\26\2\2\u0136\u013b\7J\2\2\u0137"+
|
||||
"\u0138\7\7\2\2\u0138\u0139\5\34\17\2\u0139\u013a\7\b\2\2\u013a\u013c\3"+
|
||||
"\2\2\2\u013b\u0137\3\2\2\2\u013c\u013d\3\2\2\2\u013d\u013b\3\2\2\2\u013d"+
|
||||
"\u013e\3\2\2\2\u013e\u0146\3\2\2\2\u013f\u0143\5&\24\2\u0140\u0142\5$"+
|
||||
"\23\2\u0141\u0140\3\2\2\2\u0142\u0145\3\2\2\2\u0143\u0141\3\2\2\2\u0143"+
|
||||
"\u0144\3\2\2\2\u0144\u0147\3\2\2\2\u0145\u0143\3\2\2\2\u0146\u013f\3\2"+
|
||||
"\2\2\u0146\u0147\3\2\2\2\u0147\u0149\3\2\2\2\u0148\u0126\3\2\2\2\u0148"+
|
||||
"\u012d\3\2\2\2\u0148\u0135\3\2\2\2\u0149!\3\2\2\2\u014a\u014b\6\22\26"+
|
||||
"\3\u014b\u014c\7\t\2\2\u014c\u014d\5\34\17\2\u014d\u014e\7\n\2\2\u014e"+
|
||||
"\u014f\b\22\1\2\u014f\u015b\3\2\2\2\u0150\u0151\6\22\27\3\u0151\u0152"+
|
||||
"\7\t\2\2\u0152\u0153\5\36\20\2\u0153\u0154\7\n\2\2\u0154\u015b\3\2\2\2"+
|
||||
"\u0155\u015b\7F\2\2\u0156\u015b\7K\2\2\u0157\u0158\7\26\2\2\u0158\u0159"+
|
||||
"\7J\2\2\u0159\u015b\5*\26\2\u015a\u014a\3\2\2\2\u015a\u0150\3\2\2\2\u015a"+
|
||||
"\u0155\3\2\2\2\u015a\u0156\3\2\2\2\u015a\u0157\3\2\2\2\u015b#\3\2\2\2"+
|
||||
"\u015c\u015d\6\23\30\3\u015d\u0161\5&\24\2\u015e\u015f\6\23\31\3\u015f"+
|
||||
"\u0161\5(\25\2\u0160\u015c\3\2\2\2\u0160\u015e\3\2\2\2\u0161%\3\2\2\2"+
|
||||
"\u0162\u0163\7\13\2\2\u0163\u0164\7M\2\2\u0164\u0168\5*\26\2\u0165\u0166"+
|
||||
"\7\13\2\2\u0166\u0168\t\r\2\2\u0167\u0162\3\2\2\2\u0167\u0165\3\2\2\2"+
|
||||
"\u0168\'\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5\34\17\2\u016b\u016c"+
|
||||
"\7\b\2\2\u016c)\3\2\2\2\u016d\u0176\7\t\2\2\u016e\u0173\5,\27\2\u016f"+
|
||||
"\u0170\7\f\2\2\u0170\u0172\5,\27\2\u0171\u016f\3\2\2\2\u0172\u0175\3\2"+
|
||||
"\2\2\u0173\u0171\3\2\2\2\u0173\u0174\3\2\2\2\u0174\u0177\3\2\2\2\u0175"+
|
||||
"\u0173\3\2\2\2\u0176\u016e\3\2\2\2\u0176\u0177\3\2\2\2\u0177\u0178\3\2"+
|
||||
"\2\2\u0178\u0179\7\n\2\2\u0179+\3\2\2\2\u017a\u017d\5\34\17\2\u017b\u017d"+
|
||||
"\5\24\13\2\u017c\u017a\3\2\2\2\u017c\u017b\3\2\2\2\u017d-\3\2\2\2!\61"+
|
||||
">FSW[`{\u0084\u0088\u008e\u0097\u00a1\u00a9\u00b3\u00c7\u0102\u0104\u0124"+
|
||||
"\u012a\u0132\u013d\u0143\u0146\u0148\u015a\u0160\u0167\u0173\u0176\u017c";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
|
|
@ -405,7 +405,15 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
|||
|
||||
@Override
|
||||
public Object visitFuncref(FuncrefContext ctx) {
|
||||
return new EFunctionRef(location(ctx), ctx.TYPE().getText(), ctx.ID().getText());
|
||||
final String methodText;
|
||||
if (ctx.ID() != null) {
|
||||
methodText = ctx.ID().getText();
|
||||
} else if (ctx.NEW() != null ){
|
||||
methodText = ctx.NEW().getText();
|
||||
} else {
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
return new EFunctionRef(location(ctx), ctx.TYPE().getText(), methodText);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,16 +19,25 @@
|
|||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.FunctionRef;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import static org.elasticsearch.painless.WriterConstants.LAMBDA_BOOTSTRAP_HANDLE;
|
||||
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
|
||||
/**
|
||||
* Represents a function reference.
|
||||
*/
|
||||
public class EFunctionRef extends AExpression {
|
||||
public String type;
|
||||
public String call;
|
||||
public final String type;
|
||||
public final String call;
|
||||
|
||||
private FunctionRef ref;
|
||||
|
||||
public EFunctionRef(Location location, String type, String call) {
|
||||
super(location);
|
||||
|
@ -39,12 +48,48 @@ public class EFunctionRef extends AExpression {
|
|||
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
throw createError(new UnsupportedOperationException("Function references [" + type + "::" + call +
|
||||
"] are not currently supported."));
|
||||
if (expected == null) {
|
||||
ref = null;
|
||||
actual = Definition.getType("String");
|
||||
} else {
|
||||
try {
|
||||
ref = new FunctionRef(expected, type, call);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw createError(e);
|
||||
}
|
||||
actual = expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
if (ref == null) {
|
||||
writer.push(type + "." + call);
|
||||
} else {
|
||||
writer.writeDebugInfo(location);
|
||||
// convert MethodTypes to asm Type for the constant pool.
|
||||
String invokedType = ref.invokedType.toMethodDescriptorString();
|
||||
Type samMethodType = Type.getMethodType(ref.samMethodType.toMethodDescriptorString());
|
||||
Type interfaceType = Type.getMethodType(ref.interfaceMethodType.toMethodDescriptorString());
|
||||
if (ref.needsBridges()) {
|
||||
writer.invokeDynamic(ref.invokedName,
|
||||
invokedType,
|
||||
LAMBDA_BOOTSTRAP_HANDLE,
|
||||
samMethodType,
|
||||
ref.implMethodASM,
|
||||
samMethodType,
|
||||
LambdaMetafactory.FLAG_BRIDGES,
|
||||
1,
|
||||
interfaceType);
|
||||
} else {
|
||||
writer.invokeDynamic(ref.invokedName,
|
||||
invokedType,
|
||||
LAMBDA_BOOTSTRAP_HANDLE,
|
||||
samMethodType,
|
||||
ref.implMethodASM,
|
||||
samMethodType,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public final class LCall extends ALink {
|
|||
}
|
||||
|
||||
throw createError(new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() +
|
||||
"] arguments on type [" + struct.name + "]."));
|
||||
"] arguments on type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,7 +62,7 @@ final class LDefArray extends ALink implements IDefLink {
|
|||
writer.writeDebugInfo(location);
|
||||
|
||||
String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type, index.actual.type);
|
||||
writer.invokeDynamic("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_LOAD);
|
||||
writer.invokeDynamic("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_LOAD, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,6 +70,6 @@ final class LDefArray extends ALink implements IDefLink {
|
|||
writer.writeDebugInfo(location);
|
||||
|
||||
String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, index.actual.type, after.type);
|
||||
writer.invokeDynamic("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_STORE);
|
||||
writer.invokeDynamic("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_STORE, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ final class LDefCall extends ALink implements IDefLink {
|
|||
|
||||
final String name;
|
||||
final List<AExpression> arguments;
|
||||
long recipe;
|
||||
|
||||
LDefCall(Location location, String name, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
@ -46,9 +47,20 @@ final class LDefCall extends ALink implements IDefLink {
|
|||
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (arguments.size() > 63) {
|
||||
// technically, the limitation is just methods with > 63 params, containing method references.
|
||||
// this is because we are lazy and use a long as a bitset. we can always change to a "string" if need be.
|
||||
// but NEED NOT BE. nothing with this many parameters is in the whitelist and we do not support varargs.
|
||||
throw new UnsupportedOperationException("methods with > 63 arguments are currently not supported");
|
||||
}
|
||||
|
||||
recipe = 0;
|
||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||
AExpression expression = arguments.get(argument);
|
||||
|
||||
if (expression instanceof EFunctionRef) {
|
||||
recipe |= (1L << argument); // mark argument as deferred reference
|
||||
}
|
||||
expression.internal = true;
|
||||
expression.analyze(variables);
|
||||
expression.expected = expression.actual;
|
||||
|
@ -85,7 +97,7 @@ final class LDefCall extends ALink implements IDefLink {
|
|||
// return value
|
||||
signature.append(after.type.getDescriptor());
|
||||
|
||||
writer.invokeDynamic(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.METHOD_CALL);
|
||||
writer.invokeDynamic(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.METHOD_CALL, recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ final class LDefField extends ALink implements IDefLink {
|
|||
writer.writeDebugInfo(location);
|
||||
|
||||
String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.LOAD);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.LOAD, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,6 +67,6 @@ final class LDefField extends ALink implements IDefLink {
|
|||
writer.writeDebugInfo(location);
|
||||
|
||||
String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, after.type);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.STORE);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.STORE, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.painless.node;
|
|||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Constructor;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
|
@ -37,7 +37,7 @@ public final class LNewObj extends ALink {
|
|||
final String type;
|
||||
final List<AExpression> arguments;
|
||||
|
||||
Constructor constructor;
|
||||
Method constructor;
|
||||
|
||||
public LNewObj(Location location, String type, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
@ -63,7 +63,7 @@ public final class LNewObj extends ALink {
|
|||
}
|
||||
|
||||
Struct struct = type.struct;
|
||||
constructor = struct.constructors.get(new Definition.MethodKey("new", arguments.size()));
|
||||
constructor = struct.constructors.get(new Definition.MethodKey("<init>", arguments.size()));
|
||||
|
||||
if (constructor != null) {
|
||||
Type[] types = new Type[constructor.arguments.size()];
|
||||
|
|
|
@ -197,7 +197,7 @@ public class SEach extends AStatement {
|
|||
if (method == null) {
|
||||
Type itr = Definition.getType("Iterator");
|
||||
String desc = org.objectweb.asm.Type.getMethodDescriptor(itr.type, Definition.DEF_TYPE.type);
|
||||
writer.invokeDynamic("iterator", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ITERATOR);
|
||||
writer.invokeDynamic("iterator", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ITERATOR, 0);
|
||||
} else if (java.lang.reflect.Modifier.isInterface(method.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(method.owner.type, method.method);
|
||||
} else {
|
||||
|
|
|
@ -63,6 +63,7 @@ class Boolean -> java.lang.Boolean extends Comparable,Object {
|
|||
Boolean FALSE
|
||||
boolean booleanValue()
|
||||
int compare(boolean,boolean)
|
||||
int compareTo(Boolean)
|
||||
int hashCode(boolean)
|
||||
boolean logicalAnd(boolean,boolean)
|
||||
boolean logicalOr(boolean,boolean)
|
||||
|
@ -78,6 +79,7 @@ class Byte -> java.lang.Byte extends Number,Comparable,Object {
|
|||
byte MIN_VALUE
|
||||
int SIZE
|
||||
int compare(byte,byte)
|
||||
int compareTo(Byte)
|
||||
Byte decode(String)
|
||||
int hashCode(byte)
|
||||
byte parseByte(String)
|
||||
|
@ -163,6 +165,7 @@ class Character -> java.lang.Character extends Comparable,Object {
|
|||
int codePointBefore(CharSequence,int)
|
||||
int codePointCount(CharSequence,int,int)
|
||||
int compare(char,char)
|
||||
int compareTo(Character)
|
||||
int digit(int,int)
|
||||
char forDigit(int,int)
|
||||
byte getDirectionality(int)
|
||||
|
@ -454,6 +457,7 @@ class Double -> java.lang.Double extends Number,Comparable,Object {
|
|||
double POSITIVE_INFINITY
|
||||
int SIZE
|
||||
int compare(double,double)
|
||||
int compareTo(Double)
|
||||
long doubleToLongBits(double)
|
||||
long doubleToRawLongBits(double)
|
||||
int hashCode(double)
|
||||
|
@ -473,6 +477,7 @@ class Double -> java.lang.Double extends Number,Comparable,Object {
|
|||
}
|
||||
|
||||
class Enum -> java.lang.Enum extends Comparable,Object {
|
||||
int compareTo(Enum)
|
||||
String name();
|
||||
int ordinal();
|
||||
}
|
||||
|
@ -489,6 +494,7 @@ class Float -> java.lang.Float extends Number,Comparable,Object {
|
|||
float POSITIVE_INFINITY
|
||||
int SIZE
|
||||
int compare(float,float)
|
||||
int compareTo(Float)
|
||||
int floatToIntBits(float)
|
||||
int floatToRawIntBits(float)
|
||||
int hashCode(float)
|
||||
|
@ -516,6 +522,7 @@ class Integer -> java.lang.Integer extends Number,Comparable,Object {
|
|||
int SIZE
|
||||
int bitCount(int)
|
||||
int compare(int,int)
|
||||
int compareTo(Integer)
|
||||
int compareUnsigned(int,int)
|
||||
Integer decode(String)
|
||||
int divideUnsigned(int,int)
|
||||
|
@ -555,6 +562,7 @@ class Long -> java.lang.Long extends Number,Comparable,Object {
|
|||
int SIZE
|
||||
int bitCount(long)
|
||||
int compare(long,long)
|
||||
int compareTo(Long)
|
||||
int compareUnsigned(long,long)
|
||||
Long decode(String)
|
||||
long divideUnsigned(long,long)
|
||||
|
@ -587,7 +595,7 @@ class Long -> java.lang.Long extends Number,Comparable,Object {
|
|||
Long valueOf(String,int)
|
||||
}
|
||||
|
||||
class Math -> java.lang.Math {
|
||||
class Math -> java.lang.Math extends Object {
|
||||
double E
|
||||
double PI
|
||||
double abs(double)
|
||||
|
@ -658,6 +666,7 @@ class Short -> java.lang.Short extends Number,Comparable,Object {
|
|||
short MIN_VALUE
|
||||
int SIZE
|
||||
int compare(short,short)
|
||||
int compareTo(Short)
|
||||
Short decode(String)
|
||||
int hashCode(short)
|
||||
short parseShort(String)
|
||||
|
@ -679,7 +688,7 @@ class StackTraceElement -> java.lang.StackTraceElement extends Object {
|
|||
boolean isNativeMethod()
|
||||
}
|
||||
|
||||
class StrictMath -> java.lang.StrictMath {
|
||||
class StrictMath -> java.lang.StrictMath extends Object {
|
||||
double E
|
||||
double PI
|
||||
double abs(double)
|
||||
|
@ -726,6 +735,7 @@ class String -> java.lang.String extends CharSequence,Comparable,Object {
|
|||
int codePointAt(int)
|
||||
int codePointBefore(int)
|
||||
int codePointCount(int,int)
|
||||
int compareTo(String)
|
||||
int compareToIgnoreCase(String)
|
||||
String concat(String)
|
||||
boolean contains(CharSequence)
|
||||
|
|
|
@ -35,6 +35,7 @@ class BigDecimal -> java.math.BigDecimal extends Number,Comparable,Object {
|
|||
BigDecimal add(BigDecimal)
|
||||
BigDecimal add(BigDecimal,MathContext)
|
||||
byte byteValueExact()
|
||||
int compareTo(BigDecimal)
|
||||
BigDecimal divide(BigDecimal)
|
||||
BigDecimal divide(BigDecimal,MathContext)
|
||||
BigDecimal[] divideAndRemainder(BigDecimal)
|
||||
|
@ -90,6 +91,7 @@ class BigInteger -> java.math.BigInteger extends Number,Comparable,Object {
|
|||
int bitLength()
|
||||
byte byteValueExact()
|
||||
BigInteger clearBit(int)
|
||||
int compareTo(BigInteger)
|
||||
BigInteger divide(BigInteger)
|
||||
BigInteger[] divideAndRemainder(BigInteger)
|
||||
BigInteger flipBit(int)
|
||||
|
|
|
@ -149,6 +149,7 @@ class CollationElementIterator -> java.text.CollationElementIterator extends Obj
|
|||
}
|
||||
|
||||
class CollationKey -> java.text.CollationKey extends Comparable,Object {
|
||||
int compareTo(CollationKey)
|
||||
String getSourceString()
|
||||
byte[] toByteArray()
|
||||
}
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
|
||||
#### Interfaces
|
||||
|
||||
class ChronoLocalDate -> java.time.chrono.ChronoLocalDate extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster {
|
||||
class ChronoLocalDate -> java.time.chrono.ChronoLocalDate extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable {
|
||||
ChronoLocalDateTime atTime(LocalTime)
|
||||
int compareTo(ChronoLocalDate)
|
||||
boolean equals(Object)
|
||||
String format(DateTimeFormatter)
|
||||
ChronoLocalDate from(TemporalAccessor)
|
||||
|
@ -50,8 +51,9 @@ class ChronoLocalDate -> java.time.chrono.ChronoLocalDate extends Comparable,Tem
|
|||
ChronoLocalDate with(TemporalField,long)
|
||||
}
|
||||
|
||||
class ChronoLocalDateTime -> java.time.chrono.ChronoLocalDateTime extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster {
|
||||
class ChronoLocalDateTime -> java.time.chrono.ChronoLocalDateTime extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable {
|
||||
ChronoZonedDateTime atZone(ZoneId)
|
||||
int compareTo(ChronoLocalDateTime)
|
||||
boolean equals(Object)
|
||||
String format(DateTimeFormatter)
|
||||
ChronoLocalDateTime from(TemporalAccessor)
|
||||
|
@ -75,6 +77,7 @@ class ChronoLocalDateTime -> java.time.chrono.ChronoLocalDateTime extends Compar
|
|||
}
|
||||
|
||||
class Chronology -> java.time.chrono.Chronology extends Comparable {
|
||||
int compareTo(Chronology)
|
||||
ChronoLocalDate date(TemporalAccessor)
|
||||
ChronoLocalDate date(Era,int,int,int)
|
||||
ChronoLocalDate date(int,int,int)
|
||||
|
@ -121,7 +124,8 @@ class ChronoPeriod -> java.time.chrono.ChronoPeriod extends TemporalAmount {
|
|||
String toString()
|
||||
}
|
||||
|
||||
class ChronoZonedDateTime -> java.time.chrono.ChronoZonedDateTime extends Comparable,Temporal,TemporalAccessor {
|
||||
class ChronoZonedDateTime -> java.time.chrono.ChronoZonedDateTime extends Temporal,TemporalAccessor,Comparable {
|
||||
int compareTo(ChronoZonedDateTime)
|
||||
boolean equals(Object)
|
||||
String format(DateTimeFormatter)
|
||||
ChronoZonedDateTime from(TemporalAccessor)
|
||||
|
@ -158,10 +162,10 @@ class Era -> java.time.chrono.Era extends TemporalAccessor,TemporalAdjuster {
|
|||
|
||||
#### Classes
|
||||
|
||||
class AbstractChronology -> java.time.chrono.Chronology extends Comparable,Chronology,Object {
|
||||
class AbstractChronology -> java.time.chrono.Chronology extends Chronology,Comparable,Object {
|
||||
}
|
||||
|
||||
class HijrahChronology -> java.time.chrono.HijrahChronology extends AbstractChronology,Comparable,Chronology,Object {
|
||||
class HijrahChronology -> java.time.chrono.HijrahChronology extends AbstractChronology,Chronology,Comparable,Object {
|
||||
HijrahChronology INSTANCE
|
||||
HijrahDate date(TemporalAccessor)
|
||||
HijrahDate date(int,int,int)
|
||||
|
@ -172,25 +176,26 @@ class HijrahChronology -> java.time.chrono.HijrahChronology extends AbstractChro
|
|||
HijrahDate dateYearDay(int,int)
|
||||
HijrahDate dateYearDay(Era,int,int)
|
||||
HijrahEra eraOf(int)
|
||||
HijrahDate resolveDate(Map,ResolverStyle)
|
||||
}
|
||||
|
||||
class HijrahDate -> java.time.chrono.HijrahDate extends Comparable,ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
HijrahDate now()
|
||||
HijrahDate now(ZoneId)
|
||||
HijrahDate of(int,int,int)
|
||||
class HijrahDate -> java.time.chrono.HijrahDate extends ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
HijrahDate from(TemporalAccessor)
|
||||
HijrahChronology getChronology()
|
||||
HijrahEra getEra()
|
||||
HijrahDate minus(TemporalAmount)
|
||||
HijrahDate minus(long,TemporalUnit)
|
||||
HijrahDate now()
|
||||
HijrahDate now(ZoneId)
|
||||
HijrahDate of(int,int,int)
|
||||
HijrahDate plus(TemporalAmount)
|
||||
HijrahDate plus(long,TemporalUnit)
|
||||
HijrahDate with(TemporalField,long)
|
||||
HijrahDate with(TemporalAdjuster)
|
||||
HijrahDate withVariant(HijrahChronology)
|
||||
HijrahDate plus(TemporalAmount)
|
||||
HijrahDate minus(TemporalAmount)
|
||||
HijrahDate plus(long,TemporalUnit)
|
||||
HijrahDate minus(long,TemporalUnit)
|
||||
}
|
||||
|
||||
class IsoChronology -> java.time.chrono.IsoChronology extends AbstractChronology,Comparable,Chronology,Object {
|
||||
class IsoChronology -> java.time.chrono.IsoChronology extends AbstractChronology,Chronology,Comparable,Object {
|
||||
IsoChronology INSTANCE
|
||||
LocalDate date(TemporalAccessor)
|
||||
LocalDate date(int,int,int)
|
||||
|
@ -201,9 +206,14 @@ class IsoChronology -> java.time.chrono.IsoChronology extends AbstractChronology
|
|||
LocalDate dateYearDay(int,int)
|
||||
LocalDate dateYearDay(Era,int,int)
|
||||
IsoEra eraOf(int)
|
||||
LocalDateTime localDateTime(TemporalAccessor)
|
||||
Period period(int,int,int)
|
||||
LocalDate resolveDate(Map,ResolverStyle)
|
||||
ZonedDateTime zonedDateTime(TemporalAccessor)
|
||||
ZonedDateTime zonedDateTime(Instant,ZoneId)
|
||||
}
|
||||
|
||||
class JapaneseChronology -> java.time.chrono.JapaneseChronology extends AbstractChronology,Comparable,Chronology,Object {
|
||||
class JapaneseChronology -> java.time.chrono.JapaneseChronology extends AbstractChronology,Chronology,Comparable,Object {
|
||||
JapaneseChronology INSTANCE
|
||||
JapaneseDate date(TemporalAccessor)
|
||||
JapaneseDate date(int,int,int)
|
||||
|
@ -214,9 +224,10 @@ class JapaneseChronology -> java.time.chrono.JapaneseChronology extends Abstract
|
|||
JapaneseDate dateYearDay(int,int)
|
||||
JapaneseDate dateYearDay(Era,int,int)
|
||||
JapaneseEra eraOf(int)
|
||||
JapaneseDate resolveDate(Map,ResolverStyle)
|
||||
}
|
||||
|
||||
class JapaneseDate -> java.time.chrono.JapaneseDate extends Comparable,ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class JapaneseDate -> java.time.chrono.JapaneseDate extends ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
JapaneseDate now()
|
||||
JapaneseDate now(ZoneId)
|
||||
JapaneseDate of(int,int,int)
|
||||
|
@ -242,7 +253,7 @@ class JapaneseEra -> java.time.chrono.JapaneseEra extends Era,TemporalAccessor,T
|
|||
JapaneseEra[] values()
|
||||
}
|
||||
|
||||
class MinguoChronology -> java.time.chrono.MinguoChronology extends AbstractChronology,Comparable,Chronology,Object {
|
||||
class MinguoChronology -> java.time.chrono.MinguoChronology extends AbstractChronology,Chronology,Comparable,Object {
|
||||
MinguoChronology INSTANCE
|
||||
MinguoDate date(TemporalAccessor)
|
||||
MinguoDate date(int,int,int)
|
||||
|
@ -253,9 +264,10 @@ class MinguoChronology -> java.time.chrono.MinguoChronology extends AbstractChro
|
|||
MinguoDate dateYearDay(int,int)
|
||||
MinguoDate dateYearDay(Era,int,int)
|
||||
MinguoEra eraOf(int)
|
||||
MinguoDate resolveDate(Map,ResolverStyle)
|
||||
}
|
||||
|
||||
class MinguoDate -> java.time.chrono.MinguoDate extends Comparable,ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class MinguoDate -> java.time.chrono.MinguoDate extends ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
MinguoDate now()
|
||||
MinguoDate now(ZoneId)
|
||||
MinguoDate of(int,int,int)
|
||||
|
@ -270,7 +282,7 @@ class MinguoDate -> java.time.chrono.MinguoDate extends Comparable,ChronoLocalDa
|
|||
MinguoDate minus(long,TemporalUnit)
|
||||
}
|
||||
|
||||
class ThaiBuddhistChronology -> java.time.chrono.ThaiBuddhistChronology extends AbstractChronology,Comparable,Chronology,Object {
|
||||
class ThaiBuddhistChronology -> java.time.chrono.ThaiBuddhistChronology extends AbstractChronology,Chronology,Comparable,Object {
|
||||
ThaiBuddhistChronology INSTANCE
|
||||
ThaiBuddhistDate date(TemporalAccessor)
|
||||
ThaiBuddhistDate date(int,int,int)
|
||||
|
@ -281,9 +293,10 @@ class ThaiBuddhistChronology -> java.time.chrono.ThaiBuddhistChronology extends
|
|||
ThaiBuddhistDate dateYearDay(int,int)
|
||||
ThaiBuddhistDate dateYearDay(Era,int,int)
|
||||
ThaiBuddhistEra eraOf(int)
|
||||
ThaiBuddhistDate resolveDate(Map,ResolverStyle)
|
||||
}
|
||||
|
||||
class ThaiBuddhistDate -> java.time.chrono.ThaiBuddhistDate extends Comparable,ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class ThaiBuddhistDate -> java.time.chrono.ThaiBuddhistDate extends ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
ThaiBuddhistDate now()
|
||||
ThaiBuddhistDate now(ZoneId)
|
||||
ThaiBuddhistDate of(int,int,int)
|
||||
|
|
|
@ -43,6 +43,7 @@ class Duration -> java.time.Duration extends Comparable,TemporalAmount,Object {
|
|||
Duration ZERO
|
||||
Duration abs()
|
||||
Duration between(Temporal,Temporal)
|
||||
int compareTo(Duration)
|
||||
Duration dividedBy(long)
|
||||
Duration from(TemporalAmount)
|
||||
int getNano()
|
||||
|
@ -91,6 +92,7 @@ class Instant -> java.time.Instant extends Comparable,Temporal,TemporalAccessor,
|
|||
Instant MIN
|
||||
OffsetDateTime atOffset(ZoneOffset)
|
||||
ZonedDateTime atZone(ZoneId)
|
||||
int compareTo(Instant)
|
||||
Instant from(TemporalAccessor)
|
||||
long getEpochSecond()
|
||||
int getNano()
|
||||
|
@ -118,7 +120,7 @@ class Instant -> java.time.Instant extends Comparable,Temporal,TemporalAccessor,
|
|||
Instant with(TemporalField,long)
|
||||
}
|
||||
|
||||
class LocalDate -> java.time.LocalDate extends Comparable,ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class LocalDate -> java.time.LocalDate extends ChronoLocalDate,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
LocalDate MAX
|
||||
LocalDate MIN
|
||||
LocalDateTime atStartOfDay()
|
||||
|
@ -154,6 +156,7 @@ class LocalDate -> java.time.LocalDate extends Comparable,ChronoLocalDate,Tempor
|
|||
LocalDate plusMonths(long)
|
||||
LocalDate plusWeeks(long)
|
||||
LocalDate plusDays(long)
|
||||
Period until(ChronoLocalDate)
|
||||
LocalDate with(TemporalAdjuster)
|
||||
LocalDate with(TemporalField,long)
|
||||
LocalDate withDayOfMonth(int)
|
||||
|
@ -162,7 +165,7 @@ class LocalDate -> java.time.LocalDate extends Comparable,ChronoLocalDate,Tempor
|
|||
LocalDate withYear(int)
|
||||
}
|
||||
|
||||
class LocalDateTime -> java.time.LocalDateTime extends Comparable,ChronoLocalDateTime,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class LocalDateTime -> java.time.LocalDateTime extends ChronoLocalDateTime,Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
LocalDateTime MIN
|
||||
LocalDateTime MAX
|
||||
OffsetDateTime atOffset(ZoneOffset)
|
||||
|
@ -208,6 +211,7 @@ class LocalDateTime -> java.time.LocalDateTime extends Comparable,ChronoLocalDat
|
|||
LocalDateTime plusSeconds(long)
|
||||
LocalDateTime plusWeeks(long)
|
||||
LocalDateTime plusYears(long)
|
||||
LocalDate toLocalDate()
|
||||
LocalDateTime truncatedTo(TemporalUnit)
|
||||
LocalDateTime with(TemporalAdjuster)
|
||||
LocalDateTime with(TemporalField,long)
|
||||
|
@ -220,13 +224,14 @@ class LocalDateTime -> java.time.LocalDateTime extends Comparable,ChronoLocalDat
|
|||
LocalDateTime withYear(int)
|
||||
}
|
||||
|
||||
class LocalTime -> java.time.LocalTime extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class LocalTime -> java.time.LocalTime extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
LocalTime MAX
|
||||
LocalTime MIDNIGHT
|
||||
LocalTime MIN
|
||||
LocalTime NOON
|
||||
LocalDateTime atDate(LocalDate)
|
||||
OffsetTime atOffset(ZoneOffset)
|
||||
int compareTo(LocalTime)
|
||||
String format(DateTimeFormatter)
|
||||
LocalTime from(TemporalAccessor)
|
||||
int getHour()
|
||||
|
@ -267,8 +272,9 @@ class LocalTime -> java.time.LocalTime extends Comparable,Temporal,TemporalAcces
|
|||
LocalTime withSecond(int)
|
||||
}
|
||||
|
||||
class MonthDay -> java.time.MonthDay extends Comparable,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class MonthDay -> java.time.MonthDay extends TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
LocalDate atYear(int)
|
||||
int compareTo(MonthDay)
|
||||
String format(DateTimeFormatter)
|
||||
MonthDay from(TemporalAccessor)
|
||||
int getMonthValue()
|
||||
|
@ -287,11 +293,12 @@ class MonthDay -> java.time.MonthDay extends Comparable,TemporalAccessor,Tempora
|
|||
MonthDay withMonth(int)
|
||||
}
|
||||
|
||||
class OffsetDateTime -> java.time.OffsetDateTime extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class OffsetDateTime -> java.time.OffsetDateTime extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
OffsetDateTime MAX
|
||||
OffsetDateTime MIN
|
||||
ZonedDateTime atZoneSameInstant(ZoneId)
|
||||
ZonedDateTime atZoneSimilarLocal(ZoneId)
|
||||
int compareTo(OffsetDateTime)
|
||||
String format(DateTimeFormatter)
|
||||
OffsetDateTime from(TemporalAccessor)
|
||||
int getDayOfMonth()
|
||||
|
@ -359,9 +366,10 @@ class OffsetDateTime -> java.time.OffsetDateTime extends Comparable,Temporal,Tem
|
|||
OffsetDateTime withOffsetSameInstant(ZoneOffset)
|
||||
}
|
||||
|
||||
class OffsetTime -> java.time.OffsetTime extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class OffsetTime -> java.time.OffsetTime extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
OffsetTime MAX
|
||||
OffsetTime MIN
|
||||
int compareTo(OffsetTime)
|
||||
String format(DateTimeFormatter)
|
||||
OffsetTime from(TemporalAccessor)
|
||||
int getHour()
|
||||
|
@ -434,12 +442,13 @@ class Period -> java.time.Period extends ChronoPeriod,TemporalAmount,Object {
|
|||
Period withYears(int)
|
||||
}
|
||||
|
||||
class Year -> java.time.Year extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class Year -> java.time.Year extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
int MAX_VALUE
|
||||
int MIN_VALUE
|
||||
LocalDate atDay(int)
|
||||
YearMonth atMonth(int)
|
||||
LocalDate atMonthDay(MonthDay)
|
||||
int compareTo(Year)
|
||||
String format(DateTimeFormatter)
|
||||
Year from(TemporalAccessor)
|
||||
int getValue()
|
||||
|
@ -463,9 +472,10 @@ class Year -> java.time.Year extends Comparable,Temporal,TemporalAccessor,Tempor
|
|||
Year with(TemporalField,long)
|
||||
}
|
||||
|
||||
class YearMonth -> java.time.YearMonth extends Comparable,Temporal,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class YearMonth -> java.time.YearMonth extends Temporal,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
LocalDate atDay(int)
|
||||
LocalDate atEndOfMonth()
|
||||
int compareTo(YearMonth)
|
||||
String format(DateTimeFormatter)
|
||||
YearMonth from(TemporalAccessor)
|
||||
Month getMonth()
|
||||
|
@ -496,7 +506,7 @@ class YearMonth -> java.time.YearMonth extends Comparable,Temporal,TemporalAcces
|
|||
YearMonth withMonth(int)
|
||||
}
|
||||
|
||||
class ZonedDateTime -> java.time.ZonedDateTime extends Comparable,ChronoZonedDateTime,Temporal,TemporalAccessor,Object {
|
||||
class ZonedDateTime -> java.time.ZonedDateTime extends ChronoZonedDateTime,Temporal,TemporalAccessor,Comparable,Object {
|
||||
int getDayOfMonth()
|
||||
DayOfWeek getDayOfWeek()
|
||||
int getDayOfYear()
|
||||
|
@ -589,7 +599,7 @@ class ZoneOffset -> java.time.ZoneOffset extends ZoneId,Object {
|
|||
|
||||
#### Enums
|
||||
|
||||
class DayOfWeek -> java.time.DayOfWeek extends Enum,Comparable,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class DayOfWeek -> java.time.DayOfWeek extends Enum,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
DayOfWeek FRIDAY
|
||||
DayOfWeek MONDAY
|
||||
DayOfWeek SATURDAY
|
||||
|
@ -607,7 +617,7 @@ class DayOfWeek -> java.time.DayOfWeek extends Enum,Comparable,TemporalAccessor,
|
|||
DayOfWeek[] values()
|
||||
}
|
||||
|
||||
class Month -> java.time.Month extends Enum,Comparable,TemporalAccessor,TemporalAdjuster,Object {
|
||||
class Month -> java.time.Month extends Enum,TemporalAccessor,TemporalAdjuster,Comparable,Object {
|
||||
Month APRIL
|
||||
Month AUGUST
|
||||
Month DECEMBER
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#### Classes
|
||||
|
||||
class ZoneOffsetTransition -> java.time.zone.ZoneOffsetTransition extends Comparable,Object {
|
||||
int compareTo(ZoneOffsetTransition)
|
||||
LocalDateTime getDateTimeAfter()
|
||||
LocalDateTime getDateTimeBefore()
|
||||
Duration getDuration()
|
||||
|
|
|
@ -454,6 +454,7 @@ class Calendar -> java.util.Calendar extends Comparable,Object {
|
|||
void clear()
|
||||
void clear(int)
|
||||
def clone()
|
||||
int compareTo(Calendar)
|
||||
int get(int)
|
||||
int getActualMaximum(int)
|
||||
int getActualMinimum(int)
|
||||
|
@ -584,6 +585,7 @@ class Date -> java.util.Date extends Comparable,Object {
|
|||
boolean after(Date)
|
||||
boolean before(Date)
|
||||
def clone()
|
||||
int compareTo(Date)
|
||||
Date from(Instant)
|
||||
long getTime()
|
||||
void setTime(long)
|
||||
|
@ -999,6 +1001,7 @@ class TreeSet -> java.util.TreeSet extends AbstractSet,NavigableSet,SortedSet,Se
|
|||
|
||||
class UUID -> java.util.UUID extends Comparable,Object {
|
||||
UUID <init>(long,long)
|
||||
int compareTo(UUID)
|
||||
int clockSequence()
|
||||
UUID fromString(String)
|
||||
long getLeastSignificantBits()
|
||||
|
@ -1054,101 +1057,101 @@ class Locale.FilteringMode -> java.util.Locale$FilteringMode extends Enum,Compar
|
|||
|
||||
#### Exceptions
|
||||
|
||||
class ConcurrentModificationException -> java.util.ConcurrentModificationException extends RuntimeException,Exception {
|
||||
class ConcurrentModificationException -> java.util.ConcurrentModificationException extends RuntimeException,Exception,Object {
|
||||
ConcurrentModificationException <init>()
|
||||
ConcurrentModificationException <init>(String)
|
||||
}
|
||||
|
||||
class DuplicateFormatFlagsException -> java.util.DuplicateFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class DuplicateFormatFlagsException -> java.util.DuplicateFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
DuplicateFormatFlagsException <init>(String)
|
||||
String getFlags()
|
||||
}
|
||||
|
||||
class EmptyStackException -> java.util.EmptyStackException extends RuntimeException,Exception {
|
||||
class EmptyStackException -> java.util.EmptyStackException extends RuntimeException,Exception,Object {
|
||||
EmptyStackException <init>()
|
||||
}
|
||||
|
||||
class FormatFlagsConversionMismatchException -> java.util.FormatFlagsConversionMismatchException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class FormatFlagsConversionMismatchException -> java.util.FormatFlagsConversionMismatchException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
FormatFlagsConversionMismatchException <init>(String,char)
|
||||
char getConversion()
|
||||
String getFlags()
|
||||
}
|
||||
|
||||
class FormatterClosedException -> java.util.FormatterClosedException extends IllegalStateException,RuntimeException,Exception {
|
||||
class FormatterClosedException -> java.util.FormatterClosedException extends IllegalStateException,RuntimeException,Exception,Object {
|
||||
FormatterClosedException <init>()
|
||||
}
|
||||
|
||||
class IllegalFormatCodePointException -> java.util.IllegalFormatCodePointException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatCodePointException -> java.util.IllegalFormatCodePointException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
IllegalFormatCodePointException <init>(int)
|
||||
int getCodePoint()
|
||||
}
|
||||
|
||||
class IllegalFormatConversionException -> java.util.IllegalFormatConversionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatConversionException -> java.util.IllegalFormatConversionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
char getConversion()
|
||||
}
|
||||
|
||||
class IllegalFormatException -> java.util.IllegalFormatException extends IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatException -> java.util.IllegalFormatException extends IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
}
|
||||
|
||||
class IllegalFormatFlagsException -> java.util.IllegalFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatFlagsException -> java.util.IllegalFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
IllegalFormatFlagsException <init>(String)
|
||||
String getFlags()
|
||||
}
|
||||
|
||||
class IllegalFormatPrecisionException -> java.util.IllegalFormatPrecisionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatPrecisionException -> java.util.IllegalFormatPrecisionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
IllegalFormatPrecisionException <init>(int)
|
||||
int getPrecision()
|
||||
}
|
||||
|
||||
class IllegalFormatWidthException -> java.util.IllegalFormatWidthException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class IllegalFormatWidthException -> java.util.IllegalFormatWidthException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
IllegalFormatWidthException <init>(int)
|
||||
int getWidth()
|
||||
}
|
||||
|
||||
class IllformedLocaleException -> java.util.IllformedLocaleException extends RuntimeException,Exception {
|
||||
class IllformedLocaleException -> java.util.IllformedLocaleException extends RuntimeException,Exception,Object {
|
||||
IllformedLocaleException <init>()
|
||||
IllformedLocaleException <init>(String)
|
||||
IllformedLocaleException <init>(String,int)
|
||||
int getErrorIndex()
|
||||
}
|
||||
|
||||
class InputMismatchException -> java.util.InputMismatchException extends NoSuchElementException,RuntimeException,Exception {
|
||||
class InputMismatchException -> java.util.InputMismatchException extends NoSuchElementException,RuntimeException,Exception,Object {
|
||||
InputMismatchException <init>()
|
||||
InputMismatchException <init>(String)
|
||||
}
|
||||
|
||||
class MissingFormatArgumentException -> java.util.MissingFormatArgumentException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class MissingFormatArgumentException -> java.util.MissingFormatArgumentException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
MissingFormatArgumentException <init>(String)
|
||||
String getFormatSpecifier()
|
||||
}
|
||||
|
||||
class MissingFormatWidthException -> java.util.MissingFormatWidthException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class MissingFormatWidthException -> java.util.MissingFormatWidthException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
MissingFormatWidthException <init>(String)
|
||||
String getFormatSpecifier()
|
||||
}
|
||||
|
||||
class MissingResourceException -> java.util.MissingResourceException extends RuntimeException,Exception {
|
||||
class MissingResourceException -> java.util.MissingResourceException extends RuntimeException,Exception,Object {
|
||||
MissingResourceException <init>(String,String,String)
|
||||
String getClassName()
|
||||
String getKey()
|
||||
}
|
||||
|
||||
class NoSuchElementException -> java.util.NoSuchElementException extends RuntimeException,Exception {
|
||||
class NoSuchElementException -> java.util.NoSuchElementException extends RuntimeException,Exception,Object {
|
||||
NoSuchElementException <init>()
|
||||
NoSuchElementException <init>(String)
|
||||
}
|
||||
|
||||
class TooManyListenersException -> java.util.TooManyListenersException extends Exception {
|
||||
class TooManyListenersException -> java.util.TooManyListenersException extends Exception,Object {
|
||||
TooManyListenersException <init>()
|
||||
TooManyListenersException <init>(String)
|
||||
}
|
||||
|
||||
class UnknownFormatConversionException -> java.util.UnknownFormatConversionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class UnknownFormatConversionException -> java.util.UnknownFormatConversionException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
UnknownFormatConversionException <init>(String)
|
||||
String getConversion()
|
||||
}
|
||||
|
||||
class UnknownFormatFlagsException -> java.util.UnknownFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception {
|
||||
class UnknownFormatFlagsException -> java.util.UnknownFormatFlagsException extends IllegalFormatException,IllegalArgumentException,RuntimeException,Exception,Object {
|
||||
UnknownFormatFlagsException <init>(String)
|
||||
String getFlags()
|
||||
}
|
||||
|
|
|
@ -65,22 +65,26 @@ class org.elasticsearch.common.geo.GeoPoint -> org.elasticsearch.common.geo.GeoP
|
|||
}
|
||||
|
||||
class org.elasticsearch.index.fielddata.ScriptDocValues.Strings -> org.elasticsearch.index.fielddata.ScriptDocValues$Strings extends List,Collection,Iterable,Object {
|
||||
String get(int)
|
||||
String getValue()
|
||||
List getValues()
|
||||
}
|
||||
|
||||
class org.elasticsearch.index.fielddata.ScriptDocValues.Longs -> org.elasticsearch.index.fielddata.ScriptDocValues$Longs extends List,Collection,Iterable,Object {
|
||||
Long get(int)
|
||||
long getValue()
|
||||
List getValues()
|
||||
org.joda.time.ReadableDateTime getDate()
|
||||
}
|
||||
|
||||
class org.elasticsearch.index.fielddata.ScriptDocValues.Doubles -> org.elasticsearch.index.fielddata.ScriptDocValues$Doubles extends List,Collection,Iterable,Object {
|
||||
Double get(int)
|
||||
double getValue()
|
||||
List getValues()
|
||||
}
|
||||
|
||||
class org.elasticsearch.index.fielddata.ScriptDocValues.GeoPoints -> org.elasticsearch.index.fielddata.ScriptDocValues$GeoPoints extends List,Collection,Iterable,Object {
|
||||
org.elasticsearch.common.geo.GeoPoint get(int)
|
||||
org.elasticsearch.common.geo.GeoPoint getValue()
|
||||
List getValues()
|
||||
double getLat()
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -111,7 +110,13 @@ public class BasicAPITests extends ScriptTestCase {
|
|||
assertBytecodeExists("def x = 1D", "INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;");
|
||||
}
|
||||
|
||||
void testStream() {
|
||||
assertEquals(11, exec("params.list.stream().sum()", Collections.singletonMap("list", Arrays.asList(1,2,3,5))));
|
||||
public void testInterfaceDefaultMethods() {
|
||||
assertEquals(1, exec("Map map = new HashMap(); return map.getOrDefault(5,1);"));
|
||||
assertEquals(1, exec("def map = new HashMap(); return map.getOrDefault(5,1);"));
|
||||
}
|
||||
|
||||
public void testInterfacesHaveObject() {
|
||||
assertEquals("{}", exec("Map map = new HashMap(); return map.toString();"));
|
||||
assertEquals("{}", exec("def map = new HashMap(); return map.toString();"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class DefBootstrapTests extends ESTestCase {
|
|||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DefBootstrap.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL, 0);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class DefBootstrapTests extends ESTestCase {
|
|||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DefBootstrap.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL, 0);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class DefBootstrapTests extends ESTestCase {
|
|||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DefBootstrap.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL, 0);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
|
|
@ -20,11 +20,60 @@
|
|||
package org.elasticsearch.painless;
|
||||
|
||||
public class FunctionRefTests extends ScriptTestCase {
|
||||
public void testUnsupported() {
|
||||
expectScriptThrows(UnsupportedOperationException.class, () -> {
|
||||
exec("DoubleStream.Builder builder = DoubleStream.builder();" +
|
||||
"builder.add(2.0); builder.add(1.0); builder.add(3.0);" +
|
||||
"builder.build().reduce(Double::unsupported);");
|
||||
|
||||
public void testStaticMethodReference() {
|
||||
assertEquals(1, exec("List l = new ArrayList(); l.add(2); l.add(1); l.sort(Integer::compare); return l.get(0);"));
|
||||
}
|
||||
|
||||
public void testStaticMethodReferenceDef() {
|
||||
assertEquals(1, exec("def l = new ArrayList(); l.add(2); l.add(1); l.sort(Integer::compare); return l.get(0);"));
|
||||
}
|
||||
|
||||
public void testVirtualMethodReference() {
|
||||
assertEquals(2, exec("List l = new ArrayList(); l.add(1); l.add(1); return l.stream().mapToInt(Integer::intValue).sum();"));
|
||||
}
|
||||
|
||||
public void testVirtualMethodReferenceDef() {
|
||||
assertEquals(2, exec("def l = new ArrayList(); l.add(1); l.add(1); return l.stream().mapToInt(Integer::intValue).sum();"));
|
||||
}
|
||||
|
||||
public void testCtorMethodReference() {
|
||||
assertEquals(3.0D,
|
||||
exec("List l = new ArrayList(); l.add(1.0); l.add(2.0); " +
|
||||
"DoubleStream doubleStream = l.stream().mapToDouble(Double::doubleValue);" +
|
||||
"DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new, " +
|
||||
"DoubleSummaryStatistics::accept, " +
|
||||
"DoubleSummaryStatistics::combine); " +
|
||||
"return stats.getSum()"));
|
||||
}
|
||||
|
||||
public void testCtorMethodReferenceDef() {
|
||||
assertEquals(3.0D,
|
||||
exec("def l = new ArrayList(); l.add(1.0); l.add(2.0); " +
|
||||
"def doubleStream = l.stream().mapToDouble(Double::doubleValue);" +
|
||||
"def stats = doubleStream.collect(DoubleSummaryStatistics::new, " +
|
||||
"DoubleSummaryStatistics::accept, " +
|
||||
"DoubleSummaryStatistics::combine); " +
|
||||
"return stats.getSum()"));
|
||||
}
|
||||
|
||||
public void testMethodMissing() {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("List l = new ArrayList(); l.add(2); l.add(1); l.sort(Integer::bogus); return l.get(0);");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Unknown reference"));
|
||||
}
|
||||
|
||||
public void testNotFunctionalInterface() {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("List l = new ArrayList(); l.add(2); l.add(1); l.add(Integer::bogus); return l.get(0);");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Cannot convert function reference"));
|
||||
}
|
||||
|
||||
public void testIncompatible() {
|
||||
expectScriptThrows(BootstrapMethodError.class, () -> {
|
||||
exec("List l = new ArrayList(); l.add(2); l.add(1); l.sort(String::startsWith); return l.get(0);");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class OverloadTests extends ScriptTestCase {
|
|||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("def x = 'abc123abc'; return x.indexOf('c', 3, 'bogus');");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("dynamic method [indexOf] with signature [(String,int,String)"));
|
||||
assertTrue(expected.getMessage().contains("dynamic method [indexOf]"));
|
||||
}
|
||||
|
||||
public void testConstructor() {
|
||||
|
|
Loading…
Reference in New Issue