initial messy impl of painless method references

This commit is contained in:
Robert Muir 2016-06-06 09:27:19 -04:00
parent ad118eb1e5
commit 6dbf7ab1ea
28 changed files with 659 additions and 248 deletions

View File

@ -73,7 +73,7 @@ decltype
;
funcref
: TYPE REF ID
: TYPE REF ( ID | NEW )
;
declvar

View File

@ -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;
@ -123,7 +126,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...)}
@ -134,41 +182,72 @@ 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 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(Class<?> receiverClass, String name, Object args[], long recipe) {
Method method = lookupMethodInternal(receiverClass, name, args.length - 1);
MethodHandle handle = method.handle;
MethodHandle filters[] = new MethodHandle[args.length];
if (struct != null) {
Method method = struct.methods.get(key);
if (method != null) {
return method.handle;
if (recipe != 0) {
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(method.arguments.get(i - 1).clazz, (String) args[i]);
}
}
}
handle = MethodHandles.filterArguments(handle, 0, filters);
return handle;
}
/** Returns a method handle to an implementation of clazz, given method reference signature */
private static MethodHandle lookupReference(Class<?> clazz, String signature) {
int separator = signature.indexOf('.');
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
MethodHandles.Lookup lookup = MethodHandles.lookup(); // XXX: no lookuping needed, we should pass this from DefBootstrap!
final CallSite callSite;
// XXX: clean all this up to use handles in FunctionRef, deal with ASM in EFunctionRef differently
MethodType invokedType = MethodType.fromMethodDescriptorString(ref.invokedType.getDescriptor(), Def.class.getClassLoader());
MethodType samMethodType = MethodType.fromMethodDescriptorString(ref.samMethodType.getDescriptor(), Def.class.getClassLoader());
MethodType interfaceType = MethodType.fromMethodDescriptorString(ref.interfaceType.getDescriptor(), Def.class.getClassLoader());
try {
if (ref.interfaceType.equals(ref.samMethodType)) {
callSite = LambdaMetafactory.altMetafactory(lookup,
ref.invokedName,
invokedType,
samMethodType,
ref.implMethodHandle,
samMethodType,
0);
} else {
callSite = LambdaMetafactory.altMetafactory(lookup,
ref.invokedName,
invokedType,
samMethodType,
ref.implMethodHandle,
samMethodType,
LambdaMetafactory.FLAG_BRIDGES,
1,
interfaceType);
}
} catch (LambdaConversionException e) {
throw new RuntimeException(e);
}
try {
// create an implementation of the interface (instance)
Object instance = callSite.dynamicInvoker().asType(MethodType.methodType(clazz)).invoke();
// bind this instance as a constant replacement for the parameter
return MethodHandles.dropArguments(MethodHandles.constant(clazz, instance), 0, Object.class);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
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;
}
}
}
}
// no matching methods in whitelist found
throw new IllegalArgumentException("Unable to find dynamic method [" + name + "] with signature [" + type + "] " +
"for class [" + receiverClass.getCanonicalName() + "].");
}
/**
* Looks up handle for a dynamic field getter (field load)

View File

@ -66,12 +66,16 @@ public final class DefBootstrap {
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(String name, MethodType type, int flavor, long recipe) {
super(type);
this.name = name;
this.flavor = flavor;
this.recipe = recipe;
assert recipe == 0 || flavor == METHOD_CALL;
assert Long.bitCount(flavor) <= type.parameterCount();
final MethodHandle fallback = FALLBACK.bindTo(this)
.asCollector(Object[].class, type.parameterCount())
@ -91,10 +95,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 static MethodHandle lookup(int flavor, Class<?> clazz, String name, Object[] args, long recipe) {
switch(flavor) {
case METHOD_CALL:
return Def.lookupMethod(clazz, name, type);
return Def.lookupMethod(clazz, name, args, recipe);
case LOAD:
return Def.lookupGetter(clazz, name);
case STORE:
@ -115,7 +119,7 @@ public final class DefBootstrap {
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
@ -157,8 +161,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(name, type, flavor, recipe);
}
}

View File

@ -24,6 +24,7 @@ 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.Arrays;
import java.util.Collections;
@ -31,6 +32,8 @@ 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 +174,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,7 +275,7 @@ 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;
@ -439,6 +427,18 @@ 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!";
}
}
// precompute runtime classes
for (Struct struct : structsMap.values()) {
addRuntimeClass(struct);
@ -573,7 +573,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 +611,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 +664,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("/");
@ -826,6 +837,32 @@ public final class Definition {
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));
}

View File

@ -0,0 +1,126 @@
/*
* 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.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
/**
* computes "everything you need" to call LambdaMetaFactory, given an expected interface,
* and reference class + method name
*/
public class FunctionRef {
// XXX: this is a mess, because of ASM versus MethodHandle types
// clean all this up, move reflection out of here into definition, etc etc
public final String invokedName;
public final Type invokedType;
public final Handle implMethod;
public final Type samMethodType;
public final Type interfaceType;
public final MethodHandle implMethodHandle;
public FunctionRef(Class<?> expected, String type, String call) {
boolean isCtorReference = "new".equals(call);
// check its really a functional interface
// for e.g. Comparable
java.lang.reflect.Method method = getFunctionalMethod(type, call, expected);
// e.g. compareTo
invokedName = method.getName();
// e.g. (Object)Comparator
invokedType = Type.getMethodType(Type.getType(expected));
// e.g. (Object,Object)int
interfaceType = Type.getMethodType(Type.getMethodDescriptor(method));
// 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.getParameterCount()));
} else {
// look for a static impl first
Definition.Method staticImpl = struct.staticMethods.get(new Definition.MethodKey(call, method.getParameterCount()));
if (staticImpl == null) {
// otherwise a virtual impl
impl = struct.methods.get(new Definition.MethodKey(call, method.getParameterCount()-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;
}
implMethod = new Handle(tag, struct.type.getInternalName(), impl.name, impl.method.getDescriptor());
implMethodHandle = impl.handle;
if (isCtorReference) {
samMethodType = Type.getMethodType(interfaceType.getReturnType(), impl.method.getArgumentTypes());
} else if (Modifier.isStatic(impl.modifiers)) {
samMethodType = Type.getMethodType(impl.method.getReturnType(), impl.method.getArgumentTypes());
} else {
Type[] argTypes = impl.method.getArgumentTypes();
Type[] params = new Type[argTypes.length + 1];
System.arraycopy(argTypes, 0, params, 1, argTypes.length);
params[0] = struct.type;
samMethodType = Type.getMethodType(impl.method.getReturnType(), params);
}
}
static final Set<Definition.MethodKey> OBJECT_METHODS = new HashSet<>();
static {
for (java.lang.reflect.Method m : Object.class.getMethods()) {
OBJECT_METHODS.add(new Definition.MethodKey(m.getName(), m.getParameterCount()));
}
}
// TODO: move all this crap out, to Definition to compute up front
java.lang.reflect.Method getFunctionalMethod(String type, String call, Class<?> clazz) {
if (!clazz.isInterface()) {
throw new IllegalArgumentException("Cannot convert function reference ["
+ type + "::" + call + "] to [" + clazz + "]");
}
for (java.lang.reflect.Method m : clazz.getMethods()) {
if (m.isDefault()) {
continue;
}
if (OBJECT_METHODS.contains(new Definition.MethodKey(m.getName(), m.getParameterCount()))) {
continue;
}
return m;
}
throw new IllegalArgumentException("Cannot convert function reference ["
+ type + "::" + call + "] to [" + clazz + "]");
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -27,6 +27,8 @@ 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.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.BitSet;
@ -62,7 +64,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());
@ -102,6 +104,14 @@ public final class WriterConstants {
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 {

View File

@ -986,6 +986,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);
}
@ -1000,6 +1001,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);
{
@ -1008,7 +1010,12 @@ class PainlessParser extends Parser {
setState(162);
match(REF);
setState(163);
match(ID);
_la = _input.LA(1);
if ( !(_la==NEW || _la==ID) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
}
}
catch (RecognitionException re) {
@ -2623,112 +2630,112 @@ class PainlessParser extends Parser {
"\24\3\24\3\24\3\24\3\24\5\24\u015f\n\24\3\25\3\25\3\25\3\25\3\26\3\26"+
"\3\26\3\26\7\26\u0169\n\26\f\26\16\26\u016c\13\26\5\26\u016e\n\26\3\26"+
"\3\26\3\27\3\27\5\27\u0174\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\u019b\2\61\3\2\2\2\4{"+
"\3\2\2\2\6\177\3\2\2\2\b\u0081\3\2\2\2\n\u008a\3\2\2\2\f\u008e\3\2\2\2"+
"\16\u0090\3\2\2\2\20\u0092\3\2\2\2\22\u009b\3\2\2\2\24\u00a3\3\2\2\2\26"+
"\u00a7\3\2\2\2\30\u00ac\3\2\2\2\32\u00b3\3\2\2\2\34\u00be\3\2\2\2\36\u011b"+
"\3\2\2\2 \u013f\3\2\2\2\"\u0151\3\2\2\2$\u0157\3\2\2\2&\u015e\3\2\2\2"+
"(\u0160\3\2\2\2*\u0164\3\2\2\2,\u0173\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?|\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|\3\2\2\2HI\7\21\2\2IJ\5\b\5\2JK\7\20\2\2KL\7\t\2\2L"+
"M\5\34\17\2MN\7\n\2\2NO\5\32\16\2O|\3\2\2\2PQ\7\22\2\2QS\7\t\2\2RT\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|\3\2\2\2bc\5\20\t"+
"\2cd\5\32\16\2d|\3\2\2\2ef\7\23\2\2f|\5\32\16\2gh\7\24\2\2h|\5\32\16\2"+
"ij\7\25\2\2jk\5\34\17\2kl\5\32\16\2l|\3\2\2\2mn\7\27\2\2np\5\b\5\2oq\5"+
"\30\r\2po\3\2\2\2qr\3\2\2\2rp\3\2\2\2rs\3\2\2\2s|\3\2\2\2tu\7\31\2\2u"+
"v\5\34\17\2vw\5\32\16\2w|\3\2\2\2xy\5\34\17\2yz\5\32\16\2z|\3\2\2\2{\66"+
"\3\2\2\2{@\3\2\2\2{H\3\2\2\2{P\3\2\2\2{b\3\2\2\2{e\3\2\2\2{g\3\2\2\2{"+
"i\3\2\2\2{m\3\2\2\2{t\3\2\2\2{x\3\2\2\2|\5\3\2\2\2}\u0080\5\b\5\2~\u0080"+
"\5\4\3\2\177}\3\2\2\2\177~\3\2\2\2\u0080\7\3\2\2\2\u0081\u0085\7\5\2\2"+
"\u0082\u0084\5\4\3\2\u0083\u0082\3\2\2\2\u0084\u0087\3\2\2\2\u0085\u0083"+
"\3\2\2\2\u0085\u0086\3\2\2\2\u0086\u0088\3\2\2\2\u0087\u0085\3\2\2\2\u0088"+
"\u0089\7\6\2\2\u0089\t\3\2\2\2\u008a\u008b\7\r\2\2\u008b\13\3\2\2\2\u008c"+
"\u008f\5\20\t\2\u008d\u008f\5\34\17\2\u008e\u008c\3\2\2\2\u008e\u008d"+
"\3\2\2\2\u008f\r\3\2\2\2\u0090\u0091\5\34\17\2\u0091\17\3\2\2\2\u0092"+
"\u0093\5\22\n\2\u0093\u0098\5\26\f\2\u0094\u0095\7\f\2\2\u0095\u0097\5"+
"\26\f\2\u0096\u0094\3\2\2\2\u0097\u009a\3\2\2\2\u0098\u0096\3\2\2\2\u0098"+
"\u0099\3\2\2\2\u0099\21\3\2\2\2\u009a\u0098\3\2\2\2\u009b\u00a0\7J\2\2"+
"\u009c\u009d\7\7\2\2\u009d\u009f\7\b\2\2\u009e\u009c\3\2\2\2\u009f\u00a2"+
"\3\2\2\2\u00a0\u009e\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\23\3\2\2\2\u00a2"+
"\u00a0\3\2\2\2\u00a3\u00a4\7J\2\2\u00a4\u00a5\7\63\2\2\u00a5\u00a6\7K"+
"\2\2\u00a6\25\3\2\2\2\u00a7\u00aa\7K\2\2\u00a8\u00a9\7\66\2\2\u00a9\u00ab"+
"\5\34\17\2\u00aa\u00a8\3\2\2\2\u00aa\u00ab\3\2\2\2\u00ab\27\3\2\2\2\u00ac"+
"\u00ad\7\30\2\2\u00ad\u00ae\7\t\2\2\u00ae\u00af\7J\2\2\u00af\u00b0\7K"+
"\2\2\u00b0\u00b1\7\n\2\2\u00b1\u00b2\5\b\5\2\u00b2\31\3\2\2\2\u00b3\u00b4"+
"\t\2\2\2\u00b4\33\3\2\2\2\u00b5\u00b6\b\17\1\2\u00b6\u00b7\5 \21\2\u00b7"+
"\u00b8\t\3\2\2\u00b8\u00b9\5\34\17\3\u00b9\u00ba\b\17\1\2\u00ba\u00bf"+
"\3\2\2\2\u00bb\u00bc\5\36\20\2\u00bc\u00bd\b\17\1\2\u00bd\u00bf\3\2\2"+
"\2\u00be\u00b5\3\2\2\2\u00be\u00bb\3\2\2\2\u00bf\u00fb\3\2\2\2\u00c0\u00c1"+
"\f\16\2\2\u00c1\u00c2\t\4\2\2\u00c2\u00c3\5\34\17\17\u00c3\u00c4\b\17"+
"\1\2\u00c4\u00fa\3\2\2\2\u00c5\u00c6\f\r\2\2\u00c6\u00c7\t\5\2\2\u00c7"+
"\u00c8\5\34\17\16\u00c8\u00c9\b\17\1\2\u00c9\u00fa\3\2\2\2\u00ca\u00cb"+
"\f\f\2\2\u00cb\u00cc\t\6\2\2\u00cc\u00cd\5\34\17\r\u00cd\u00ce\b\17\1"+
"\2\u00ce\u00fa\3\2\2\2\u00cf\u00d0\f\13\2\2\u00d0\u00d1\t\7\2\2\u00d1"+
"\u00d2\5\34\17\f\u00d2\u00d3\b\17\1\2\u00d3\u00fa\3\2\2\2\u00d4\u00d5"+
"\f\n\2\2\u00d5\u00d6\t\b\2\2\u00d6\u00d7\5\34\17\13\u00d7\u00d8\b\17\1"+
"\2\u00d8\u00fa\3\2\2\2\u00d9\u00da\f\t\2\2\u00da\u00db\7,\2\2\u00db\u00dc"+
"\5\34\17\n\u00dc\u00dd\b\17\1\2\u00dd\u00fa\3\2\2\2\u00de\u00df\f\b\2"+
"\2\u00df\u00e0\7-\2\2\u00e0\u00e1\5\34\17\t\u00e1\u00e2\b\17\1\2\u00e2"+
"\u00fa\3\2\2\2\u00e3\u00e4\f\7\2\2\u00e4\u00e5\7.\2\2\u00e5\u00e6\5\34"+
"\17\b\u00e6\u00e7\b\17\1\2\u00e7\u00fa\3\2\2\2\u00e8\u00e9\f\6\2\2\u00e9"+
"\u00ea\7/\2\2\u00ea\u00eb\5\34\17\7\u00eb\u00ec\b\17\1\2\u00ec\u00fa\3"+
"\2\2\2\u00ed\u00ee\f\5\2\2\u00ee\u00ef\7\60\2\2\u00ef\u00f0\5\34\17\6"+
"\u00f0\u00f1\b\17\1\2\u00f1\u00fa\3\2\2\2\u00f2\u00f3\f\4\2\2\u00f3\u00f4"+
"\7\61\2\2\u00f4\u00f5\5\34\17\2\u00f5\u00f6\7\62\2\2\u00f6\u00f7\5\34"+
"\17\4\u00f7\u00f8\b\17\1\2\u00f8\u00fa\3\2\2\2\u00f9\u00c0\3\2\2\2\u00f9"+
"\u00c5\3\2\2\2\u00f9\u00ca\3\2\2\2\u00f9\u00cf\3\2\2\2\u00f9\u00d4\3\2"+
"\2\2\u00f9\u00d9\3\2\2\2\u00f9\u00de\3\2\2\2\u00f9\u00e3\3\2\2\2\u00f9"+
"\u00e8\3\2\2\2\u00f9\u00ed\3\2\2\2\u00f9\u00f2\3\2\2\2\u00fa\u00fd\3\2"+
"\2\2\u00fb\u00f9\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fc\35\3\2\2\2\u00fd\u00fb"+
"\3\2\2\2\u00fe\u00ff\6\20\16\3\u00ff\u0100\t\t\2\2\u0100\u011c\5 \21\2"+
"\u0101\u0102\6\20\17\3\u0102\u0103\5 \21\2\u0103\u0104\t\t\2\2\u0104\u011c"+
"\3\2\2\2\u0105\u0106\6\20\20\3\u0106\u011c\5 \21\2\u0107\u0108\6\20\21"+
"\3\u0108\u0109\t\n\2\2\u0109\u011c\b\20\1\2\u010a\u010b\6\20\22\3\u010b"+
"\u010c\7G\2\2\u010c\u011c\b\20\1\2\u010d\u010e\6\20\23\3\u010e\u010f\7"+
"H\2\2\u010f\u011c\b\20\1\2\u0110\u0111\6\20\24\3\u0111\u0112\7I\2\2\u0112"+
"\u011c\b\20\1\2\u0113\u0114\6\20\25\3\u0114\u0115\t\13\2\2\u0115\u011c"+
"\5\36\20\2\u0116\u0117\7\t\2\2\u0117\u0118\5\22\n\2\u0118\u0119\7\n\2"+
"\2\u0119\u011a\5\36\20\2\u011a\u011c\3\2\2\2\u011b\u00fe\3\2\2\2\u011b"+
"\u0101\3\2\2\2\u011b\u0105\3\2\2\2\u011b\u0107\3\2\2\2\u011b\u010a\3\2"+
"\2\2\u011b\u010d\3\2\2\2\u011b\u0110\3\2\2\2\u011b\u0113\3\2\2\2\u011b"+
"\u0116\3\2\2\2\u011c\37\3\2\2\2\u011d\u0121\5\"\22\2\u011e\u0120\5$\23"+
"\2\u011f\u011e\3\2\2\2\u0120\u0123\3\2\2\2\u0121\u011f\3\2\2\2\u0121\u0122"+
"\3\2\2\2\u0122\u0140\3\2\2\2\u0123\u0121\3\2\2\2\u0124\u0125\5\22\n\2"+
"\u0125\u0129\5&\24\2\u0126\u0128\5$\23\2\u0127\u0126\3\2\2\2\u0128\u012b"+
"\3\2\2\2\u0129\u0127\3\2\2\2\u0129\u012a\3\2\2\2\u012a\u0140\3\2\2\2\u012b"+
"\u0129\3\2\2\2\u012c\u012d\7\26\2\2\u012d\u0132\7J\2\2\u012e\u012f\7\7"+
"\2\2\u012f\u0130\5\34\17\2\u0130\u0131\7\b\2\2\u0131\u0133\3\2\2\2\u0132"+
"\u012e\3\2\2\2\u0133\u0134\3\2\2\2\u0134\u0132\3\2\2\2\u0134\u0135\3\2"+
"\2\2\u0135\u013d\3\2\2\2\u0136\u013a\5&\24\2\u0137\u0139\5$\23\2\u0138"+
"\u0137\3\2\2\2\u0139\u013c\3\2\2\2\u013a\u0138\3\2\2\2\u013a\u013b\3\2"+
"\2\2\u013b\u013e\3\2\2\2\u013c\u013a\3\2\2\2\u013d\u0136\3\2\2\2\u013d"+
"\u013e\3\2\2\2\u013e\u0140\3\2\2\2\u013f\u011d\3\2\2\2\u013f\u0124\3\2"+
"\2\2\u013f\u012c\3\2\2\2\u0140!\3\2\2\2\u0141\u0142\6\22\26\3\u0142\u0143"+
"\7\t\2\2\u0143\u0144\5\34\17\2\u0144\u0145\7\n\2\2\u0145\u0146\b\22\1"+
"\2\u0146\u0152\3\2\2\2\u0147\u0148\6\22\27\3\u0148\u0149\7\t\2\2\u0149"+
"\u014a\5\36\20\2\u014a\u014b\7\n\2\2\u014b\u0152\3\2\2\2\u014c\u0152\7"+
"F\2\2\u014d\u0152\7K\2\2\u014e\u014f\7\26\2\2\u014f\u0150\7J\2\2\u0150"+
"\u0152\5*\26\2\u0151\u0141\3\2\2\2\u0151\u0147\3\2\2\2\u0151\u014c\3\2"+
"\2\2\u0151\u014d\3\2\2\2\u0151\u014e\3\2\2\2\u0152#\3\2\2\2\u0153\u0154"+
"\6\23\30\3\u0154\u0158\5&\24\2\u0155\u0156\6\23\31\3\u0156\u0158\5(\25"+
"\2\u0157\u0153\3\2\2\2\u0157\u0155\3\2\2\2\u0158%\3\2\2\2\u0159\u015a"+
"\7\13\2\2\u015a\u015b\7M\2\2\u015b\u015f\5*\26\2\u015c\u015d\7\13\2\2"+
"\u015d\u015f\t\f\2\2\u015e\u0159\3\2\2\2\u015e\u015c\3\2\2\2\u015f\'\3"+
"\2\2\2\u0160\u0161\7\7\2\2\u0161\u0162\5\34\17\2\u0162\u0163\7\b\2\2\u0163"+
")\3\2\2\2\u0164\u016d\7\t\2\2\u0165\u016a\5,\27\2\u0166\u0167\7\f\2\2"+
"\u0167\u0169\5,\27\2\u0168\u0166\3\2\2\2\u0169\u016c\3\2\2\2\u016a\u0168"+
"\3\2\2\2\u016a\u016b\3\2\2\2\u016b\u016e\3\2\2\2\u016c\u016a\3\2\2\2\u016d"+
"\u0165\3\2\2\2\u016d\u016e\3\2\2\2\u016e\u016f\3\2\2\2\u016f\u0170\7\n"+
"\2\2\u0170+\3\2\2\2\u0171\u0174\5\34\17\2\u0172\u0174\5\24\13\2\u0173"+
"\u0171\3\2\2\2\u0173\u0172\3\2\2\2\u0174-\3\2\2\2!\61>FSW[`r{\177\u0085"+
"\u008e\u0098\u00a0\u00aa\u00be\u00f9\u00fb\u011b\u0121\u0129\u0134\u013a"+
"\u013d\u013f\u0151\u0157\u015e\u016a\u016d\u0173";
"\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\u019b\2\61"+
"\3\2\2\2\4{\3\2\2\2\6\177\3\2\2\2\b\u0081\3\2\2\2\n\u008a\3\2\2\2\f\u008e"+
"\3\2\2\2\16\u0090\3\2\2\2\20\u0092\3\2\2\2\22\u009b\3\2\2\2\24\u00a3\3"+
"\2\2\2\26\u00a7\3\2\2\2\30\u00ac\3\2\2\2\32\u00b3\3\2\2\2\34\u00be\3\2"+
"\2\2\36\u011b\3\2\2\2 \u013f\3\2\2\2\"\u0151\3\2\2\2$\u0157\3\2\2\2&\u015e"+
"\3\2\2\2(\u0160\3\2\2\2*\u0164\3\2\2\2,\u0173\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\2"+
"9:\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?|\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|\3\2\2\2HI\7\21\2\2IJ\5\b\5\2JK\7\20\2\2K"+
"L\7\t\2\2LM\5\34\17\2MN\7\n\2\2NO\5\32\16\2O|\3\2\2\2PQ\7\22\2\2QS\7\t"+
"\2\2RT\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|\3\2\2"+
"\2bc\5\20\t\2cd\5\32\16\2d|\3\2\2\2ef\7\23\2\2f|\5\32\16\2gh\7\24\2\2"+
"h|\5\32\16\2ij\7\25\2\2jk\5\34\17\2kl\5\32\16\2l|\3\2\2\2mn\7\27\2\2n"+
"p\5\b\5\2oq\5\30\r\2po\3\2\2\2qr\3\2\2\2rp\3\2\2\2rs\3\2\2\2s|\3\2\2\2"+
"tu\7\31\2\2uv\5\34\17\2vw\5\32\16\2w|\3\2\2\2xy\5\34\17\2yz\5\32\16\2"+
"z|\3\2\2\2{\66\3\2\2\2{@\3\2\2\2{H\3\2\2\2{P\3\2\2\2{b\3\2\2\2{e\3\2\2"+
"\2{g\3\2\2\2{i\3\2\2\2{m\3\2\2\2{t\3\2\2\2{x\3\2\2\2|\5\3\2\2\2}\u0080"+
"\5\b\5\2~\u0080\5\4\3\2\177}\3\2\2\2\177~\3\2\2\2\u0080\7\3\2\2\2\u0081"+
"\u0085\7\5\2\2\u0082\u0084\5\4\3\2\u0083\u0082\3\2\2\2\u0084\u0087\3\2"+
"\2\2\u0085\u0083\3\2\2\2\u0085\u0086\3\2\2\2\u0086\u0088\3\2\2\2\u0087"+
"\u0085\3\2\2\2\u0088\u0089\7\6\2\2\u0089\t\3\2\2\2\u008a\u008b\7\r\2\2"+
"\u008b\13\3\2\2\2\u008c\u008f\5\20\t\2\u008d\u008f\5\34\17\2\u008e\u008c"+
"\3\2\2\2\u008e\u008d\3\2\2\2\u008f\r\3\2\2\2\u0090\u0091\5\34\17\2\u0091"+
"\17\3\2\2\2\u0092\u0093\5\22\n\2\u0093\u0098\5\26\f\2\u0094\u0095\7\f"+
"\2\2\u0095\u0097\5\26\f\2\u0096\u0094\3\2\2\2\u0097\u009a\3\2\2\2\u0098"+
"\u0096\3\2\2\2\u0098\u0099\3\2\2\2\u0099\21\3\2\2\2\u009a\u0098\3\2\2"+
"\2\u009b\u00a0\7J\2\2\u009c\u009d\7\7\2\2\u009d\u009f\7\b\2\2\u009e\u009c"+
"\3\2\2\2\u009f\u00a2\3\2\2\2\u00a0\u009e\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1"+
"\23\3\2\2\2\u00a2\u00a0\3\2\2\2\u00a3\u00a4\7J\2\2\u00a4\u00a5\7\63\2"+
"\2\u00a5\u00a6\t\2\2\2\u00a6\25\3\2\2\2\u00a7\u00aa\7K\2\2\u00a8\u00a9"+
"\7\66\2\2\u00a9\u00ab\5\34\17\2\u00aa\u00a8\3\2\2\2\u00aa\u00ab\3\2\2"+
"\2\u00ab\27\3\2\2\2\u00ac\u00ad\7\30\2\2\u00ad\u00ae\7\t\2\2\u00ae\u00af"+
"\7J\2\2\u00af\u00b0\7K\2\2\u00b0\u00b1\7\n\2\2\u00b1\u00b2\5\b\5\2\u00b2"+
"\31\3\2\2\2\u00b3\u00b4\t\3\2\2\u00b4\33\3\2\2\2\u00b5\u00b6\b\17\1\2"+
"\u00b6\u00b7\5 \21\2\u00b7\u00b8\t\4\2\2\u00b8\u00b9\5\34\17\3\u00b9\u00ba"+
"\b\17\1\2\u00ba\u00bf\3\2\2\2\u00bb\u00bc\5\36\20\2\u00bc\u00bd\b\17\1"+
"\2\u00bd\u00bf\3\2\2\2\u00be\u00b5\3\2\2\2\u00be\u00bb\3\2\2\2\u00bf\u00fb"+
"\3\2\2\2\u00c0\u00c1\f\16\2\2\u00c1\u00c2\t\5\2\2\u00c2\u00c3\5\34\17"+
"\17\u00c3\u00c4\b\17\1\2\u00c4\u00fa\3\2\2\2\u00c5\u00c6\f\r\2\2\u00c6"+
"\u00c7\t\6\2\2\u00c7\u00c8\5\34\17\16\u00c8\u00c9\b\17\1\2\u00c9\u00fa"+
"\3\2\2\2\u00ca\u00cb\f\f\2\2\u00cb\u00cc\t\7\2\2\u00cc\u00cd\5\34\17\r"+
"\u00cd\u00ce\b\17\1\2\u00ce\u00fa\3\2\2\2\u00cf\u00d0\f\13\2\2\u00d0\u00d1"+
"\t\b\2\2\u00d1\u00d2\5\34\17\f\u00d2\u00d3\b\17\1\2\u00d3\u00fa\3\2\2"+
"\2\u00d4\u00d5\f\n\2\2\u00d5\u00d6\t\t\2\2\u00d6\u00d7\5\34\17\13\u00d7"+
"\u00d8\b\17\1\2\u00d8\u00fa\3\2\2\2\u00d9\u00da\f\t\2\2\u00da\u00db\7"+
",\2\2\u00db\u00dc\5\34\17\n\u00dc\u00dd\b\17\1\2\u00dd\u00fa\3\2\2\2\u00de"+
"\u00df\f\b\2\2\u00df\u00e0\7-\2\2\u00e0\u00e1\5\34\17\t\u00e1\u00e2\b"+
"\17\1\2\u00e2\u00fa\3\2\2\2\u00e3\u00e4\f\7\2\2\u00e4\u00e5\7.\2\2\u00e5"+
"\u00e6\5\34\17\b\u00e6\u00e7\b\17\1\2\u00e7\u00fa\3\2\2\2\u00e8\u00e9"+
"\f\6\2\2\u00e9\u00ea\7/\2\2\u00ea\u00eb\5\34\17\7\u00eb\u00ec\b\17\1\2"+
"\u00ec\u00fa\3\2\2\2\u00ed\u00ee\f\5\2\2\u00ee\u00ef\7\60\2\2\u00ef\u00f0"+
"\5\34\17\6\u00f0\u00f1\b\17\1\2\u00f1\u00fa\3\2\2\2\u00f2\u00f3\f\4\2"+
"\2\u00f3\u00f4\7\61\2\2\u00f4\u00f5\5\34\17\2\u00f5\u00f6\7\62\2\2\u00f6"+
"\u00f7\5\34\17\4\u00f7\u00f8\b\17\1\2\u00f8\u00fa\3\2\2\2\u00f9\u00c0"+
"\3\2\2\2\u00f9\u00c5\3\2\2\2\u00f9\u00ca\3\2\2\2\u00f9\u00cf\3\2\2\2\u00f9"+
"\u00d4\3\2\2\2\u00f9\u00d9\3\2\2\2\u00f9\u00de\3\2\2\2\u00f9\u00e3\3\2"+
"\2\2\u00f9\u00e8\3\2\2\2\u00f9\u00ed\3\2\2\2\u00f9\u00f2\3\2\2\2\u00fa"+
"\u00fd\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fc\35\3\2\2"+
"\2\u00fd\u00fb\3\2\2\2\u00fe\u00ff\6\20\16\3\u00ff\u0100\t\n\2\2\u0100"+
"\u011c\5 \21\2\u0101\u0102\6\20\17\3\u0102\u0103\5 \21\2\u0103\u0104\t"+
"\n\2\2\u0104\u011c\3\2\2\2\u0105\u0106\6\20\20\3\u0106\u011c\5 \21\2\u0107"+
"\u0108\6\20\21\3\u0108\u0109\t\13\2\2\u0109\u011c\b\20\1\2\u010a\u010b"+
"\6\20\22\3\u010b\u010c\7G\2\2\u010c\u011c\b\20\1\2\u010d\u010e\6\20\23"+
"\3\u010e\u010f\7H\2\2\u010f\u011c\b\20\1\2\u0110\u0111\6\20\24\3\u0111"+
"\u0112\7I\2\2\u0112\u011c\b\20\1\2\u0113\u0114\6\20\25\3\u0114\u0115\t"+
"\f\2\2\u0115\u011c\5\36\20\2\u0116\u0117\7\t\2\2\u0117\u0118\5\22\n\2"+
"\u0118\u0119\7\n\2\2\u0119\u011a\5\36\20\2\u011a\u011c\3\2\2\2\u011b\u00fe"+
"\3\2\2\2\u011b\u0101\3\2\2\2\u011b\u0105\3\2\2\2\u011b\u0107\3\2\2\2\u011b"+
"\u010a\3\2\2\2\u011b\u010d\3\2\2\2\u011b\u0110\3\2\2\2\u011b\u0113\3\2"+
"\2\2\u011b\u0116\3\2\2\2\u011c\37\3\2\2\2\u011d\u0121\5\"\22\2\u011e\u0120"+
"\5$\23\2\u011f\u011e\3\2\2\2\u0120\u0123\3\2\2\2\u0121\u011f\3\2\2\2\u0121"+
"\u0122\3\2\2\2\u0122\u0140\3\2\2\2\u0123\u0121\3\2\2\2\u0124\u0125\5\22"+
"\n\2\u0125\u0129\5&\24\2\u0126\u0128\5$\23\2\u0127\u0126\3\2\2\2\u0128"+
"\u012b\3\2\2\2\u0129\u0127\3\2\2\2\u0129\u012a\3\2\2\2\u012a\u0140\3\2"+
"\2\2\u012b\u0129\3\2\2\2\u012c\u012d\7\26\2\2\u012d\u0132\7J\2\2\u012e"+
"\u012f\7\7\2\2\u012f\u0130\5\34\17\2\u0130\u0131\7\b\2\2\u0131\u0133\3"+
"\2\2\2\u0132\u012e\3\2\2\2\u0133\u0134\3\2\2\2\u0134\u0132\3\2\2\2\u0134"+
"\u0135\3\2\2\2\u0135\u013d\3\2\2\2\u0136\u013a\5&\24\2\u0137\u0139\5$"+
"\23\2\u0138\u0137\3\2\2\2\u0139\u013c\3\2\2\2\u013a\u0138\3\2\2\2\u013a"+
"\u013b\3\2\2\2\u013b\u013e\3\2\2\2\u013c\u013a\3\2\2\2\u013d\u0136\3\2"+
"\2\2\u013d\u013e\3\2\2\2\u013e\u0140\3\2\2\2\u013f\u011d\3\2\2\2\u013f"+
"\u0124\3\2\2\2\u013f\u012c\3\2\2\2\u0140!\3\2\2\2\u0141\u0142\6\22\26"+
"\3\u0142\u0143\7\t\2\2\u0143\u0144\5\34\17\2\u0144\u0145\7\n\2\2\u0145"+
"\u0146\b\22\1\2\u0146\u0152\3\2\2\2\u0147\u0148\6\22\27\3\u0148\u0149"+
"\7\t\2\2\u0149\u014a\5\36\20\2\u014a\u014b\7\n\2\2\u014b\u0152\3\2\2\2"+
"\u014c\u0152\7F\2\2\u014d\u0152\7K\2\2\u014e\u014f\7\26\2\2\u014f\u0150"+
"\7J\2\2\u0150\u0152\5*\26\2\u0151\u0141\3\2\2\2\u0151\u0147\3\2\2\2\u0151"+
"\u014c\3\2\2\2\u0151\u014d\3\2\2\2\u0151\u014e\3\2\2\2\u0152#\3\2\2\2"+
"\u0153\u0154\6\23\30\3\u0154\u0158\5&\24\2\u0155\u0156\6\23\31\3\u0156"+
"\u0158\5(\25\2\u0157\u0153\3\2\2\2\u0157\u0155\3\2\2\2\u0158%\3\2\2\2"+
"\u0159\u015a\7\13\2\2\u015a\u015b\7M\2\2\u015b\u015f\5*\26\2\u015c\u015d"+
"\7\13\2\2\u015d\u015f\t\r\2\2\u015e\u0159\3\2\2\2\u015e\u015c\3\2\2\2"+
"\u015f\'\3\2\2\2\u0160\u0161\7\7\2\2\u0161\u0162\5\34\17\2\u0162\u0163"+
"\7\b\2\2\u0163)\3\2\2\2\u0164\u016d\7\t\2\2\u0165\u016a\5,\27\2\u0166"+
"\u0167\7\f\2\2\u0167\u0169\5,\27\2\u0168\u0166\3\2\2\2\u0169\u016c\3\2"+
"\2\2\u016a\u0168\3\2\2\2\u016a\u016b\3\2\2\2\u016b\u016e\3\2\2\2\u016c"+
"\u016a\3\2\2\2\u016d\u0165\3\2\2\2\u016d\u016e\3\2\2\2\u016e\u016f\3\2"+
"\2\2\u016f\u0170\7\n\2\2\u0170+\3\2\2\2\u0171\u0174\5\34\17\2\u0172\u0174"+
"\5\24\13\2\u0173\u0171\3\2\2\2\u0173\u0172\3\2\2\2\u0174-\3\2\2\2!\61"+
">FSW[`r{\177\u0085\u008e\u0098\u00a0\u00aa\u00be\u00f9\u00fb\u011b\u0121"+
"\u0129\u0134\u013a\u013d\u013f\u0151\u0157\u015e\u016a\u016d\u0173";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

@ -391,7 +391,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

View File

@ -19,16 +19,24 @@
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 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 +47,35 @@ 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.clazz, 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);
// 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 :)
if (ref.interfaceType.equals(ref.samMethodType)) {
writer.invokeDynamic(ref.invokedName, ref.invokedType.getDescriptor(), LAMBDA_BOOTSTRAP_HANDLE,
ref.samMethodType, ref.implMethod, ref.samMethodType, 0);
} else {
writer.invokeDynamic(ref.invokedName, ref.invokedType.getDescriptor(), LAMBDA_BOOTSTRAP_HANDLE,
ref.samMethodType, ref.implMethod, ref.samMethodType,
LambdaMetafactory.FLAG_BRIDGES, 1, ref.interfaceType);
}
}
}
}

View File

@ -61,13 +61,13 @@ final class LDefArray extends ALink implements IDefLink {
void load(MethodWriter writer) {
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
void store(MethodWriter writer) {
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);
}
}

View File

@ -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;
@ -84,7 +96,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

View File

@ -58,13 +58,13 @@ final class LDefField extends ALink implements IDefLink {
void load(MethodWriter writer) {
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
void store(MethodWriter writer) {
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);
}
}

View File

@ -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()];

View File

@ -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)

View File

@ -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)

View File

@ -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()
}

View File

@ -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)

View File

@ -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

View File

@ -25,6 +25,7 @@
#### Classes
class ZoneOffsetTransition -> java.time.zone.ZoneOffsetTransition extends Comparable,Object {
int compareTo(ZoneOffsetTransition)
LocalDateTime getDateTimeAfter()
LocalDateTime getDateTimeBefore()
Duration getDuration()

View File

@ -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()
}

View File

@ -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()

View File

@ -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();"));
}
}

View File

@ -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);

View File

@ -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);");
});
}
}

View File

@ -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() {