mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-30 20:08:29 +00:00
Remove Painless Type From Locals, Variables, Params, and ScriptInfo (#28471)
This commit is contained in:
parent
998461c737
commit
df1c696e1d
@ -93,7 +93,7 @@ import static org.objectweb.asm.Opcodes.H_NEWINVOKESPECIAL;
|
|||||||
* private $$Lambda0(List arg$0) {
|
* private $$Lambda0(List arg$0) {
|
||||||
* this.arg$0 = arg$0;
|
* this.arg$0 = arg$0;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public static Consumer create$lambda(List arg$0) {
|
* public static Consumer create$lambda(List arg$0) {
|
||||||
* return new $$Lambda0(arg$0);
|
* return new $$Lambda0(arg$0);
|
||||||
* }
|
* }
|
||||||
@ -212,7 +212,7 @@ public final class LambdaBootstrap {
|
|||||||
ClassWriter cw = beginLambdaClass(lambdaClassName, factoryMethodType.returnType());
|
ClassWriter cw = beginLambdaClass(lambdaClassName, factoryMethodType.returnType());
|
||||||
Capture[] captures = generateCaptureFields(cw, factoryMethodType);
|
Capture[] captures = generateCaptureFields(cw, factoryMethodType);
|
||||||
generateLambdaConstructor(cw, lambdaClassType, factoryMethodType, captures);
|
generateLambdaConstructor(cw, lambdaClassType, factoryMethodType, captures);
|
||||||
|
|
||||||
// Handles the special case where a method reference refers to a ctor (we need a static wrapper method):
|
// Handles the special case where a method reference refers to a ctor (we need a static wrapper method):
|
||||||
if (delegateInvokeType == H_NEWINVOKESPECIAL) {
|
if (delegateInvokeType == H_NEWINVOKESPECIAL) {
|
||||||
assert CTOR_METHOD_NAME.equals(delegateMethodName);
|
assert CTOR_METHOD_NAME.equals(delegateMethodName);
|
||||||
@ -226,7 +226,7 @@ public final class LambdaBootstrap {
|
|||||||
generateInterfaceMethod(cw, factoryMethodType, lambdaClassType, interfaceMethodName,
|
generateInterfaceMethod(cw, factoryMethodType, lambdaClassType, interfaceMethodName,
|
||||||
interfaceMethodType, delegateClassType, delegateInvokeType,
|
interfaceMethodType, delegateClassType, delegateInvokeType,
|
||||||
delegateMethodName, delegateMethodType, captures);
|
delegateMethodName, delegateMethodType, captures);
|
||||||
|
|
||||||
endLambdaClass(cw);
|
endLambdaClass(cw);
|
||||||
|
|
||||||
Class<?> lambdaClass = createLambdaClass(loader, cw, lambdaClassType);
|
Class<?> lambdaClass = createLambdaClass(loader, cw, lambdaClassType);
|
||||||
@ -321,7 +321,7 @@ public final class LambdaBootstrap {
|
|||||||
|
|
||||||
constructor.returnValue();
|
constructor.returnValue();
|
||||||
constructor.endMethod();
|
constructor.endMethod();
|
||||||
|
|
||||||
// Add a factory method, if lambda takes captures.
|
// Add a factory method, if lambda takes captures.
|
||||||
// @uschindler says: I talked with Rémi Forax about this. Technically, a plain ctor
|
// @uschindler says: I talked with Rémi Forax about this. Technically, a plain ctor
|
||||||
// and a MethodHandle to the ctor would be enough - BUT: Hotspot is unable to
|
// and a MethodHandle to the ctor would be enough - BUT: Hotspot is unable to
|
||||||
@ -337,10 +337,10 @@ public final class LambdaBootstrap {
|
|||||||
/**
|
/**
|
||||||
* Generates a factory method to delegate to constructors.
|
* Generates a factory method to delegate to constructors.
|
||||||
*/
|
*/
|
||||||
private static void generateStaticCtorDelegator(ClassWriter cw, int access, String delegatorMethodName,
|
private static void generateStaticCtorDelegator(ClassWriter cw, int access, String delegatorMethodName,
|
||||||
Type delegateClassType, MethodType delegateMethodType) {
|
Type delegateClassType, MethodType delegateMethodType) {
|
||||||
Method wrapperMethod = new Method(delegatorMethodName, delegateMethodType.toMethodDescriptorString());
|
Method wrapperMethod = new Method(delegatorMethodName, delegateMethodType.toMethodDescriptorString());
|
||||||
Method constructorMethod =
|
Method constructorMethod =
|
||||||
new Method(CTOR_METHOD_NAME, delegateMethodType.changeReturnType(void.class).toMethodDescriptorString());
|
new Method(CTOR_METHOD_NAME, delegateMethodType.changeReturnType(void.class).toMethodDescriptorString());
|
||||||
int modifiers = access | ACC_STATIC;
|
int modifiers = access | ACC_STATIC;
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ public final class LambdaBootstrap {
|
|||||||
GeneratorAdapter iface = new GeneratorAdapter(modifiers, lamMeth,
|
GeneratorAdapter iface = new GeneratorAdapter(modifiers, lamMeth,
|
||||||
cw.visitMethod(modifiers, interfaceMethodName, lamDesc, null, null));
|
cw.visitMethod(modifiers, interfaceMethodName, lamDesc, null, null));
|
||||||
iface.visitCode();
|
iface.visitCode();
|
||||||
|
|
||||||
// Loads any captured variables onto the stack.
|
// Loads any captured variables onto the stack.
|
||||||
for (int captureCount = 0; captureCount < captures.length; ++captureCount) {
|
for (int captureCount = 0; captureCount < captures.length; ++captureCount) {
|
||||||
iface.loadThis();
|
iface.loadThis();
|
||||||
@ -473,7 +473,7 @@ public final class LambdaBootstrap {
|
|||||||
private static CallSite createNoCaptureCallSite(
|
private static CallSite createNoCaptureCallSite(
|
||||||
MethodType factoryMethodType,
|
MethodType factoryMethodType,
|
||||||
Class<?> lambdaClass) {
|
Class<?> lambdaClass) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new ConstantCallSite(MethodHandles.constant(
|
return new ConstantCallSite(MethodHandles.constant(
|
||||||
factoryMethodType.returnType(), lambdaClass.getConstructor().newInstance()));
|
factoryMethodType.returnType(), lambdaClass.getConstructor().newInstance()));
|
||||||
@ -503,7 +503,7 @@ public final class LambdaBootstrap {
|
|||||||
* delegate method will use converted types from the interface method. Using
|
* delegate method will use converted types from the interface method. Using
|
||||||
* invokedynamic to make the delegate method call allows
|
* invokedynamic to make the delegate method call allows
|
||||||
* {@link MethodHandle#asType} to be used to do the type conversion instead
|
* {@link MethodHandle#asType} to be used to do the type conversion instead
|
||||||
* of either a lot more code or requiring many {@link Definition.Type}s to be looked
|
* of either a lot more code or requiring many {@link Class}es to be looked
|
||||||
* up at link-time.
|
* up at link-time.
|
||||||
*/
|
*/
|
||||||
public static CallSite delegateBootstrap(Lookup lookup,
|
public static CallSite delegateBootstrap(Lookup lookup,
|
||||||
|
@ -21,7 +21,6 @@ package org.elasticsearch.painless;
|
|||||||
|
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
import org.elasticsearch.painless.Definition.MethodKey;
|
import org.elasticsearch.painless.Definition.MethodKey;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.ScriptClassInfo.MethodArgument;
|
import org.elasticsearch.painless.ScriptClassInfo.MethodArgument;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -58,7 +57,7 @@ public final class Locals {
|
|||||||
* <p>
|
* <p>
|
||||||
* This is just like {@link #newFunctionScope}, except the captured parameters are made read-only.
|
* This is just like {@link #newFunctionScope}, except the captured parameters are made read-only.
|
||||||
*/
|
*/
|
||||||
public static Locals newLambdaScope(Locals programScope, Type returnType, List<Parameter> parameters,
|
public static Locals newLambdaScope(Locals programScope, Class<?> returnType, List<Parameter> parameters,
|
||||||
int captureCount, int maxLoopCounter) {
|
int captureCount, int maxLoopCounter) {
|
||||||
Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
|
Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
@ -68,43 +67,43 @@ public final class Locals {
|
|||||||
// currently, this cannot be allowed, as we swap in real types,
|
// currently, this cannot be allowed, as we swap in real types,
|
||||||
// but that can prevent a store of a different type...
|
// but that can prevent a store of a different type...
|
||||||
boolean isCapture = true;
|
boolean isCapture = true;
|
||||||
locals.addVariable(parameter.location, parameter.type, parameter.name, isCapture);
|
locals.addVariable(parameter.location, parameter.clazz, parameter.name, isCapture);
|
||||||
}
|
}
|
||||||
// Loop counter to catch infinite loops. Internal use only.
|
// Loop counter to catch infinite loops. Internal use only.
|
||||||
if (maxLoopCounter > 0) {
|
if (maxLoopCounter > 0) {
|
||||||
locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
|
locals.defineVariable(null, int.class, LOOP, true);
|
||||||
}
|
}
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a new function scope inside the current scope */
|
/** Creates a new function scope inside the current scope */
|
||||||
public static Locals newFunctionScope(Locals programScope, Type returnType, List<Parameter> parameters, int maxLoopCounter) {
|
public static Locals newFunctionScope(Locals programScope, Class<?> returnType, List<Parameter> parameters, int maxLoopCounter) {
|
||||||
Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
|
Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
|
||||||
for (Parameter parameter : parameters) {
|
for (Parameter parameter : parameters) {
|
||||||
locals.addVariable(parameter.location, parameter.type, parameter.name, false);
|
locals.addVariable(parameter.location, parameter.clazz, parameter.name, false);
|
||||||
}
|
}
|
||||||
// Loop counter to catch infinite loops. Internal use only.
|
// Loop counter to catch infinite loops. Internal use only.
|
||||||
if (maxLoopCounter > 0) {
|
if (maxLoopCounter > 0) {
|
||||||
locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
|
locals.defineVariable(null, int.class, LOOP, true);
|
||||||
}
|
}
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a new main method scope */
|
/** Creates a new main method scope */
|
||||||
public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals programScope, int maxLoopCounter) {
|
public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals programScope, int maxLoopCounter) {
|
||||||
Locals locals = new Locals(programScope, programScope.definition,
|
Locals locals = new Locals(
|
||||||
scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
|
programScope, programScope.definition, scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
|
||||||
// This reference. Internal use only.
|
// This reference. Internal use only.
|
||||||
locals.defineVariable(null, programScope.definition.getType("Object"), THIS, true);
|
locals.defineVariable(null, Object.class, THIS, true);
|
||||||
|
|
||||||
// Method arguments
|
// Method arguments
|
||||||
for (MethodArgument arg : scriptClassInfo.getExecuteArguments()) {
|
for (MethodArgument arg : scriptClassInfo.getExecuteArguments()) {
|
||||||
locals.defineVariable(null, arg.getType(), arg.getName(), true);
|
locals.defineVariable(null, arg.getClazz(), arg.getName(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop counter to catch infinite loops. Internal use only.
|
// Loop counter to catch infinite loops. Internal use only.
|
||||||
if (maxLoopCounter > 0) {
|
if (maxLoopCounter > 0) {
|
||||||
locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
|
locals.defineVariable(null, int.class, LOOP, true);
|
||||||
}
|
}
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
@ -155,18 +154,18 @@ public final class Locals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a new variable. Throws IAE if the variable has already been defined (even in a parent) or reserved. */
|
/** Creates a new variable. Throws IAE if the variable has already been defined (even in a parent) or reserved. */
|
||||||
public Variable addVariable(Location location, Type type, String name, boolean readonly) {
|
public Variable addVariable(Location location, Class<?> clazz, String name, boolean readonly) {
|
||||||
if (hasVariable(name)) {
|
if (hasVariable(name)) {
|
||||||
throw location.createError(new IllegalArgumentException("Variable [" + name + "] is already defined."));
|
throw location.createError(new IllegalArgumentException("Variable [" + name + "] is already defined."));
|
||||||
}
|
}
|
||||||
if (keywords.contains(name)) {
|
if (keywords.contains(name)) {
|
||||||
throw location.createError(new IllegalArgumentException("Variable [" + name + "] is reserved."));
|
throw location.createError(new IllegalArgumentException("Variable [" + name + "] is reserved."));
|
||||||
}
|
}
|
||||||
return defineVariable(location, type, name, readonly);
|
return defineVariable(location, clazz, name, readonly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return type of this scope (e.g. int, if inside a function that returns int) */
|
/** Return type of this scope (e.g. int, if inside a function that returns int) */
|
||||||
public Type getReturnType() {
|
public Class<?> getReturnType() {
|
||||||
return returnType;
|
return returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +190,7 @@ public final class Locals {
|
|||||||
// parent scope
|
// parent scope
|
||||||
private final Locals parent;
|
private final Locals parent;
|
||||||
// return type of this scope
|
// return type of this scope
|
||||||
private final Type returnType;
|
private final Class<?> returnType;
|
||||||
// keywords for this scope
|
// keywords for this scope
|
||||||
private final Set<String> keywords;
|
private final Set<String> keywords;
|
||||||
// next slot number to assign
|
// next slot number to assign
|
||||||
@ -211,7 +210,7 @@ public final class Locals {
|
|||||||
/**
|
/**
|
||||||
* Create a new Locals with specified return type
|
* Create a new Locals with specified return type
|
||||||
*/
|
*/
|
||||||
private Locals(Locals parent, Definition definition, Type returnType, Set<String> keywords) {
|
private Locals(Locals parent, Definition definition, Class<?> returnType, Set<String> keywords) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
@ -246,13 +245,13 @@ public final class Locals {
|
|||||||
|
|
||||||
|
|
||||||
/** Defines a variable at this scope internally. */
|
/** Defines a variable at this scope internally. */
|
||||||
private Variable defineVariable(Location location, Type type, String name, boolean readonly) {
|
private Variable defineVariable(Location location, Class<?> type, String name, boolean readonly) {
|
||||||
if (variables == null) {
|
if (variables == null) {
|
||||||
variables = new HashMap<>();
|
variables = new HashMap<>();
|
||||||
}
|
}
|
||||||
Variable variable = new Variable(location, name, type, getNextSlot(), readonly);
|
Variable variable = new Variable(location, name, type, getNextSlot(), readonly);
|
||||||
variables.put(name, variable); // TODO: check result
|
variables.put(name, variable); // TODO: check result
|
||||||
nextSlotNumber += type.type.getSize();
|
nextSlotNumber += MethodWriter.getType(type).getSize();
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,15 +271,15 @@ public final class Locals {
|
|||||||
public static final class Variable {
|
public static final class Variable {
|
||||||
public final Location location;
|
public final Location location;
|
||||||
public final String name;
|
public final String name;
|
||||||
public final Type type;
|
public final Class<?> clazz;
|
||||||
public final boolean readonly;
|
public final boolean readonly;
|
||||||
private final int slot;
|
private final int slot;
|
||||||
private boolean used;
|
private boolean used;
|
||||||
|
|
||||||
public Variable(Location location, String name, Type type, int slot, boolean readonly) {
|
public Variable(Location location, String name, Class<?> clazz, int slot, boolean readonly) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.clazz = clazz;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.readonly = readonly;
|
this.readonly = readonly;
|
||||||
}
|
}
|
||||||
@ -292,7 +291,7 @@ public final class Locals {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
b.append("Variable[type=").append(type);
|
b.append("Variable[type=").append(Definition.ClassToName(clazz));
|
||||||
b.append(",name=").append(name);
|
b.append(",name=").append(name);
|
||||||
b.append(",slot=").append(slot);
|
b.append(",slot=").append(slot);
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
@ -306,12 +305,12 @@ public final class Locals {
|
|||||||
public static final class Parameter {
|
public static final class Parameter {
|
||||||
public final Location location;
|
public final Location location;
|
||||||
public final String name;
|
public final String name;
|
||||||
public final Type type;
|
public final Class<?> clazz;
|
||||||
|
|
||||||
public Parameter(Location location, String name, Type type) {
|
public Parameter(Location location, String name, Class<?> clazz) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.clazz = clazz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,11 @@ public class ScriptClassInfo {
|
|||||||
|
|
||||||
private final Class<?> baseClass;
|
private final Class<?> baseClass;
|
||||||
private final org.objectweb.asm.commons.Method executeMethod;
|
private final org.objectweb.asm.commons.Method executeMethod;
|
||||||
private final Definition.Type executeMethodReturnType;
|
private final Class<?> executeMethodReturnType;
|
||||||
private final List<MethodArgument> executeArguments;
|
private final List<MethodArgument> executeArguments;
|
||||||
private final List<org.objectweb.asm.commons.Method> needsMethods;
|
private final List<org.objectweb.asm.commons.Method> needsMethods;
|
||||||
private final List<org.objectweb.asm.commons.Method> getMethods;
|
private final List<org.objectweb.asm.commons.Method> getMethods;
|
||||||
private final List<Definition.Type> getReturns;
|
private final List<Class<?>> getReturns;
|
||||||
|
|
||||||
public ScriptClassInfo(Definition definition, Class<?> baseClass) {
|
public ScriptClassInfo(Definition definition, Class<?> baseClass) {
|
||||||
this.baseClass = baseClass;
|
this.baseClass = baseClass;
|
||||||
@ -51,7 +51,7 @@ public class ScriptClassInfo {
|
|||||||
java.lang.reflect.Method executeMethod = null;
|
java.lang.reflect.Method executeMethod = null;
|
||||||
List<org.objectweb.asm.commons.Method> needsMethods = new ArrayList<>();
|
List<org.objectweb.asm.commons.Method> needsMethods = new ArrayList<>();
|
||||||
List<org.objectweb.asm.commons.Method> getMethods = new ArrayList<>();
|
List<org.objectweb.asm.commons.Method> getMethods = new ArrayList<>();
|
||||||
List<Definition.Type> getReturns = new ArrayList<>();
|
List<Class<?>> getReturns = new ArrayList<>();
|
||||||
for (java.lang.reflect.Method m : baseClass.getMethods()) {
|
for (java.lang.reflect.Method m : baseClass.getMethods()) {
|
||||||
if (m.isDefault()) {
|
if (m.isDefault()) {
|
||||||
continue;
|
continue;
|
||||||
@ -65,7 +65,7 @@ public class ScriptClassInfo {
|
|||||||
+ "] has more than one.");
|
+ "] has more than one.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m.getName().startsWith("needs") && m.getReturnType().equals(boolean.class) && m.getParameterTypes().length == 0) {
|
if (m.getName().startsWith("needs") && m.getReturnType() == boolean.class && m.getParameterTypes().length == 0) {
|
||||||
needsMethods.add(new org.objectweb.asm.commons.Method(m.getName(), NEEDS_PARAMETER_METHOD_TYPE.toMethodDescriptorString()));
|
needsMethods.add(new org.objectweb.asm.commons.Method(m.getName(), NEEDS_PARAMETER_METHOD_TYPE.toMethodDescriptorString()));
|
||||||
}
|
}
|
||||||
if (m.getName().startsWith("get") && m.getName().equals("getClass") == false && Modifier.isStatic(m.getModifiers()) == false) {
|
if (m.getName().startsWith("get") && m.getName().equals("getClass") == false && Modifier.isStatic(m.getModifiers()) == false) {
|
||||||
@ -118,15 +118,15 @@ public class ScriptClassInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Painless {@link Definition.Type} or the return type of the {@code execute} method. This is used to generate the appropriate
|
* The Painless {@link Class} or the return type of the {@code execute} method. This is used to generate the appropriate
|
||||||
* return bytecode.
|
* return bytecode.
|
||||||
*/
|
*/
|
||||||
public Definition.Type getExecuteMethodReturnType() {
|
public Class<?> getExecuteMethodReturnType() {
|
||||||
return executeMethodReturnType;
|
return executeMethodReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Painless {@link Definition.Type}s and names of the arguments to the {@code execute} method. The names are exposed to the Painless
|
* Painless {@link Class}s and names of the arguments to the {@code execute} method. The names are exposed to the Painless
|
||||||
* script.
|
* script.
|
||||||
*/
|
*/
|
||||||
public List<MethodArgument> getExecuteArguments() {
|
public List<MethodArgument> getExecuteArguments() {
|
||||||
@ -150,24 +150,24 @@ public class ScriptClassInfo {
|
|||||||
/**
|
/**
|
||||||
* The {@code getVarName} methods return types.
|
* The {@code getVarName} methods return types.
|
||||||
*/
|
*/
|
||||||
public List<Definition.Type> getGetReturns() {
|
public List<Class<?>> getGetReturns() {
|
||||||
return getReturns;
|
return getReturns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Painless {@link Definition.Type}s and name of the argument to the {@code execute} method.
|
* Painless {@link Class}es and name of the argument to the {@code execute} method.
|
||||||
*/
|
*/
|
||||||
public static class MethodArgument {
|
public static class MethodArgument {
|
||||||
private final Definition.Type type;
|
private final Class<?> clazz;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public MethodArgument(Definition.Type type, String name) {
|
public MethodArgument(Class<?> clazz, String name) {
|
||||||
this.type = type;
|
this.clazz = clazz;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Definition.Type getType() {
|
public Class<?> getClazz() {
|
||||||
return type;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -175,13 +175,13 @@ public class ScriptClassInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodArgument methodArgument(Definition definition, Class<?> type, String argName) {
|
private MethodArgument methodArgument(Definition definition, Class<?> clazz, String argName) {
|
||||||
Definition.Type defType = definitionTypeForClass(definition, type, componentType -> "[" + argName + "] is of unknown type ["
|
Class<?> defClass = definitionTypeForClass(definition, clazz, componentType -> "[" + argName + "] is of unknown type ["
|
||||||
+ componentType.getName() + ". Painless interfaces can only accept arguments that are of whitelisted types.");
|
+ componentType.getName() + ". Painless interfaces can only accept arguments that are of whitelisted types.");
|
||||||
return new MethodArgument(defType, argName);
|
return new MethodArgument(defClass, argName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Definition.Type definitionTypeForClass(Definition definition, Class<?> type,
|
private static Class<?> definitionTypeForClass(Definition definition, Class<?> type,
|
||||||
Function<Class<?>, String> unknownErrorMessageSource) {
|
Function<Class<?>, String> unknownErrorMessageSource) {
|
||||||
int dimensions = 0;
|
int dimensions = 0;
|
||||||
Class<?> componentType = type;
|
Class<?> componentType = type;
|
||||||
@ -190,8 +190,8 @@ public class ScriptClassInfo {
|
|||||||
componentType = componentType.getComponentType();
|
componentType = componentType.getComponentType();
|
||||||
}
|
}
|
||||||
Definition.Struct struct;
|
Definition.Struct struct;
|
||||||
if (componentType.equals(Object.class)) {
|
if (componentType == Object.class) {
|
||||||
struct = definition.DefType.struct;
|
struct = definition.getType("def").struct;
|
||||||
} else {
|
} else {
|
||||||
Definition.RuntimeClass runtimeClass = definition.getRuntimeClass(componentType);
|
Definition.RuntimeClass runtimeClass = definition.getRuntimeClass(componentType);
|
||||||
if (runtimeClass == null) {
|
if (runtimeClass == null) {
|
||||||
@ -199,7 +199,7 @@ public class ScriptClassInfo {
|
|||||||
}
|
}
|
||||||
struct = runtimeClass.getStruct();
|
struct = runtimeClass.getStruct();
|
||||||
}
|
}
|
||||||
return definition.getType(struct, dimensions);
|
return Definition.TypeToClass(definition.getType(struct, dimensions));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] readArgumentNamesConstant(Class<?> iface) {
|
private static String[] readArgumentNamesConstant(Class<?> iface) {
|
||||||
|
@ -22,6 +22,7 @@ package org.elasticsearch.painless.node;
|
|||||||
import org.elasticsearch.painless.AnalyzerCaster;
|
import org.elasticsearch.painless.AnalyzerCaster;
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition;
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
import org.elasticsearch.painless.FunctionRef;
|
import org.elasticsearch.painless.FunctionRef;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
@ -63,20 +64,20 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
|||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
captured = locals.getVariable(location, variable);
|
captured = locals.getVariable(location, variable);
|
||||||
if (expected == null) {
|
if (expected == null) {
|
||||||
if (captured.type.dynamic) {
|
if (captured.clazz == def.class) {
|
||||||
// dynamic implementation
|
// dynamic implementation
|
||||||
defPointer = "D" + variable + "." + call + ",1";
|
defPointer = "D" + variable + "." + call + ",1";
|
||||||
} else {
|
} else {
|
||||||
// typed implementation
|
// typed implementation
|
||||||
defPointer = "S" + captured.type.name + "." + call + ",1";
|
defPointer = "S" + Definition.ClassToName(captured.clazz) + "." + call + ",1";
|
||||||
}
|
}
|
||||||
actual = String.class;
|
actual = String.class;
|
||||||
} else {
|
} else {
|
||||||
defPointer = null;
|
defPointer = null;
|
||||||
// static case
|
// static case
|
||||||
if (captured.type.dynamic == false) {
|
if (captured.clazz != def.class) {
|
||||||
try {
|
try {
|
||||||
ref = new FunctionRef(locals.getDefinition(), expected, captured.type.name, call, 1);
|
ref = new FunctionRef(locals.getDefinition(), expected, Definition.ClassToName(captured.clazz), call, 1);
|
||||||
|
|
||||||
// check casts between the interface method and the delegate method are legal
|
// check casts between the interface method and the delegate method are legal
|
||||||
for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
|
for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
|
||||||
@ -103,15 +104,15 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
|||||||
// dynamic interface: push captured parameter on stack
|
// dynamic interface: push captured parameter on stack
|
||||||
// TODO: don't do this: its just to cutover :)
|
// TODO: don't do this: its just to cutover :)
|
||||||
writer.push((String)null);
|
writer.push((String)null);
|
||||||
writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
|
||||||
} else if (ref == null) {
|
} else if (ref == null) {
|
||||||
// typed interface, dynamic implementation
|
// typed interface, dynamic implementation
|
||||||
writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
|
||||||
Type methodType = Type.getMethodType(MethodWriter.getType(expected), captured.type.type);
|
Type methodType = Type.getMethodType(MethodWriter.getType(expected), MethodWriter.getType(captured.clazz));
|
||||||
writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, Definition.ClassToName(expected));
|
writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, Definition.ClassToName(expected));
|
||||||
} else {
|
} else {
|
||||||
// typed interface, typed implementation
|
// typed interface, typed implementation
|
||||||
writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
|
||||||
writer.invokeDynamic(
|
writer.invokeDynamic(
|
||||||
ref.interfaceMethodName,
|
ref.interfaceMethodName,
|
||||||
ref.factoryDescriptor,
|
ref.factoryDescriptor,
|
||||||
@ -132,7 +133,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type[] getCaptures() {
|
public Type[] getCaptures() {
|
||||||
return new Type[] { captured.type.type };
|
return new Type[] { MethodWriter.getType(captured.clazz) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -162,7 +162,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
List<String> paramTypes = new ArrayList<>(captures.size() + actualParamTypeStrs.size());
|
List<String> paramTypes = new ArrayList<>(captures.size() + actualParamTypeStrs.size());
|
||||||
List<String> paramNames = new ArrayList<>(captures.size() + paramNameStrs.size());
|
List<String> paramNames = new ArrayList<>(captures.size() + paramNameStrs.size());
|
||||||
for (Variable var : captures) {
|
for (Variable var : captures) {
|
||||||
paramTypes.add(var.type.name);
|
paramTypes.add(Definition.ClassToName(var.clazz));
|
||||||
paramNames.add(var.name);
|
paramNames.add(var.name);
|
||||||
}
|
}
|
||||||
paramTypes.addAll(actualParamTypeStrs);
|
paramTypes.addAll(actualParamTypeStrs);
|
||||||
@ -172,7 +172,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
desugared = new SFunction(reserved, location, Definition.ClassToName(returnType), name,
|
desugared = new SFunction(reserved, location, Definition.ClassToName(returnType), name,
|
||||||
paramTypes, paramNames, statements, true);
|
paramTypes, paramNames, statements, true);
|
||||||
desugared.generateSignature(locals.getDefinition());
|
desugared.generateSignature(locals.getDefinition());
|
||||||
desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), locals.getDefinition().ClassToType(returnType),
|
desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), returnType,
|
||||||
desugared.parameters, captures.size(), reserved.getMaxLoopCounter()));
|
desugared.parameters, captures.size(), reserved.getMaxLoopCounter()));
|
||||||
|
|
||||||
// setup method reference to synthetic method
|
// setup method reference to synthetic method
|
||||||
@ -191,7 +191,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
// check casts between the interface method and the delegate method are legal
|
// check casts between the interface method and the delegate method are legal
|
||||||
for (int i = 0; i < interfaceMethod.arguments.size(); ++i) {
|
for (int i = 0; i < interfaceMethod.arguments.size(); ++i) {
|
||||||
Class<?> from = interfaceMethod.arguments.get(i);
|
Class<?> from = interfaceMethod.arguments.get(i);
|
||||||
Class<?> to = Definition.TypeToClass(desugared.parameters.get(i + captures.size()).type);
|
Class<?> to = desugared.parameters.get(i + captures.size()).clazz;
|
||||||
AnalyzerCaster.getLegalCast(location, from, to, false, true);
|
AnalyzerCaster.getLegalCast(location, from, to, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
// load captures
|
// load captures
|
||||||
for (Variable capture : captures) {
|
for (Variable capture : captures) {
|
||||||
writer.visitVarInsn(MethodWriter.getType(capture.type.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(capture.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.invokeDynamic(
|
writer.invokeDynamic(
|
||||||
@ -229,7 +229,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
writer.push((String)null);
|
writer.push((String)null);
|
||||||
// load captures
|
// load captures
|
||||||
for (Variable capture : captures) {
|
for (Variable capture : captures) {
|
||||||
writer.visitVarInsn(MethodWriter.getType(capture.type.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(capture.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ public final class ELambda extends AExpression implements ILambda {
|
|||||||
public org.objectweb.asm.Type[] getCaptures() {
|
public org.objectweb.asm.Type[] getCaptures() {
|
||||||
org.objectweb.asm.Type[] types = new org.objectweb.asm.Type[captures.size()];
|
org.objectweb.asm.Type[] types = new org.objectweb.asm.Type[captures.size()];
|
||||||
for (int i = 0; i < types.length; i++) {
|
for (int i = 0; i < types.length; i++) {
|
||||||
types[i] = MethodWriter.getType(captures.get(i).type.clazz);
|
types[i] = MethodWriter.getType(captures.get(i).clazz);
|
||||||
}
|
}
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public final class EVariable extends AStoreable {
|
|||||||
throw createError(new IllegalArgumentException("Variable [" + variable.name + "] is read-only."));
|
throw createError(new IllegalArgumentException("Variable [" + variable.name + "] is read-only."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = Definition.TypeToClass(variable.type);
|
actual = variable.clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
import org.elasticsearch.painless.Definition.Type;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
@ -65,19 +66,19 @@ public final class SCatch extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
final Type type;
|
Class<?> clazz;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
type = locals.getDefinition().getType(this.type);
|
clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Exception.class.isAssignableFrom(type.clazz)) {
|
if (!Exception.class.isAssignableFrom(clazz)) {
|
||||||
throw createError(new ClassCastException("Not an exception type [" + this.type + "]."));
|
throw createError(new ClassCastException("Not an exception type [" + this.type + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
variable = locals.addVariable(location, type, name, true);
|
variable = locals.addVariable(location, clazz, name, true);
|
||||||
|
|
||||||
if (block != null) {
|
if (block != null) {
|
||||||
block.lastSource = lastSource;
|
block.lastSource = lastSource;
|
||||||
@ -102,7 +103,7 @@ public final class SCatch extends AStatement {
|
|||||||
Label jump = new Label();
|
Label jump = new Label();
|
||||||
|
|
||||||
writer.mark(jump);
|
writer.mark(jump);
|
||||||
writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||||
|
|
||||||
if (block != null) {
|
if (block != null) {
|
||||||
block.continu = continu;
|
block.continu = continu;
|
||||||
@ -110,7 +111,7 @@ public final class SCatch extends AStatement {
|
|||||||
block.write(writer, globals);
|
block.write(writer, globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.visitTryCatchBlock(begin, end, jump, variable.type.type.getInternalName());
|
writer.visitTryCatchBlock(begin, end, jump, MethodWriter.getType(variable.clazz).getInternalName());
|
||||||
|
|
||||||
if (exception != null && !block.allEscape) {
|
if (exception != null && !block.allEscape) {
|
||||||
writer.goTo(exception);
|
writer.goTo(exception);
|
||||||
|
@ -61,21 +61,21 @@ public final class SDeclaration extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
final Type type;
|
Class<?> clazz;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
type = locals.getDefinition().getType(this.type);
|
clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.expected = Definition.TypeToClass(type);
|
expression.expected = clazz;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
variable = locals.addVariable(location, type, name, false);
|
variable = locals.addVariable(location, clazz, name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -83,7 +83,7 @@ public final class SDeclaration extends AStatement {
|
|||||||
writer.writeStatementOffset(location);
|
writer.writeStatementOffset(location);
|
||||||
|
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
Class<?> sort = variable.type.clazz;
|
Class<?> sort = variable.clazz;
|
||||||
|
|
||||||
if (sort == void.class || sort == boolean.class || sort == byte.class ||
|
if (sort == void.class || sort == boolean.class || sort == byte.class ||
|
||||||
sort == short.class || sort == char.class || sort == int.class) {
|
sort == short.class || sort == char.class || sort == int.class) {
|
||||||
@ -101,7 +101,7 @@ public final class SDeclaration extends AStatement {
|
|||||||
expression.write(writer, globals);
|
expression.write(writer, globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,16 +69,16 @@ public class SEach extends AStatement {
|
|||||||
expression.expected = expression.actual;
|
expression.expected = expression.actual;
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
|
||||||
final Type type;
|
Class<?> clazz;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
type = locals.getDefinition().getType(this.type);
|
clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
locals = Locals.newLocalScope(locals);
|
locals = Locals.newLocalScope(locals);
|
||||||
Variable variable = locals.addVariable(location, type, name, true);
|
Variable variable = locals.addVariable(location, clazz, name, true);
|
||||||
|
|
||||||
if (expression.actual.isArray()) {
|
if (expression.actual.isArray()) {
|
||||||
sub = new SSubEachArray(location, variable, expression, block);
|
sub = new SSubEachArray(location, variable, expression, block);
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
import org.elasticsearch.painless.Location;
|
import org.elasticsearch.painless.Location;
|
||||||
@ -49,8 +47,8 @@ public final class SExpression extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
Type rtnType = locals.getReturnType();
|
Class<?> rtnType = locals.getReturnType();
|
||||||
boolean isVoid = rtnType.clazz == void.class;
|
boolean isVoid = rtnType == void.class;
|
||||||
|
|
||||||
expression.read = lastSource && !isVoid;
|
expression.read = lastSource && !isVoid;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
@ -61,7 +59,7 @@ public final class SExpression extends AStatement {
|
|||||||
|
|
||||||
boolean rtn = lastSource && !isVoid && expression.actual != void.class;
|
boolean rtn = lastSource && !isVoid && expression.actual != void.class;
|
||||||
|
|
||||||
expression.expected = rtn ? Definition.TypeToClass(rtnType) : expression.actual;
|
expression.expected = rtn ? rtnType : expression.actual;
|
||||||
expression.internal = rtn;
|
expression.internal = rtn;
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ public final class SFunction extends AStatement {
|
|||||||
|
|
||||||
paramClasses[param] = Definition.defClassToObjectClass(paramType);
|
paramClasses[param] = Definition.defClassToObjectClass(paramType);
|
||||||
paramTypes.add(paramType);
|
paramTypes.add(paramType);
|
||||||
parameters.add(new Parameter(location, paramNameStrs.get(param), definition.ClassToType(paramType)));
|
parameters.add(new Parameter(location, paramNameStrs.get(param), paramType));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException(
|
throw createError(new IllegalArgumentException(
|
||||||
"Illegal parameter type [" + this.paramTypeStrs.get(param) + "] for function [" + name + "]."));
|
"Illegal parameter type [" + this.paramTypeStrs.get(param) + "] for function [" + name + "]."));
|
||||||
|
@ -48,7 +48,7 @@ public final class SReturn extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
expression.expected = Definition.TypeToClass(locals.getReturnType());
|
expression.expected = locals.getReturnType();
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
@ -186,8 +186,8 @@ public final class SSource extends AStatement {
|
|||||||
@Override
|
@Override
|
||||||
void analyze(Locals program) {
|
void analyze(Locals program) {
|
||||||
for (SFunction function : functions) {
|
for (SFunction function : functions) {
|
||||||
Locals functionLocals = Locals.newFunctionScope(program, program.getDefinition().ClassToType(function.rtnType),
|
Locals functionLocals =
|
||||||
function.parameters, function.reserved.getMaxLoopCounter());
|
Locals.newFunctionScope(program, function.rtnType, function.parameters, function.reserved.getMaxLoopCounter());
|
||||||
function.analyze(functionLocals);
|
function.analyze(functionLocals);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ public final class SSource extends AStatement {
|
|||||||
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||||
|
|
||||||
if (reserved.getUsedVariables().contains(name)) {
|
if (reserved.getUsedVariables().contains(name)) {
|
||||||
Definition.Type rtn = scriptClassInfo.getGetReturns().get(get);
|
Class<?> rtn = scriptClassInfo.getGetReturns().get(get);
|
||||||
mainMethod.addVariable(new Location("getter [" + name + "]", 0), rtn, name, true);
|
mainMethod.addVariable(new Location("getter [" + name + "]", 0), rtn, name, true);
|
||||||
getMethods.add(method);
|
getMethods.add(method);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ package org.elasticsearch.painless.node;
|
|||||||
import org.elasticsearch.painless.AnalyzerCaster;
|
import org.elasticsearch.painless.AnalyzerCaster;
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Cast;
|
import org.elasticsearch.painless.Definition.Cast;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
import org.elasticsearch.painless.Locals.Variable;
|
import org.elasticsearch.painless.Locals.Variable;
|
||||||
@ -45,7 +44,7 @@ final class SSubEachArray extends AStatement {
|
|||||||
private Cast cast = null;
|
private Cast cast = null;
|
||||||
private Variable array = null;
|
private Variable array = null;
|
||||||
private Variable index = null;
|
private Variable index = null;
|
||||||
private Type indexed = null;
|
private Class<?> indexed = null;
|
||||||
|
|
||||||
SSubEachArray(Location location, Variable variable, AExpression expression, SBlock block) {
|
SSubEachArray(Location location, Variable variable, AExpression expression, SBlock block) {
|
||||||
super(location);
|
super(location);
|
||||||
@ -64,11 +63,10 @@ final class SSubEachArray extends AStatement {
|
|||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
// We must store the array and index as variables for securing slots on the stack, and
|
// We must store the array and index as variables for securing slots on the stack, and
|
||||||
// also add the location offset to make the names unique in case of nested for each loops.
|
// also add the location offset to make the names unique in case of nested for each loops.
|
||||||
Type actualType = locals.getDefinition().ClassToType(expression.actual);
|
array = locals.addVariable(location, expression.actual, "#array" + location.getOffset(), true);
|
||||||
array = locals.addVariable(location, actualType, "#array" + location.getOffset(), true);
|
index = locals.addVariable(location, int.class, "#index" + location.getOffset(), true);
|
||||||
index = locals.addVariable(location, locals.getDefinition().intType, "#index" + location.getOffset(), true);
|
indexed = expression.actual.getComponentType();
|
||||||
indexed = locals.getDefinition().getType(actualType.struct, actualType.dimensions - 1);
|
cast = AnalyzerCaster.getLegalCast(location, indexed, variable.clazz, true, true);
|
||||||
cast = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(indexed), Definition.TypeToClass(variable.type), true, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,9 +74,9 @@ final class SSubEachArray extends AStatement {
|
|||||||
writer.writeStatementOffset(location);
|
writer.writeStatementOffset(location);
|
||||||
|
|
||||||
expression.write(writer, globals);
|
expression.write(writer, globals);
|
||||||
writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ISTORE), array.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ISTORE), array.getSlot());
|
||||||
writer.push(-1);
|
writer.push(-1);
|
||||||
writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ISTORE), index.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ISTORE), index.getSlot());
|
||||||
|
|
||||||
Label begin = new Label();
|
Label begin = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
@ -86,16 +84,16 @@ final class SSubEachArray extends AStatement {
|
|||||||
writer.mark(begin);
|
writer.mark(begin);
|
||||||
|
|
||||||
writer.visitIincInsn(index.getSlot(), 1);
|
writer.visitIincInsn(index.getSlot(), 1);
|
||||||
writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ILOAD), index.getSlot());
|
||||||
writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ILOAD), array.getSlot());
|
||||||
writer.arrayLength();
|
writer.arrayLength();
|
||||||
writer.ifICmp(MethodWriter.GE, end);
|
writer.ifICmp(MethodWriter.GE, end);
|
||||||
|
|
||||||
writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ILOAD), array.getSlot());
|
||||||
writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ILOAD), index.getSlot());
|
||||||
writer.arrayLoad(indexed.type);
|
writer.arrayLoad(MethodWriter.getType(indexed));
|
||||||
writer.writeCast(cast);
|
writer.writeCast(cast);
|
||||||
writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||||
|
|
||||||
if (loopCounter != null) {
|
if (loopCounter != null) {
|
||||||
writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
|
writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
|
||||||
@ -111,6 +109,6 @@ final class SSubEachArray extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return singleLineToString(variable.type.name, variable.name, expression, block);
|
return singleLineToString(Definition.ClassToName(variable.clazz), variable.name, expression, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,7 @@ final class SSubEachIterable extends AStatement {
|
|||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
// We must store the iterator as a variable for securing a slot on the stack, and
|
// We must store the iterator as a variable for securing a slot on the stack, and
|
||||||
// also add the location offset to make the name unique in case of nested for each loops.
|
// also add the location offset to make the name unique in case of nested for each loops.
|
||||||
iterator = locals.addVariable(location, locals.getDefinition().getType("Iterator"),
|
iterator = locals.addVariable(location, Iterator.class, "#itr" + location.getOffset(), true);
|
||||||
"#itr" + location.getOffset(), true);
|
|
||||||
|
|
||||||
if (expression.actual == def.class) {
|
if (expression.actual == def.class) {
|
||||||
method = null;
|
method = null;
|
||||||
@ -88,7 +87,7 @@ final class SSubEachIterable extends AStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast = AnalyzerCaster.getLegalCast(location, def.class, Definition.TypeToClass(variable.type), true, true);
|
cast = AnalyzerCaster.getLegalCast(location, def.class, variable.clazz, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -105,21 +104,21 @@ final class SSubEachIterable extends AStatement {
|
|||||||
method.write(writer);
|
method.write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ISTORE), iterator.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ISTORE), iterator.getSlot());
|
||||||
|
|
||||||
Label begin = new Label();
|
Label begin = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
|
|
||||||
writer.mark(begin);
|
writer.mark(begin);
|
||||||
|
|
||||||
writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ILOAD), iterator.getSlot());
|
||||||
writer.invokeInterface(ITERATOR_TYPE, ITERATOR_HASNEXT);
|
writer.invokeInterface(ITERATOR_TYPE, ITERATOR_HASNEXT);
|
||||||
writer.ifZCmp(MethodWriter.EQ, end);
|
writer.ifZCmp(MethodWriter.EQ, end);
|
||||||
|
|
||||||
writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ILOAD), iterator.getSlot());
|
||||||
writer.invokeInterface(ITERATOR_TYPE, ITERATOR_NEXT);
|
writer.invokeInterface(ITERATOR_TYPE, ITERATOR_NEXT);
|
||||||
writer.writeCast(cast);
|
writer.writeCast(cast);
|
||||||
writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||||
|
|
||||||
if (loopCounter != null) {
|
if (loopCounter != null) {
|
||||||
writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
|
writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
|
||||||
@ -135,6 +134,6 @@ final class SSubEachIterable extends AStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return singleLineToString(variable.type.name, variable.name, expression, block);
|
return singleLineToString(Definition.ClassToName(variable.clazz), variable.name, expression, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -763,7 +763,7 @@ public class NodeToStringTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testSSubEachArray() {
|
public void testSSubEachArray() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
Variable v = new Variable(l, "test", definition.intType, 5, false);
|
Variable v = new Variable(l, "test", int.class, 5, false);
|
||||||
AExpression e = new ENewArray(l, "int", Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)), true);
|
AExpression e = new ENewArray(l, "int", Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)), true);
|
||||||
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
||||||
SSubEachArray node = new SSubEachArray(l, v, e, b);
|
SSubEachArray node = new SSubEachArray(l, v, e, b);
|
||||||
@ -775,7 +775,7 @@ public class NodeToStringTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testSSubEachIterable() {
|
public void testSSubEachIterable() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
Variable v = new Variable(l, "test", definition.intType, 5, false);
|
Variable v = new Variable(l, "test", int.class, 5, false);
|
||||||
AExpression e = new EListInit(l, Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)));
|
AExpression e = new EListInit(l, Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)));
|
||||||
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
||||||
SSubEachIterable node = new SSubEachIterable(l, v, e, b);
|
SSubEachIterable node = new SSubEachIterable(l, v, e, b);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user