Remove Painless Type from e-nodes in favor of Java Class (#28364)
This commit is contained in:
parent
43d1dcb919
commit
f13da9f534
|
@ -452,60 +452,60 @@ public final class Definition {
|
||||||
return getTypeInternal(struct, dimensions);
|
return getTypeInternal(struct, dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getBoxedType(Type unboxed) {
|
public static Class<?> getBoxedType(Class<?> clazz) {
|
||||||
if (unboxed.clazz == boolean.class) {
|
if (clazz == boolean.class) {
|
||||||
return BooleanType;
|
return Boolean.class;
|
||||||
} else if (unboxed.clazz == byte.class) {
|
} else if (clazz == byte.class) {
|
||||||
return ByteType;
|
return Byte.class;
|
||||||
} else if (unboxed.clazz == short.class) {
|
} else if (clazz == short.class) {
|
||||||
return ShortType;
|
return Short.class;
|
||||||
} else if (unboxed.clazz == char.class) {
|
} else if (clazz == char.class) {
|
||||||
return CharacterType;
|
return Character.class;
|
||||||
} else if (unboxed.clazz == int.class) {
|
} else if (clazz == int.class) {
|
||||||
return IntegerType;
|
return Integer.class;
|
||||||
} else if (unboxed.clazz == long.class) {
|
} else if (clazz == long.class) {
|
||||||
return LongType;
|
return Long.class;
|
||||||
} else if (unboxed.clazz == float.class) {
|
} else if (clazz == float.class) {
|
||||||
return FloatType;
|
return Float.class;
|
||||||
} else if (unboxed.clazz == double.class) {
|
} else if (clazz == double.class) {
|
||||||
return DoubleType;
|
return Double.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
return unboxed;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getUnboxedType(Type boxed) {
|
public static Class<?> getUnboxedype(Class<?> clazz) {
|
||||||
if (boxed.clazz == Boolean.class) {
|
if (clazz == Boolean.class) {
|
||||||
return booleanType;
|
return boolean.class;
|
||||||
} else if (boxed.clazz == Byte.class) {
|
} else if (clazz == Byte.class) {
|
||||||
return byteType;
|
return byte.class;
|
||||||
} else if (boxed.clazz == Short.class) {
|
} else if (clazz == Short.class) {
|
||||||
return shortType;
|
return short.class;
|
||||||
} else if (boxed.clazz == Character.class) {
|
} else if (clazz == Character.class) {
|
||||||
return charType;
|
return char.class;
|
||||||
} else if (boxed.clazz == Integer.class) {
|
} else if (clazz == Integer.class) {
|
||||||
return intType;
|
return int.class;
|
||||||
} else if (boxed.clazz == Long.class) {
|
} else if (clazz == Long.class) {
|
||||||
return longType;
|
return long.class;
|
||||||
} else if (boxed.clazz == Float.class) {
|
} else if (clazz == Float.class) {
|
||||||
return floatType;
|
return float.class;
|
||||||
} else if (boxed.clazz == Double.class) {
|
} else if (clazz == Double.class) {
|
||||||
return doubleType;
|
return double.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
return boxed;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isConstantType(Type constant) {
|
public static boolean isConstantType(Class<?> clazz) {
|
||||||
return constant.clazz == boolean.class ||
|
return clazz == boolean.class ||
|
||||||
constant.clazz == byte.class ||
|
clazz == byte.class ||
|
||||||
constant.clazz == short.class ||
|
clazz == short.class ||
|
||||||
constant.clazz == char.class ||
|
clazz == char.class ||
|
||||||
constant.clazz == int.class ||
|
clazz == int.class ||
|
||||||
constant.clazz == long.class ||
|
clazz == long.class ||
|
||||||
constant.clazz == float.class ||
|
clazz == float.class ||
|
||||||
constant.clazz == double.class ||
|
clazz == double.class ||
|
||||||
constant.clazz == String.class;
|
clazz == String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> ObjectClassTodefClass(Class<?> clazz) {
|
public static Class<?> ObjectClassTodefClass(Class<?> clazz) {
|
||||||
|
@ -579,7 +579,7 @@ public final class Definition {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component == def.class) {
|
if (component == def.class) {
|
||||||
StringBuilder builder = new StringBuilder("def");
|
StringBuilder builder = new StringBuilder(def.class.getSimpleName());
|
||||||
|
|
||||||
for (int dimension = 0; dimension < dimensions; dimensions++) {
|
for (int dimension = 0; dimension < dimensions; dimensions++) {
|
||||||
builder.append("[]");
|
builder.append("[]");
|
||||||
|
@ -588,7 +588,7 @@ public final class Definition {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
} else if (clazz == def.class) {
|
} else if (clazz == def.class) {
|
||||||
return "def";
|
return def.class.getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
return clazz.getCanonicalName().replace('$', '.');
|
return clazz.getCanonicalName().replace('$', '.');
|
||||||
|
@ -606,20 +606,20 @@ public final class Definition {
|
||||||
++dimensions;
|
++dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clazz == def.class) {
|
if (component == def.class) {
|
||||||
return getType(structsMap.get("def"), dimensions);
|
return getType(structsMap.get(def.class.getSimpleName()), dimensions);
|
||||||
} else {
|
} else {
|
||||||
return getType(runtimeMap.get(clazz).struct, dimensions);
|
return getType(runtimeMap.get(component).struct, dimensions);
|
||||||
}
|
}
|
||||||
} else if (clazz == def.class) {
|
} else if (clazz == def.class) {
|
||||||
return getType(structsMap.get("def"), 0);
|
return getType(structsMap.get(def.class.getSimpleName()), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getType(structsMap.get(ClassToName(clazz)), 0);
|
return getType(structsMap.get(ClassToName(clazz)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> TypeToClass (Type type) {
|
public static Class<?> TypeToClass(Type type) {
|
||||||
if (type.dynamic) {
|
if (def.class.getSimpleName().equals(type.struct.name)) {
|
||||||
return ObjectClassTodefClass(type.clazz);
|
return ObjectClassTodefClass(type.clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +672,8 @@ public final class Definition {
|
||||||
String origin = null;
|
String origin = null;
|
||||||
|
|
||||||
// add the universal def type
|
// add the universal def type
|
||||||
structsMap.put("def", new Struct("def", Object.class, org.objectweb.asm.Type.getType(Object.class)));
|
structsMap.put(def.class.getSimpleName(),
|
||||||
|
new Struct(def.class.getSimpleName(), Object.class, org.objectweb.asm.Type.getType(Object.class)));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// first iteration collects all the Painless type names that
|
// first iteration collects all the Painless type names that
|
||||||
|
@ -777,7 +778,7 @@ public final class Definition {
|
||||||
copyStruct(painlessStruct.name, painlessSuperStructs);
|
copyStruct(painlessStruct.name, painlessSuperStructs);
|
||||||
|
|
||||||
// copies methods and fields from Object into interface types
|
// copies methods and fields from Object into interface types
|
||||||
if (painlessStruct.clazz.isInterface() || ("def").equals(painlessStruct.name)) {
|
if (painlessStruct.clazz.isInterface() || (def.class.getSimpleName()).equals(painlessStruct.name)) {
|
||||||
Struct painlessObjectStruct = javaClassesToPainlessStructs.get(Object.class);
|
Struct painlessObjectStruct = javaClassesToPainlessStructs.get(Object.class);
|
||||||
|
|
||||||
if (painlessObjectStruct != null) {
|
if (painlessObjectStruct != null) {
|
||||||
|
@ -835,7 +836,7 @@ public final class Definition {
|
||||||
charType = getType("char");
|
charType = getType("char");
|
||||||
CharacterType = getType("Character");
|
CharacterType = getType("Character");
|
||||||
ObjectType = getType("Object");
|
ObjectType = getType("Object");
|
||||||
DefType = getType("def");
|
DefType = getType(def.class.getSimpleName());
|
||||||
NumberType = getType("Number");
|
NumberType = getType("Number");
|
||||||
StringType = getType("String");
|
StringType = getType("String");
|
||||||
ExceptionType = getType("Exception");
|
ExceptionType = getType("Exception");
|
||||||
|
@ -1409,7 +1410,7 @@ public final class Definition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Type(name, dimensions, "def".equals(name), struct, clazz, type);
|
return new Type(name, dimensions, def.class.getSimpleName().equals(name), struct, clazz, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getDimensions(String name) {
|
private int getDimensions(String name) {
|
||||||
|
|
|
@ -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.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
import org.elasticsearch.painless.Location;
|
import org.elasticsearch.painless.Location;
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ public abstract class AExpression extends ANode {
|
||||||
* Set to the expected type this node needs to be. Note this variable
|
* Set to the expected type this node needs to be. Note this variable
|
||||||
* is always set by the parent as input and should never be read from.
|
* is always set by the parent as input and should never be read from.
|
||||||
*/
|
*/
|
||||||
Type expected = null;
|
Class<?> expected = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to the actual type this node is. Note this variable is always
|
* Set to the actual type this node is. Note this variable is always
|
||||||
|
@ -68,7 +67,7 @@ public abstract class AExpression extends ANode {
|
||||||
* node itself. <b>Also, actual can always be read after a cast is
|
* node itself. <b>Also, actual can always be read after a cast is
|
||||||
* called on this node to get the type of the node after the cast.</b>
|
* called on this node to get the type of the node after the cast.</b>
|
||||||
*/
|
*/
|
||||||
Type actual = null;
|
Class<?> actual = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set by {@link EExplicit} if a cast made on an expression node should be
|
* Set by {@link EExplicit} if a cast made on an expression node should be
|
||||||
|
@ -119,8 +118,7 @@ public abstract class AExpression extends ANode {
|
||||||
* @return The new child node for the parent node calling this method.
|
* @return The new child node for the parent node calling this method.
|
||||||
*/
|
*/
|
||||||
AExpression cast(Locals locals) {
|
AExpression cast(Locals locals) {
|
||||||
Cast cast =
|
Cast cast = AnalyzerCaster.getLegalCast(location, actual, expected, explicit, internal);
|
||||||
AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(actual), Definition.TypeToClass(expected), explicit, internal);
|
|
||||||
|
|
||||||
if (cast == null) {
|
if (cast == null) {
|
||||||
if (constant == null || this instanceof EConstant) {
|
if (constant == null || this instanceof EConstant) {
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
import org.elasticsearch.painless.Location;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
@ -86,7 +85,7 @@ abstract class AStoreable extends AExpression {
|
||||||
* actual will be set to this value. This is used for an optimization
|
* actual will be set to this value. This is used for an optimization
|
||||||
* during assignment to def type targets.
|
* during assignment to def type targets.
|
||||||
*/
|
*/
|
||||||
abstract void updateActual(Type actual);
|
abstract void updateActual(Class<?> actual);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before a storeable node is loaded or stored. Used to load prefixes and
|
* Called before a storeable node is loaded or stored. Used to load prefixes and
|
||||||
|
|
|
@ -22,9 +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.Cast;
|
import org.elasticsearch.painless.Definition.Cast;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Definition.def;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
@ -49,11 +47,10 @@ public final class EAssignment extends AExpression {
|
||||||
private Operation operation;
|
private Operation operation;
|
||||||
|
|
||||||
private boolean cat = false;
|
private boolean cat = false;
|
||||||
private Type promote = null;
|
private Class<?> promote = null;
|
||||||
private Type shiftDistance; // for shifts, the RHS is promoted independently
|
private Class<?> shiftDistance; // for shifts, the RHS is promoted independently
|
||||||
private Cast there = null;
|
private Cast there = null;
|
||||||
private Cast back = null;
|
private Cast back = null;
|
||||||
private Type DefType = null;
|
|
||||||
|
|
||||||
public EAssignment(Location location, AExpression lhs, AExpression rhs, boolean pre, boolean post, Operation operation) {
|
public EAssignment(Location location, AExpression lhs, AExpression rhs, boolean pre, boolean post, Operation operation) {
|
||||||
super(location);
|
super(location);
|
||||||
|
@ -83,8 +80,6 @@ public final class EAssignment extends AExpression {
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Illegal tree structure.");
|
throw new IllegalStateException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DefType = locals.getDefinition().DefType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeLHS(Locals locals) {
|
private void analyzeLHS(Locals locals) {
|
||||||
|
@ -108,11 +103,11 @@ public final class EAssignment extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == Operation.INCR) {
|
if (operation == Operation.INCR) {
|
||||||
if (lhs.actual.clazz == double.class) {
|
if (lhs.actual == double.class) {
|
||||||
rhs = new EConstant(location, 1D);
|
rhs = new EConstant(location, 1D);
|
||||||
} else if (lhs.actual.clazz == float.class) {
|
} else if (lhs.actual == float.class) {
|
||||||
rhs = new EConstant(location, 1F);
|
rhs = new EConstant(location, 1F);
|
||||||
} else if (lhs.actual.clazz == long.class) {
|
} else if (lhs.actual == long.class) {
|
||||||
rhs = new EConstant(location, 1L);
|
rhs = new EConstant(location, 1L);
|
||||||
} else {
|
} else {
|
||||||
rhs = new EConstant(location, 1);
|
rhs = new EConstant(location, 1);
|
||||||
|
@ -120,11 +115,11 @@ public final class EAssignment extends AExpression {
|
||||||
|
|
||||||
operation = Operation.ADD;
|
operation = Operation.ADD;
|
||||||
} else if (operation == Operation.DECR) {
|
} else if (operation == Operation.DECR) {
|
||||||
if (lhs.actual.clazz == double.class) {
|
if (lhs.actual == double.class) {
|
||||||
rhs = new EConstant(location, 1D);
|
rhs = new EConstant(location, 1D);
|
||||||
} else if (lhs.actual.clazz == float.class) {
|
} else if (lhs.actual == float.class) {
|
||||||
rhs = new EConstant(location, 1F);
|
rhs = new EConstant(location, 1F);
|
||||||
} else if (lhs.actual.clazz == long.class) {
|
} else if (lhs.actual == long.class) {
|
||||||
rhs = new EConstant(location, 1L);
|
rhs = new EConstant(location, 1L);
|
||||||
} else {
|
} else {
|
||||||
rhs = new EConstant(location, 1);
|
rhs = new EConstant(location, 1);
|
||||||
|
@ -143,41 +138,33 @@ public final class EAssignment extends AExpression {
|
||||||
boolean shift = false;
|
boolean shift = false;
|
||||||
|
|
||||||
if (operation == Operation.MUL) {
|
if (operation == Operation.MUL) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, rhs.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
|
|
||||||
} else if (operation == Operation.DIV) {
|
} else if (operation == Operation.DIV) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, rhs.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
|
|
||||||
} else if (operation == Operation.REM) {
|
} else if (operation == Operation.REM) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, rhs.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
|
|
||||||
} else if (operation == Operation.ADD) {
|
} else if (operation == Operation.ADD) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteAdd(lhs.actual, rhs.actual);
|
||||||
AnalyzerCaster.promoteAdd(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
|
|
||||||
} else if (operation == Operation.SUB) {
|
} else if (operation == Operation.SUB) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, rhs.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
|
|
||||||
} else if (operation == Operation.LSH) {
|
} else if (operation == Operation.LSH) {
|
||||||
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, false);
|
||||||
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
|
shiftDistance = AnalyzerCaster.promoteNumeric(rhs.actual, false);
|
||||||
shift = true;
|
shift = true;
|
||||||
} else if (operation == Operation.RSH) {
|
} else if (operation == Operation.RSH) {
|
||||||
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, false);
|
||||||
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
|
shiftDistance = AnalyzerCaster.promoteNumeric(rhs.actual, false);
|
||||||
shift = true;
|
shift = true;
|
||||||
} else if (operation == Operation.USH) {
|
} else if (operation == Operation.USH) {
|
||||||
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
|
promote = AnalyzerCaster.promoteNumeric(lhs.actual, false);
|
||||||
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
|
shiftDistance = AnalyzerCaster.promoteNumeric(rhs.actual, false);
|
||||||
shift = true;
|
shift = true;
|
||||||
} else if (operation == Operation.BWAND) {
|
} else if (operation == Operation.BWAND) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteXor(lhs.actual, rhs.actual);
|
||||||
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
|
|
||||||
} else if (operation == Operation.XOR) {
|
} else if (operation == Operation.XOR) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteXor(lhs.actual, rhs.actual);
|
||||||
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
|
|
||||||
} else if (operation == Operation.BWOR) {
|
} else if (operation == Operation.BWOR) {
|
||||||
promote = locals.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteXor(lhs.actual, rhs.actual);
|
||||||
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
|
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
@ -187,20 +174,20 @@ public final class EAssignment extends AExpression {
|
||||||
"[" + operation.symbol + "=] to types [" + lhs.actual + "] and [" + rhs.actual + "]."));
|
"[" + operation.symbol + "=] to types [" + lhs.actual + "] and [" + rhs.actual + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
cat = operation == Operation.ADD && promote.clazz == String.class;
|
cat = operation == Operation.ADD && promote == String.class;
|
||||||
|
|
||||||
if (cat) {
|
if (cat) {
|
||||||
if (rhs instanceof EBinary && ((EBinary)rhs).operation == Operation.ADD && rhs.actual.clazz == String.class) {
|
if (rhs instanceof EBinary && ((EBinary)rhs).operation == Operation.ADD && rhs.actual == String.class) {
|
||||||
((EBinary)rhs).cat = true;
|
((EBinary)rhs).cat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rhs.expected = rhs.actual;
|
rhs.expected = rhs.actual;
|
||||||
} else if (shift) {
|
} else if (shift) {
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
// shifts are promoted independently, but for the def type, we need object.
|
// shifts are promoted independently, but for the def type, we need object.
|
||||||
rhs.expected = promote;
|
rhs.expected = promote;
|
||||||
} else if (shiftDistance.clazz == long.class) {
|
} else if (shiftDistance == long.class) {
|
||||||
rhs.expected = locals.getDefinition().intType;
|
rhs.expected = int.class;
|
||||||
rhs.explicit = true;
|
rhs.explicit = true;
|
||||||
} else {
|
} else {
|
||||||
rhs.expected = shiftDistance;
|
rhs.expected = shiftDistance;
|
||||||
|
@ -211,11 +198,11 @@ public final class EAssignment extends AExpression {
|
||||||
|
|
||||||
rhs = rhs.cast(locals);
|
rhs = rhs.cast(locals);
|
||||||
|
|
||||||
there = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(lhs.actual), Definition.TypeToClass(promote), false, false);
|
there = AnalyzerCaster.getLegalCast(location, lhs.actual, promote, false, false);
|
||||||
back = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(promote), Definition.TypeToClass(lhs.actual), true, false);
|
back = AnalyzerCaster.getLegalCast(location, promote, lhs.actual, true, false);
|
||||||
|
|
||||||
this.statement = true;
|
this.statement = true;
|
||||||
this.actual = read ? lhs.actual : locals.getDefinition().voidType;
|
this.actual = read ? lhs.actual : void.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeSimple(Locals locals) {
|
private void analyzeSimple(Locals locals) {
|
||||||
|
@ -225,7 +212,7 @@ public final class EAssignment extends AExpression {
|
||||||
if (lhs.isDefOptimized()) {
|
if (lhs.isDefOptimized()) {
|
||||||
rhs.analyze(locals);
|
rhs.analyze(locals);
|
||||||
|
|
||||||
if (rhs.actual.clazz == void.class) {
|
if (rhs.actual == void.class) {
|
||||||
throw createError(new IllegalArgumentException("Right-hand side cannot be a [void] type for assignment."));
|
throw createError(new IllegalArgumentException("Right-hand side cannot be a [void] type for assignment."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +227,7 @@ public final class EAssignment extends AExpression {
|
||||||
rhs = rhs.cast(locals);
|
rhs = rhs.cast(locals);
|
||||||
|
|
||||||
this.statement = true;
|
this.statement = true;
|
||||||
this.actual = read ? lhs.actual : locals.getDefinition().voidType;
|
this.actual = read ? lhs.actual : void.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,20 +262,20 @@ public final class EAssignment extends AExpression {
|
||||||
writer.writeDup(lhs.accessElementCount(), catElementStackSize); // dup the top element and insert it
|
writer.writeDup(lhs.accessElementCount(), catElementStackSize); // dup the top element and insert it
|
||||||
// before concat helper on stack
|
// before concat helper on stack
|
||||||
lhs.load(writer, globals); // read the current lhs's value
|
lhs.load(writer, globals); // read the current lhs's value
|
||||||
writer.writeAppendStrings(Definition.TypeToClass(lhs.actual)); // append the lhs's value using the StringBuilder
|
writer.writeAppendStrings(lhs.actual); // append the lhs's value using the StringBuilder
|
||||||
|
|
||||||
rhs.write(writer, globals); // write the bytecode for the rhs
|
rhs.write(writer, globals); // write the bytecode for the rhs
|
||||||
|
|
||||||
if (!(rhs instanceof EBinary) || !((EBinary)rhs).cat) { // check to see if the rhs has already done a concatenation
|
if (!(rhs instanceof EBinary) || !((EBinary)rhs).cat) { // check to see if the rhs has already done a concatenation
|
||||||
writer.writeAppendStrings(Definition.TypeToClass(rhs.actual)); // append the rhs's value since it's hasn't already
|
writer.writeAppendStrings(rhs.actual); // append the rhs's value since it's hasn't already
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeToStrings(); // put the value for string concat onto the stack
|
writer.writeToStrings(); // put the value for string concat onto the stack
|
||||||
writer.writeCast(back); // if necessary, cast the String to the lhs actual type
|
writer.writeCast(back); // if necessary, cast the String to the lhs actual type
|
||||||
|
|
||||||
if (lhs.read) {
|
if (lhs.read) {
|
||||||
writer.writeDup(lhs.actual.type.getSize(), lhs.accessElementCount()); // if this lhs is also read
|
writer.writeDup(MethodWriter.getType(lhs.actual).getSize(), lhs.accessElementCount()); // if this lhs is also read
|
||||||
// from dup the value onto the stack
|
// from dup the value onto the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
||||||
|
@ -301,7 +288,7 @@ public final class EAssignment extends AExpression {
|
||||||
lhs.load(writer, globals); // load the current lhs's value
|
lhs.load(writer, globals); // load the current lhs's value
|
||||||
|
|
||||||
if (lhs.read && post) {
|
if (lhs.read && post) {
|
||||||
writer.writeDup(lhs.actual.type.getSize(), lhs.accessElementCount()); // dup the value if the lhs is also
|
writer.writeDup(MethodWriter.getType(lhs.actual).getSize(), lhs.accessElementCount()); // dup the value if the lhs is also
|
||||||
// read from and is a post increment
|
// read from and is a post increment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,18 +299,19 @@ public final class EAssignment extends AExpression {
|
||||||
// XXX: fix these types, but first we need def compound assignment tests.
|
// XXX: fix these types, but first we need def compound assignment tests.
|
||||||
// its tricky here as there are possibly explicit casts, too.
|
// its tricky here as there are possibly explicit casts, too.
|
||||||
// write the operation instruction for compound assignment
|
// write the operation instruction for compound assignment
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
writer.writeDynamicBinaryInstruction(
|
writer.writeDynamicBinaryInstruction(
|
||||||
location, Definition.TypeToClass(promote), def.class, def.class, operation, DefBootstrap.OPERATOR_COMPOUND_ASSIGNMENT);
|
location, promote, def.class, def.class, operation, DefBootstrap.OPERATOR_COMPOUND_ASSIGNMENT);
|
||||||
} else {
|
} else {
|
||||||
writer.writeBinaryInstruction(location, Definition.TypeToClass(promote), operation);
|
writer.writeBinaryInstruction(location, promote, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeCast(back); // if necessary cast the promotion type value back to the lhs's type
|
writer.writeCast(back); // if necessary cast the promotion type value back to the lhs's type
|
||||||
|
|
||||||
if (lhs.read && !post) {
|
if (lhs.read && !post) {
|
||||||
writer.writeDup(lhs.actual.type.getSize(), lhs.accessElementCount()); // dup the value if the lhs is also
|
writer.writeDup(MethodWriter.getType(lhs.actual).getSize(), lhs.accessElementCount()); // dup the value if the lhs is also
|
||||||
// read from and is not a post increment
|
// read from and is not a post
|
||||||
|
// increment
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
||||||
|
@ -333,7 +321,8 @@ public final class EAssignment extends AExpression {
|
||||||
rhs.write(writer, globals); // write the bytecode for the rhs rhs
|
rhs.write(writer, globals); // write the bytecode for the rhs rhs
|
||||||
|
|
||||||
if (lhs.read) {
|
if (lhs.read) {
|
||||||
writer.writeDup(lhs.actual.type.getSize(), lhs.accessElementCount()); // dup the value if the lhs is also read from
|
writer.writeDup(MethodWriter.getType(lhs.actual).getSize(), lhs.accessElementCount()); // dup the value if the lhs
|
||||||
|
// is also read from
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
||||||
|
|
|
@ -22,7 +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.Type;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
|
@ -44,8 +44,8 @@ public final class EBinary extends AExpression {
|
||||||
private AExpression left;
|
private AExpression left;
|
||||||
private AExpression right;
|
private AExpression right;
|
||||||
|
|
||||||
private Type promote = null; // promoted type
|
private Class<?> promote = null; // promoted type
|
||||||
private Type shiftDistance = null; // for shifts, the rhs is promoted independently
|
private Class<?> shiftDistance = null; // for shifts, the rhs is promoted independently
|
||||||
boolean cat = false;
|
boolean cat = false;
|
||||||
private boolean originallyExplicit = false; // record whether there was originally an explicit cast
|
private boolean originallyExplicit = false; // record whether there was originally an explicit cast
|
||||||
|
|
||||||
|
@ -102,17 +102,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
|
throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
|
@ -127,15 +126,13 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant * (int)right.constant;
|
constant = (int)left.constant * (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant * (long)right.constant;
|
constant = (long)left.constant * (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = (float)left.constant * (float)right.constant;
|
constant = (float)left.constant * (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = (double)left.constant * (double)right.constant;
|
constant = (double)left.constant * (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -147,17 +144,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply divide [/] to types " +
|
throw createError(new ClassCastException("Cannot apply divide [/] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -173,16 +169,14 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (sort == int.class) {
|
if (promote == int.class) {
|
||||||
constant = (int)left.constant / (int)right.constant;
|
constant = (int)left.constant / (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant / (long)right.constant;
|
constant = (long)left.constant / (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = (float)left.constant / (float)right.constant;
|
constant = (float)left.constant / (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = (double)left.constant / (double)right.constant;
|
constant = (double)left.constant / (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -197,17 +191,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
|
throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -223,16 +216,14 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (sort == int.class) {
|
if (promote == int.class) {
|
||||||
constant = (int)left.constant % (int)right.constant;
|
constant = (int)left.constant % (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant % (long)right.constant;
|
constant = (long)left.constant % (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = (float)left.constant % (float)right.constant;
|
constant = (float)left.constant % (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = (double)left.constant % (double)right.constant;
|
constant = (double)left.constant % (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -247,31 +238,28 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteAdd(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteAdd(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply add [+] to types " +
|
throw createError(new ClassCastException("Cannot apply add [+] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> sort = promote.clazz;
|
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (sort == String.class) {
|
if (promote == String.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
|
|
||||||
if (left instanceof EBinary && ((EBinary)left).operation == Operation.ADD && left.actual.clazz == String.class) {
|
if (left instanceof EBinary && ((EBinary)left).operation == Operation.ADD && left.actual == String.class) {
|
||||||
((EBinary)left).cat = true;
|
((EBinary)left).cat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
if (right instanceof EBinary && ((EBinary)right).operation == Operation.ADD && right.actual.clazz == String.class) {
|
if (right instanceof EBinary && ((EBinary)right).operation == Operation.ADD && right.actual == String.class) {
|
||||||
((EBinary)right).cat = true;
|
((EBinary)right).cat = true;
|
||||||
}
|
}
|
||||||
} else if (promote.dynamic) {
|
} else if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -287,15 +275,15 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
if (sort == int.class) {
|
if (promote == int.class) {
|
||||||
constant = (int)left.constant + (int)right.constant;
|
constant = (int)left.constant + (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant + (long)right.constant;
|
constant = (long)left.constant + (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = (float)left.constant + (float)right.constant;
|
constant = (float)left.constant + (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = (double)left.constant + (double)right.constant;
|
constant = (double)left.constant + (double)right.constant;
|
||||||
} else if (sort == String.class) {
|
} else if (promote == String.class) {
|
||||||
constant = left.constant.toString() + right.constant.toString();
|
constant = left.constant.toString() + right.constant.toString();
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -308,17 +296,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
|
throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -334,15 +321,13 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant - (int)right.constant;
|
constant = (int)left.constant - (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant - (long)right.constant;
|
constant = (long)left.constant - (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = (float)left.constant - (float)right.constant;
|
constant = (float)left.constant - (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = (double)left.constant - (double)right.constant;
|
constant = (double)left.constant - (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -354,32 +339,32 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
left.expected = variables.getDefinition().StringType;
|
left.expected = String.class;
|
||||||
right.expected = variables.getDefinition().PatternType;
|
right.expected = Pattern.class;
|
||||||
|
|
||||||
left = left.cast(variables);
|
left = left.cast(variables);
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().booleanType;
|
promote = boolean.class;
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeLSH(Locals variables) {
|
private void analyzeLSH(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
|
Class<?> lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||||
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
|
Class<?> rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false);
|
||||||
|
|
||||||
if (lhspromote == null || rhspromote == null) {
|
if (lhspromote == null || rhspromote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply left shift [<<] to types " +
|
throw createError(new ClassCastException("Cannot apply left shift [<<] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote = lhspromote;
|
actual = promote = lhspromote;
|
||||||
shiftDistance = rhspromote;
|
shiftDistance = rhspromote;
|
||||||
|
|
||||||
if (lhspromote.dynamic || rhspromote.dynamic) {
|
if (lhspromote == def.class || rhspromote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -389,8 +374,8 @@ public final class EBinary extends AExpression {
|
||||||
} else {
|
} else {
|
||||||
left.expected = lhspromote;
|
left.expected = lhspromote;
|
||||||
|
|
||||||
if (rhspromote.clazz == long.class) {
|
if (rhspromote == long.class) {
|
||||||
right.expected = variables.getDefinition().intType;
|
right.expected = int.class;
|
||||||
right.explicit = true;
|
right.explicit = true;
|
||||||
} else {
|
} else {
|
||||||
right.expected = rhspromote;
|
right.expected = rhspromote;
|
||||||
|
@ -401,11 +386,9 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = lhspromote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant << (int)right.constant;
|
constant = (int)left.constant << (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant << (int)right.constant;
|
constant = (long)left.constant << (int)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -417,18 +400,18 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
|
Class<?> lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||||
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
|
Class<?> rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false);
|
||||||
|
|
||||||
if (lhspromote == null || rhspromote == null) {
|
if (lhspromote == null || rhspromote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply right shift [>>] to types " +
|
throw createError(new ClassCastException("Cannot apply right shift [>>] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote = lhspromote;
|
actual = promote = lhspromote;
|
||||||
shiftDistance = rhspromote;
|
shiftDistance = rhspromote;
|
||||||
|
|
||||||
if (lhspromote.dynamic || rhspromote.dynamic) {
|
if (lhspromote == def.class || rhspromote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -438,8 +421,8 @@ public final class EBinary extends AExpression {
|
||||||
} else {
|
} else {
|
||||||
left.expected = lhspromote;
|
left.expected = lhspromote;
|
||||||
|
|
||||||
if (rhspromote.clazz == long.class) {
|
if (rhspromote == long.class) {
|
||||||
right.expected = variables.getDefinition().intType;
|
right.expected = int.class;
|
||||||
right.explicit = true;
|
right.explicit = true;
|
||||||
} else {
|
} else {
|
||||||
right.expected = rhspromote;
|
right.expected = rhspromote;
|
||||||
|
@ -450,11 +433,9 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = lhspromote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant >> (int)right.constant;
|
constant = (int)left.constant >> (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant >> (int)right.constant;
|
constant = (long)left.constant >> (int)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -466,18 +447,18 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
|
Class<?> lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||||
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
|
Class<?> rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false);
|
||||||
|
|
||||||
actual = promote = lhspromote;
|
actual = promote = lhspromote;
|
||||||
shiftDistance = rhspromote;
|
shiftDistance = rhspromote;
|
||||||
|
|
||||||
if (lhspromote == null || rhspromote == null) {
|
if (lhspromote == null || rhspromote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " +
|
throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lhspromote.dynamic || rhspromote.dynamic) {
|
if (lhspromote == def.class || rhspromote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -487,8 +468,8 @@ public final class EBinary extends AExpression {
|
||||||
} else {
|
} else {
|
||||||
left.expected = lhspromote;
|
left.expected = lhspromote;
|
||||||
|
|
||||||
if (rhspromote.clazz == long.class) {
|
if (rhspromote == long.class) {
|
||||||
right.expected = variables.getDefinition().intType;
|
right.expected = int.class;
|
||||||
right.explicit = true;
|
right.explicit = true;
|
||||||
} else {
|
} else {
|
||||||
right.expected = rhspromote;
|
right.expected = rhspromote;
|
||||||
|
@ -499,11 +480,9 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = lhspromote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant >>> (int)right.constant;
|
constant = (int)left.constant >>> (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant >>> (int)right.constant;
|
constant = (long)left.constant >>> (int)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -515,17 +494,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), false));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply and [&] to types " +
|
throw createError(new ClassCastException("Cannot apply and [&] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
|
|
||||||
|
@ -541,11 +519,9 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant & (int)right.constant;
|
constant = (int)left.constant & (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant & (long)right.constant;
|
constant = (long)left.constant & (long)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -557,17 +533,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteXor(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteXor(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply xor [^] to types " +
|
throw createError(new ClassCastException("Cannot apply xor [^] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
|
@ -582,13 +557,11 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == boolean.class) {
|
||||||
|
|
||||||
if (sort == boolean.class) {
|
|
||||||
constant = (boolean)left.constant ^ (boolean)right.constant;
|
constant = (boolean)left.constant ^ (boolean)right.constant;
|
||||||
} else if (sort == int.class) {
|
} else if (promote == int.class) {
|
||||||
constant = (int)left.constant ^ (int)right.constant;
|
constant = (int)left.constant ^ (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant ^ (long)right.constant;
|
constant = (long)left.constant ^ (long)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -600,17 +573,16 @@ public final class EBinary extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(
|
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), false));
|
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply or [|] to types " +
|
throw createError(new ClassCastException("Cannot apply or [|] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
|
@ -625,11 +597,9 @@ public final class EBinary extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant | (int)right.constant;
|
constant = (int)left.constant | (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = (long)left.constant | (long)right.constant;
|
constant = (long)left.constant | (long)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -641,7 +611,7 @@ public final class EBinary extends AExpression {
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
if (promote.clazz == String.class && operation == Operation.ADD) {
|
if (promote == String.class && operation == Operation.ADD) {
|
||||||
if (!cat) {
|
if (!cat) {
|
||||||
writer.writeNewStrings();
|
writer.writeNewStrings();
|
||||||
}
|
}
|
||||||
|
@ -649,13 +619,13 @@ public final class EBinary extends AExpression {
|
||||||
left.write(writer, globals);
|
left.write(writer, globals);
|
||||||
|
|
||||||
if (!(left instanceof EBinary) || !((EBinary)left).cat) {
|
if (!(left instanceof EBinary) || !((EBinary)left).cat) {
|
||||||
writer.writeAppendStrings(Definition.TypeToClass(left.actual));
|
writer.writeAppendStrings(left.actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
right.write(writer, globals);
|
right.write(writer, globals);
|
||||||
|
|
||||||
if (!(right instanceof EBinary) || !((EBinary)right).cat) {
|
if (!(right instanceof EBinary) || !((EBinary)right).cat) {
|
||||||
writer.writeAppendStrings(Definition.TypeToClass(right.actual));
|
writer.writeAppendStrings(right.actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cat) {
|
if (!cat) {
|
||||||
|
@ -677,17 +647,16 @@ public final class EBinary extends AExpression {
|
||||||
left.write(writer, globals);
|
left.write(writer, globals);
|
||||||
right.write(writer, globals);
|
right.write(writer, globals);
|
||||||
|
|
||||||
if (promote.dynamic || (shiftDistance != null && shiftDistance.dynamic)) {
|
if (promote == def.class || (shiftDistance != null && shiftDistance == def.class)) {
|
||||||
// def calls adopt the wanted return value. if there was a narrowing cast,
|
// def calls adopt the wanted return value. if there was a narrowing cast,
|
||||||
// we need to flag that so that its done at runtime.
|
// we need to flag that so that its done at runtime.
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (originallyExplicit) {
|
if (originallyExplicit) {
|
||||||
flags |= DefBootstrap.OPERATOR_EXPLICIT_CAST;
|
flags |= DefBootstrap.OPERATOR_EXPLICIT_CAST;
|
||||||
}
|
}
|
||||||
writer.writeDynamicBinaryInstruction(location, Definition.TypeToClass(actual),
|
writer.writeDynamicBinaryInstruction(location, actual, left.actual, right.actual, operation, flags);
|
||||||
Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), operation, flags);
|
|
||||||
} else {
|
} else {
|
||||||
writer.writeBinaryInstruction(location, Definition.TypeToClass(actual), operation);
|
writer.writeBinaryInstruction(location, actual, operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,17 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Operation;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
import org.elasticsearch.painless.Operation;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a boolean expression.
|
* Represents a boolean expression.
|
||||||
*/
|
*/
|
||||||
|
@ -57,11 +55,11 @@ public final class EBool extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
left.expected = locals.getDefinition().booleanType;
|
left.expected = boolean.class;
|
||||||
left.analyze(locals);
|
left.analyze(locals);
|
||||||
left = left.cast(locals);
|
left = left.cast(locals);
|
||||||
|
|
||||||
right.expected = locals.getDefinition().booleanType;
|
right.expected = boolean.class;
|
||||||
right.analyze(locals);
|
right.analyze(locals);
|
||||||
right = right.cast(locals);
|
right = right.cast(locals);
|
||||||
|
|
||||||
|
@ -75,7 +73,7 @@ public final class EBool extends AExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -49,7 +48,7 @@ public final class EBoolean extends AExpression {
|
||||||
throw createError(new IllegalArgumentException("Must read from constant [" + constant + "]."));
|
throw createError(new IllegalArgumentException("Must read from constant [" + constant + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
import org.elasticsearch.painless.Definition.MethodKey;
|
import org.elasticsearch.painless.Definition.MethodKey;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
|
@ -68,14 +69,14 @@ public final class ECallLocal extends AExpression {
|
||||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||||
AExpression expression = arguments.get(argument);
|
AExpression expression = arguments.get(argument);
|
||||||
|
|
||||||
expression.expected = method.arguments.get(argument);
|
expression.expected = Definition.TypeToClass(method.arguments.get(argument));
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
arguments.set(argument, expression.cast(locals));
|
arguments.set(argument, expression.cast(locals));
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = true;
|
statement = true;
|
||||||
actual = method.rtn;
|
actual = Definition.TypeToClass(method.rtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -70,13 +70,14 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
||||||
// typed implementation
|
// typed implementation
|
||||||
defPointer = "S" + captured.type.name + "." + call + ",1";
|
defPointer = "S" + captured.type.name + "." + call + ",1";
|
||||||
}
|
}
|
||||||
actual = locals.getDefinition().getType("String");
|
actual = String.class;
|
||||||
} else {
|
} else {
|
||||||
defPointer = null;
|
defPointer = null;
|
||||||
// static case
|
// static case
|
||||||
if (captured.type.dynamic == false) {
|
if (captured.type.dynamic == false) {
|
||||||
try {
|
try {
|
||||||
ref = new FunctionRef(locals.getDefinition(), expected, captured.type.name, call, 1);
|
ref = new FunctionRef(
|
||||||
|
locals.getDefinition(), locals.getDefinition().ClassToType(expected), captured.type.name, 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) {
|
||||||
|
@ -108,8 +109,8 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
||||||
} 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(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
|
||||||
Type methodType = Type.getMethodType(expected.type, captured.type.type);
|
Type methodType = Type.getMethodType(MethodWriter.getType(expected), captured.type.type);
|
||||||
writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, expected.name);
|
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(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
|
||||||
|
|
|
@ -21,15 +21,14 @@ package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
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.Globals;
|
||||||
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a cast that is inserted into the tree replacing other casts. (Internal only.)
|
* Represents a cast that is inserted into the tree replacing other casts. (Internal only.)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,23 +19,23 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.AnalyzerCaster;
|
import org.elasticsearch.painless.AnalyzerCaster;
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
import org.elasticsearch.painless.Operation;
|
import org.elasticsearch.painless.Definition;
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
import org.elasticsearch.painless.Operation;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
import static org.elasticsearch.painless.WriterConstants.OBJECTS_TYPE;
|
|
||||||
import static org.elasticsearch.painless.WriterConstants.EQUALS;
|
import static org.elasticsearch.painless.WriterConstants.EQUALS;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.OBJECTS_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a comparison expression.
|
* Represents a comparison expression.
|
||||||
|
@ -46,7 +46,7 @@ public final class EComp extends AExpression {
|
||||||
private AExpression left;
|
private AExpression left;
|
||||||
private AExpression right;
|
private AExpression right;
|
||||||
|
|
||||||
private Type promotedType;
|
private Class<?> promotedType;
|
||||||
|
|
||||||
public EComp(Location location, Operation operation, AExpression left, AExpression right) {
|
public EComp(Location location, Operation operation, AExpression left, AExpression right) {
|
||||||
super(location);
|
super(location);
|
||||||
|
@ -89,15 +89,14 @@ public final class EComp extends AExpression {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply equals [==] to types " +
|
throw createError(new ClassCastException("Cannot apply equals [==] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,17 +112,15 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == boolean.class) {
|
||||||
|
|
||||||
if (sort == boolean.class) {
|
|
||||||
constant = (boolean)left.constant == (boolean)right.constant;
|
constant = (boolean)left.constant == (boolean)right.constant;
|
||||||
} else if (sort == int.class) {
|
} else if (promotedType == int.class) {
|
||||||
constant = (int)left.constant == (int)right.constant;
|
constant = (int)left.constant == (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant == (long)right.constant;
|
constant = (long)left.constant == (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant == (float)right.constant;
|
constant = (float)left.constant == (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant == (double)right.constant;
|
constant = (double)left.constant == (double)right.constant;
|
||||||
} else if (!left.isNull) {
|
} else if (!left.isNull) {
|
||||||
constant = left.constant.equals(right.constant);
|
constant = left.constant.equals(right.constant);
|
||||||
|
@ -134,19 +131,18 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeEqR(Locals variables) {
|
private void analyzeEqR(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
|
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
left.expected = promotedType;
|
left.expected = promotedType;
|
||||||
|
@ -160,39 +156,36 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == boolean.class) {
|
||||||
|
|
||||||
if (sort == boolean.class) {
|
|
||||||
constant = (boolean)left.constant == (boolean)right.constant;
|
constant = (boolean)left.constant == (boolean)right.constant;
|
||||||
} else if (sort == int.class) {
|
} else if (promotedType == int.class) {
|
||||||
constant = (int)left.constant == (int)right.constant;
|
constant = (int)left.constant == (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant == (long)right.constant;
|
constant = (long)left.constant == (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant == (float)right.constant;
|
constant = (float)left.constant == (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant == (double)right.constant;
|
constant = (double)left.constant == (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
constant = left.constant == right.constant;
|
constant = left.constant == right.constant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeNE(Locals variables) {
|
private void analyzeNE(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
|
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,17 +201,15 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == boolean.class) {
|
||||||
|
|
||||||
if (sort == boolean.class) {
|
|
||||||
constant = (boolean)left.constant != (boolean)right.constant;
|
constant = (boolean)left.constant != (boolean)right.constant;
|
||||||
} else if (sort == int.class) {
|
} else if (promotedType == int.class) {
|
||||||
constant = (int)left.constant != (int)right.constant;
|
constant = (int)left.constant != (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant != (long)right.constant;
|
constant = (long)left.constant != (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant != (float)right.constant;
|
constant = (float)left.constant != (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant != (double)right.constant;
|
constant = (double)left.constant != (double)right.constant;
|
||||||
} else if (!left.isNull) {
|
} else if (!left.isNull) {
|
||||||
constant = !left.constant.equals(right.constant);
|
constant = !left.constant.equals(right.constant);
|
||||||
|
@ -229,19 +220,18 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeNER(Locals variables) {
|
private void analyzeNER(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||||
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
|
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
left.expected = promotedType;
|
left.expected = promotedType;
|
||||||
|
@ -255,39 +245,36 @@ public final class EComp extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == boolean.class) {
|
||||||
|
|
||||||
if (sort == boolean.class) {
|
|
||||||
constant = (boolean)left.constant != (boolean)right.constant;
|
constant = (boolean)left.constant != (boolean)right.constant;
|
||||||
} else if (sort == int.class) {
|
} else if (promotedType == int.class) {
|
||||||
constant = (int)left.constant != (int)right.constant;
|
constant = (int)left.constant != (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant != (long)right.constant;
|
constant = (long)left.constant != (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant != (float)right.constant;
|
constant = (float)left.constant != (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant != (double)right.constant;
|
constant = (double)left.constant != (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
constant = left.constant != right.constant;
|
constant = left.constant != right.constant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeGTE(Locals variables) {
|
private void analyzeGTE(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
|
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -299,37 +286,34 @@ public final class EComp extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant >= (int)right.constant;
|
constant = (int)left.constant >= (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant >= (long)right.constant;
|
constant = (long)left.constant >= (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant >= (float)right.constant;
|
constant = (float)left.constant >= (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant >= (double)right.constant;
|
constant = (double)left.constant >= (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeGT(Locals variables) {
|
private void analyzeGT(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
|
throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -341,37 +325,34 @@ public final class EComp extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant > (int)right.constant;
|
constant = (int)left.constant > (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant > (long)right.constant;
|
constant = (long)left.constant > (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant > (float)right.constant;
|
constant = (float)left.constant > (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant > (double)right.constant;
|
constant = (double)left.constant > (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeLTE(Locals variables) {
|
private void analyzeLTE(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
|
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -383,37 +364,34 @@ public final class EComp extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant <= (int)right.constant;
|
constant = (int)left.constant <= (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant <= (long)right.constant;
|
constant = (long)left.constant <= (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant <= (float)right.constant;
|
constant = (float)left.constant <= (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant <= (double)right.constant;
|
constant = (double)left.constant <= (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeLT(Locals variables) {
|
private void analyzeLT(Locals variables) {
|
||||||
left.analyze(variables);
|
left.analyze(variables);
|
||||||
right.analyze(variables);
|
right.analyze(variables);
|
||||||
|
|
||||||
promotedType = variables.getDefinition().ClassToType(
|
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||||
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
|
|
||||||
|
|
||||||
if (promotedType == null) {
|
if (promotedType == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply less than [>=] to types " +
|
throw createError(new ClassCastException("Cannot apply less than [>=] to types " +
|
||||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
"[" + Definition.ClassToName(left.actual) + "] and [" + Definition.ClassToName(right.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promotedType.dynamic) {
|
if (promotedType == def.class) {
|
||||||
left.expected = left.actual;
|
left.expected = left.actual;
|
||||||
right.expected = right.actual;
|
right.expected = right.actual;
|
||||||
} else {
|
} else {
|
||||||
|
@ -425,22 +403,20 @@ public final class EComp extends AExpression {
|
||||||
right = right.cast(variables);
|
right = right.cast(variables);
|
||||||
|
|
||||||
if (left.constant != null && right.constant != null) {
|
if (left.constant != null && right.constant != null) {
|
||||||
Class<?> sort = promotedType.clazz;
|
if (promotedType == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = (int)left.constant < (int)right.constant;
|
constant = (int)left.constant < (int)right.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promotedType == long.class) {
|
||||||
constant = (long)left.constant < (long)right.constant;
|
constant = (long)left.constant < (long)right.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promotedType == float.class) {
|
||||||
constant = (float)left.constant < (float)right.constant;
|
constant = (float)left.constant < (float)right.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promotedType == double.class) {
|
||||||
constant = (double)left.constant < (double)right.constant;
|
constant = (double)left.constant < (double)right.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -465,30 +441,30 @@ public final class EComp extends AExpression {
|
||||||
|
|
||||||
boolean writejump = true;
|
boolean writejump = true;
|
||||||
|
|
||||||
Class<?> sort = promotedType.clazz;
|
Type type = MethodWriter.getType(promotedType);
|
||||||
|
|
||||||
if (sort == void.class || sort == byte.class || sort == short.class || sort == char.class) {
|
if (promotedType == void.class || promotedType == byte.class || promotedType == short.class || promotedType == char.class) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
} else if (sort == boolean.class) {
|
} else if (promotedType == boolean.class) {
|
||||||
if (eq) writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
if (eq) writer.ifCmp(type, MethodWriter.EQ, jump);
|
||||||
else if (ne) writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
else if (ne) writer.ifCmp(type, MethodWriter.NE, jump);
|
||||||
else {
|
else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
} else if (sort == int.class || sort == long.class || sort == float.class || sort == double.class) {
|
} else if (promotedType == int.class || promotedType == long.class || promotedType == float.class || promotedType == double.class) {
|
||||||
if (eq) writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
if (eq) writer.ifCmp(type, MethodWriter.EQ, jump);
|
||||||
else if (ne) writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
else if (ne) writer.ifCmp(type, MethodWriter.NE, jump);
|
||||||
else if (lt) writer.ifCmp(promotedType.type, MethodWriter.LT, jump);
|
else if (lt) writer.ifCmp(type, MethodWriter.LT, jump);
|
||||||
else if (lte) writer.ifCmp(promotedType.type, MethodWriter.LE, jump);
|
else if (lte) writer.ifCmp(type, MethodWriter.LE, jump);
|
||||||
else if (gt) writer.ifCmp(promotedType.type, MethodWriter.GT, jump);
|
else if (gt) writer.ifCmp(type, MethodWriter.GT, jump);
|
||||||
else if (gte) writer.ifCmp(promotedType.type, MethodWriter.GE, jump);
|
else if (gte) writer.ifCmp(type, MethodWriter.GE, jump);
|
||||||
else {
|
else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (promotedType.dynamic) {
|
} else if (promotedType == def.class) {
|
||||||
org.objectweb.asm.Type booleanType = org.objectweb.asm.Type.getType(boolean.class);
|
Type booleanType = Type.getType(boolean.class);
|
||||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(booleanType, left.actual.type, right.actual.type);
|
Type descriptor = Type.getMethodType(booleanType, MethodWriter.getType(left.actual), MethodWriter.getType(right.actual));
|
||||||
|
|
||||||
if (eq) {
|
if (eq) {
|
||||||
if (right.isNull) {
|
if (right.isNull) {
|
||||||
|
@ -497,7 +473,7 @@ public final class EComp extends AExpression {
|
||||||
writer.invokeDefCall("eq", descriptor, DefBootstrap.BINARY_OPERATOR, DefBootstrap.OPERATOR_ALLOWS_NULL);
|
writer.invokeDefCall("eq", descriptor, DefBootstrap.BINARY_OPERATOR, DefBootstrap.OPERATOR_ALLOWS_NULL);
|
||||||
writejump = false;
|
writejump = false;
|
||||||
} else {
|
} else {
|
||||||
writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
writer.ifCmp(type, MethodWriter.EQ, jump);
|
||||||
}
|
}
|
||||||
} else if (ne) {
|
} else if (ne) {
|
||||||
if (right.isNull) {
|
if (right.isNull) {
|
||||||
|
@ -506,7 +482,7 @@ public final class EComp extends AExpression {
|
||||||
writer.invokeDefCall("eq", descriptor, DefBootstrap.BINARY_OPERATOR, DefBootstrap.OPERATOR_ALLOWS_NULL);
|
writer.invokeDefCall("eq", descriptor, DefBootstrap.BINARY_OPERATOR, DefBootstrap.OPERATOR_ALLOWS_NULL);
|
||||||
writer.ifZCmp(MethodWriter.EQ, jump);
|
writer.ifZCmp(MethodWriter.EQ, jump);
|
||||||
} else {
|
} else {
|
||||||
writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
writer.ifCmp(type, MethodWriter.NE, jump);
|
||||||
}
|
}
|
||||||
} else if (lt) {
|
} else if (lt) {
|
||||||
writer.invokeDefCall("lt", descriptor, DefBootstrap.BINARY_OPERATOR, 0);
|
writer.invokeDefCall("lt", descriptor, DefBootstrap.BINARY_OPERATOR, 0);
|
||||||
|
@ -531,7 +507,7 @@ public final class EComp extends AExpression {
|
||||||
writer.invokeStatic(OBJECTS_TYPE, EQUALS);
|
writer.invokeStatic(OBJECTS_TYPE, EQUALS);
|
||||||
writejump = false;
|
writejump = false;
|
||||||
} else {
|
} else {
|
||||||
writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
writer.ifCmp(type, MethodWriter.EQ, jump);
|
||||||
}
|
}
|
||||||
} else if (ne) {
|
} else if (ne) {
|
||||||
if (right.isNull) {
|
if (right.isNull) {
|
||||||
|
@ -540,7 +516,7 @@ public final class EComp extends AExpression {
|
||||||
writer.invokeStatic(OBJECTS_TYPE, EQUALS);
|
writer.invokeStatic(OBJECTS_TYPE, EQUALS);
|
||||||
writer.ifZCmp(MethodWriter.EQ, jump);
|
writer.ifZCmp(MethodWriter.EQ, jump);
|
||||||
} else {
|
} else {
|
||||||
writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
writer.ifCmp(type, MethodWriter.NE, jump);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
|
|
@ -19,20 +19,17 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.AnalyzerCaster;
|
import org.elasticsearch.painless.AnalyzerCaster;
|
||||||
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a conditional expression.
|
* Represents a conditional expression.
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +56,7 @@ public final class EConditional extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
@ -79,8 +76,7 @@ public final class EConditional extends AExpression {
|
||||||
right.analyze(locals);
|
right.analyze(locals);
|
||||||
|
|
||||||
if (expected == null) {
|
if (expected == null) {
|
||||||
Type promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteConditional(
|
Class<?> promote = AnalyzerCaster.promoteConditional(left.actual, right.actual, left.constant, right.constant);
|
||||||
Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), left.constant, right.constant));
|
|
||||||
|
|
||||||
left.expected = promote;
|
left.expected = promote;
|
||||||
right.expected = promote;
|
right.expected = promote;
|
||||||
|
|
|
@ -19,15 +19,13 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a constant inserted into the tree replacing
|
* Represents a constant inserted into the tree replacing
|
||||||
* other constants during constant folding. (Internal only.)
|
* other constants during constant folding. (Internal only.)
|
||||||
|
@ -48,23 +46,23 @@ final class EConstant extends AExpression {
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
if (constant instanceof String) {
|
if (constant instanceof String) {
|
||||||
actual = locals.getDefinition().StringType;
|
actual = String.class;
|
||||||
} else if (constant instanceof Double) {
|
} else if (constant instanceof Double) {
|
||||||
actual = locals.getDefinition().doubleType;
|
actual = double.class;
|
||||||
} else if (constant instanceof Float) {
|
} else if (constant instanceof Float) {
|
||||||
actual = locals.getDefinition().floatType;
|
actual = float.class;
|
||||||
} else if (constant instanceof Long) {
|
} else if (constant instanceof Long) {
|
||||||
actual = locals.getDefinition().longType;
|
actual = long.class;
|
||||||
} else if (constant instanceof Integer) {
|
} else if (constant instanceof Integer) {
|
||||||
actual = locals.getDefinition().intType;
|
actual = int.class;
|
||||||
} else if (constant instanceof Character) {
|
} else if (constant instanceof Character) {
|
||||||
actual = locals.getDefinition().charType;
|
actual = char.class;
|
||||||
} else if (constant instanceof Short) {
|
} else if (constant instanceof Short) {
|
||||||
actual = locals.getDefinition().shortType;
|
actual = short.class;
|
||||||
} else if (constant instanceof Byte) {
|
} else if (constant instanceof Byte) {
|
||||||
actual = locals.getDefinition().byteType;
|
actual = byte.class;
|
||||||
} else if (constant instanceof Boolean) {
|
} else if (constant instanceof Boolean) {
|
||||||
actual = locals.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
@ -72,15 +70,15 @@ final class EConstant extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
if (actual.clazz == String.class) writer.push((String)constant);
|
if (actual == String.class) writer.push((String)constant);
|
||||||
else if (actual.clazz == double.class) writer.push((double)constant);
|
else if (actual == double.class) writer.push((double)constant);
|
||||||
else if (actual.clazz == float.class) writer.push((float)constant);
|
else if (actual == float.class) writer.push((float)constant);
|
||||||
else if (actual.clazz == long.class) writer.push((long)constant);
|
else if (actual == long.class) writer.push((long)constant);
|
||||||
else if (actual.clazz == int.class) writer.push((int)constant);
|
else if (actual == int.class) writer.push((int)constant);
|
||||||
else if (actual.clazz == char.class) writer.push((char)constant);
|
else if (actual == char.class) writer.push((char)constant);
|
||||||
else if (actual.clazz == short.class) writer.push((short)constant);
|
else if (actual == short.class) writer.push((short)constant);
|
||||||
else if (actual.clazz == byte.class) writer.push((byte)constant);
|
else if (actual == byte.class) writer.push((byte)constant);
|
||||||
else if (actual.clazz == boolean.class) writer.push((boolean)constant);
|
else if (actual == boolean.class) writer.push((boolean)constant);
|
||||||
else {
|
else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -53,7 +52,7 @@ public final class EDecimal extends AExpression {
|
||||||
if (value.endsWith("f") || value.endsWith("F")) {
|
if (value.endsWith("f") || value.endsWith("F")) {
|
||||||
try {
|
try {
|
||||||
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
||||||
actual = locals.getDefinition().floatType;
|
actual = float.class;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +63,7 @@ public final class EDecimal extends AExpression {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
constant = Double.parseDouble(toParse);
|
constant = Double.parseDouble(toParse);
|
||||||
actual = locals.getDefinition().doubleType;
|
actual = double.class;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
package org.elasticsearch.painless.node;
|
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.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;
|
||||||
|
@ -55,7 +53,7 @@ public class EElvis extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
if (expected != null && expected.clazz.isPrimitive()) {
|
if (expected != null && expected.isPrimitive()) {
|
||||||
throw createError(new IllegalArgumentException("Elvis operator cannot return primitives"));
|
throw createError(new IllegalArgumentException("Elvis operator cannot return primitives"));
|
||||||
}
|
}
|
||||||
lhs.expected = expected;
|
lhs.expected = expected;
|
||||||
|
@ -74,7 +72,7 @@ public class EElvis extends AExpression {
|
||||||
if (lhs.constant != null) {
|
if (lhs.constant != null) {
|
||||||
throw createError(new IllegalArgumentException("Extraneous elvis operator. LHS is a constant."));
|
throw createError(new IllegalArgumentException("Extraneous elvis operator. LHS is a constant."));
|
||||||
}
|
}
|
||||||
if (lhs.actual.clazz.isPrimitive()) {
|
if (lhs.actual.isPrimitive()) {
|
||||||
throw createError(new IllegalArgumentException("Extraneous elvis operator. LHS is a primitive."));
|
throw createError(new IllegalArgumentException("Extraneous elvis operator. LHS is a primitive."));
|
||||||
}
|
}
|
||||||
if (rhs.isNull) {
|
if (rhs.isNull) {
|
||||||
|
@ -82,8 +80,7 @@ public class EElvis extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expected == null) {
|
if (expected == null) {
|
||||||
Type promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteConditional(
|
Class<?> promote = AnalyzerCaster.promoteConditional(lhs.actual, rhs.actual, lhs.constant, rhs.constant);
|
||||||
Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), lhs.constant, rhs.constant));
|
|
||||||
|
|
||||||
lhs.expected = promote;
|
lhs.expected = promote;
|
||||||
rhs.expected = promote;
|
rhs.expected = promote;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
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;
|
||||||
|
@ -50,9 +51,9 @@ public final class EExplicit extends AExpression {
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
try {
|
try {
|
||||||
actual = locals.getDefinition().getType(type);
|
actual = Definition.TypeToClass(locals.getDefinition().getType(type));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
throw createError(new IllegalArgumentException("Not a type [" + type + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
child.expected = actual;
|
child.expected = actual;
|
||||||
|
|
|
@ -59,24 +59,24 @@ public final class EFunctionRef extends AExpression implements ILambda {
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
if (expected == null) {
|
if (expected == null) {
|
||||||
ref = null;
|
ref = null;
|
||||||
actual = locals.getDefinition().getType("String");
|
actual = String.class;
|
||||||
defPointer = "S" + type + "." + call + ",0";
|
defPointer = "S" + type + "." + call + ",0";
|
||||||
} else {
|
} else {
|
||||||
defPointer = null;
|
defPointer = null;
|
||||||
try {
|
try {
|
||||||
if ("this".equals(type)) {
|
if ("this".equals(type)) {
|
||||||
// user's own function
|
// user's own function
|
||||||
Method interfaceMethod = expected.struct.getFunctionalMethod();
|
Method interfaceMethod = locals.getDefinition().ClassToType(expected).struct.getFunctionalMethod();
|
||||||
if (interfaceMethod == null) {
|
if (interfaceMethod == null) {
|
||||||
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
||||||
"to [" + expected.name + "], not a functional interface");
|
"to [" + Definition.ClassToName(expected) + "], not a functional interface");
|
||||||
}
|
}
|
||||||
Method delegateMethod = locals.getMethod(new MethodKey(call, interfaceMethod.arguments.size()));
|
Method delegateMethod = locals.getMethod(new MethodKey(call, interfaceMethod.arguments.size()));
|
||||||
if (delegateMethod == null) {
|
if (delegateMethod == null) {
|
||||||
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
||||||
"to [" + expected.name + "], function not found");
|
"to [" + Definition.ClassToName(expected) + "], function not found");
|
||||||
}
|
}
|
||||||
ref = new FunctionRef(expected, interfaceMethod, delegateMethod, 0);
|
ref = new FunctionRef(locals.getDefinition().ClassToType(expected), interfaceMethod, delegateMethod, 0);
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -91,7 +91,7 @@ public final class EFunctionRef extends AExpression implements ILambda {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// whitelist lookup
|
// whitelist lookup
|
||||||
ref = new FunctionRef(locals.getDefinition(), expected, type, call, 0);
|
ref = new FunctionRef(locals.getDefinition(), locals.getDefinition().ClassToType(expected), type, call, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
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;
|
||||||
|
@ -55,17 +54,17 @@ public final class EInstanceof extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
final Type type;
|
Class<?> clazz;
|
||||||
|
|
||||||
// ensure the specified type is part of the definition
|
// ensure the specified type is part of the definition
|
||||||
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 + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// map to wrapped type for primitive types
|
// map to wrapped type for primitive types
|
||||||
resolvedType = type.clazz.isPrimitive() ? locals.getDefinition().getBoxedType(type).clazz : type.clazz;
|
resolvedType = clazz.isPrimitive() ? Definition.getBoxedType(clazz) : Definition.defClassToObjectClass(clazz);
|
||||||
|
|
||||||
// analyze and cast the expression
|
// analyze and cast the expression
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
|
@ -73,11 +72,12 @@ public final class EInstanceof extends AExpression {
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
|
||||||
// record if the expression returns a primitive
|
// record if the expression returns a primitive
|
||||||
primitiveExpression = expression.actual.clazz.isPrimitive();
|
primitiveExpression = expression.actual.isPrimitive();
|
||||||
// map to wrapped type for primitive types
|
// map to wrapped type for primitive types
|
||||||
expressionType = expression.actual.clazz.isPrimitive() ? locals.getDefinition().getBoxedType(expression.actual).clazz : type.clazz;
|
expressionType = expression.actual.isPrimitive() ?
|
||||||
|
Definition.getBoxedType(expression.actual) : Definition.defClassToObjectClass(clazz);
|
||||||
|
|
||||||
actual = locals.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,7 +87,7 @@ public final class EInstanceof extends AExpression {
|
||||||
// run the expression anyway (who knows what it does)
|
// run the expression anyway (who knows what it does)
|
||||||
expression.write(writer, globals);
|
expression.write(writer, globals);
|
||||||
// discard its result
|
// discard its result
|
||||||
writer.writePop(expression.actual.type.getSize());
|
writer.writePop(MethodWriter.getType(expression.actual).getSize());
|
||||||
// push our result: its a primitive so it cannot be null.
|
// push our result: its a primitive so it cannot be null.
|
||||||
writer.push(resolvedType.isAssignableFrom(expressionType));
|
writer.push(resolvedType.isAssignableFrom(expressionType));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -120,15 +120,15 @@ public final class ELambda extends AExpression implements ILambda {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we know the method statically, infer return type and any unknown/def types
|
// we know the method statically, infer return type and any unknown/def types
|
||||||
interfaceMethod = expected.struct.getFunctionalMethod();
|
interfaceMethod = locals.getDefinition().ClassToType(expected).struct.getFunctionalMethod();
|
||||||
if (interfaceMethod == null) {
|
if (interfaceMethod == null) {
|
||||||
throw createError(new IllegalArgumentException("Cannot pass lambda to [" + expected.name +
|
throw createError(new IllegalArgumentException("Cannot pass lambda to [" + Definition.ClassToName(expected) +
|
||||||
"], not a functional interface"));
|
"], not a functional interface"));
|
||||||
}
|
}
|
||||||
// check arity before we manipulate parameters
|
// check arity before we manipulate parameters
|
||||||
if (interfaceMethod.arguments.size() != paramTypeStrs.size())
|
if (interfaceMethod.arguments.size() != paramTypeStrs.size())
|
||||||
throw new IllegalArgumentException("Incorrect number of parameters for [" + interfaceMethod.name +
|
throw new IllegalArgumentException("Incorrect number of parameters for [" + interfaceMethod.name +
|
||||||
"] in [" + expected.clazz + "]");
|
"] in [" + Definition.ClassToName(expected) + "]");
|
||||||
// for method invocation, its allowed to ignore the return value
|
// for method invocation, its allowed to ignore the return value
|
||||||
if (interfaceMethod.rtn.equals(locals.getDefinition().voidType)) {
|
if (interfaceMethod.rtn.equals(locals.getDefinition().voidType)) {
|
||||||
returnType = locals.getDefinition().DefType;
|
returnType = locals.getDefinition().DefType;
|
||||||
|
@ -178,12 +178,12 @@ public final class ELambda extends AExpression implements ILambda {
|
||||||
// setup method reference to synthetic method
|
// setup method reference to synthetic method
|
||||||
if (expected == null) {
|
if (expected == null) {
|
||||||
ref = null;
|
ref = null;
|
||||||
actual = locals.getDefinition().getType("String");
|
actual = String.class;
|
||||||
defPointer = "Sthis." + name + "," + captures.size();
|
defPointer = "Sthis." + name + "," + captures.size();
|
||||||
} else {
|
} else {
|
||||||
defPointer = null;
|
defPointer = null;
|
||||||
try {
|
try {
|
||||||
ref = new FunctionRef(expected, interfaceMethod, desugared.method, captures.size());
|
ref = new FunctionRef(locals.getDefinition().ClassToType(expected), interfaceMethod, desugared.method, captures.size());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw createError(e);
|
throw createError(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,15 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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.def;
|
||||||
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;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -58,15 +59,15 @@ public final class EListInit extends AExpression {
|
||||||
throw createError(new IllegalArgumentException("Must read from list initializer."));
|
throw createError(new IllegalArgumentException("Must read from list initializer."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().ArrayListType;
|
actual = ArrayList.class;
|
||||||
|
|
||||||
constructor = actual.struct.constructors.get(new MethodKey("<init>", 0));
|
constructor = locals.getDefinition().ClassToType(actual).struct.constructors.get(new MethodKey("<init>", 0));
|
||||||
|
|
||||||
if (constructor == null) {
|
if (constructor == null) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
||||||
method = actual.struct.methods.get(new MethodKey("add", 1));
|
method = locals.getDefinition().ClassToType(actual).struct.methods.get(new MethodKey("add", 1));
|
||||||
|
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -75,7 +76,7 @@ public final class EListInit extends AExpression {
|
||||||
for (int index = 0; index < values.size(); ++index) {
|
for (int index = 0; index < values.size(); ++index) {
|
||||||
AExpression expression = values.get(index);
|
AExpression expression = values.get(index);
|
||||||
|
|
||||||
expression.expected = locals.getDefinition().DefType;
|
expression.expected = def.class;
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
values.set(index, expression.cast(locals));
|
values.set(index, expression.cast(locals));
|
||||||
|
@ -86,7 +87,7 @@ public final class EListInit extends AExpression {
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
writer.newInstance(actual.type);
|
writer.newInstance(MethodWriter.getType(actual));
|
||||||
writer.dup();
|
writer.dup();
|
||||||
writer.invokeConstructor(constructor.owner.type, constructor.method);
|
writer.invokeConstructor(constructor.owner.type, constructor.method);
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,15 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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.def;
|
||||||
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;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -64,15 +65,15 @@ public final class EMapInit extends AExpression {
|
||||||
throw createError(new IllegalArgumentException("Must read from map initializer."));
|
throw createError(new IllegalArgumentException("Must read from map initializer."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().HashMapType;
|
actual = HashMap.class;
|
||||||
|
|
||||||
constructor = actual.struct.constructors.get(new MethodKey("<init>", 0));
|
constructor = locals.getDefinition().ClassToType(actual).struct.constructors.get(new MethodKey("<init>", 0));
|
||||||
|
|
||||||
if (constructor == null) {
|
if (constructor == null) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
||||||
method = actual.struct.methods.get(new MethodKey("put", 2));
|
method = locals.getDefinition().ClassToType(actual).struct.methods.get(new MethodKey("put", 2));
|
||||||
|
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
|
@ -85,7 +86,7 @@ public final class EMapInit extends AExpression {
|
||||||
for (int index = 0; index < keys.size(); ++index) {
|
for (int index = 0; index < keys.size(); ++index) {
|
||||||
AExpression expression = keys.get(index);
|
AExpression expression = keys.get(index);
|
||||||
|
|
||||||
expression.expected = locals.getDefinition().DefType;
|
expression.expected = def.class;
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
keys.set(index, expression.cast(locals));
|
keys.set(index, expression.cast(locals));
|
||||||
|
@ -94,7 +95,7 @@ public final class EMapInit extends AExpression {
|
||||||
for (int index = 0; index < values.size(); ++index) {
|
for (int index = 0; index < values.size(); ++index) {
|
||||||
AExpression expression = values.get(index);
|
AExpression expression = values.get(index);
|
||||||
|
|
||||||
expression.expected = locals.getDefinition().DefType;
|
expression.expected = def.class;
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
values.set(index, expression.cast(locals));
|
values.set(index, expression.cast(locals));
|
||||||
|
@ -105,7 +106,7 @@ public final class EMapInit extends AExpression {
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
writer.newInstance(actual.type);
|
writer.newInstance(MethodWriter.getType(actual));
|
||||||
writer.dup();
|
writer.dup();
|
||||||
writer.invokeConstructor(constructor.owner.type, constructor.method);
|
writer.invokeConstructor(constructor.owner.type, constructor.method);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
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;
|
||||||
|
@ -39,6 +38,8 @@ public final class ENewArray extends AExpression {
|
||||||
private final List<AExpression> arguments;
|
private final List<AExpression> arguments;
|
||||||
private final boolean initialize;
|
private final boolean initialize;
|
||||||
|
|
||||||
|
private Class<?> array;
|
||||||
|
|
||||||
public ENewArray(Location location, String type, List<AExpression> arguments, boolean initialize) {
|
public ENewArray(Location location, String type, List<AExpression> arguments, boolean initialize) {
|
||||||
super(location);
|
super(location);
|
||||||
|
|
||||||
|
@ -60,10 +61,10 @@ public final class ENewArray extends AExpression {
|
||||||
throw createError(new IllegalArgumentException("A newly created array must be read from."));
|
throw createError(new IllegalArgumentException("A newly created array must be read from."));
|
||||||
}
|
}
|
||||||
|
|
||||||
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 + "]."));
|
||||||
}
|
}
|
||||||
|
@ -71,13 +72,15 @@ public final class ENewArray extends AExpression {
|
||||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||||
AExpression expression = arguments.get(argument);
|
AExpression expression = arguments.get(argument);
|
||||||
|
|
||||||
expression.expected = initialize ? locals.getDefinition().getType(type.struct, 0) : locals.getDefinition().intType;
|
expression.expected = initialize ? clazz : int.class;
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
arguments.set(argument, expression.cast(locals));
|
arguments.set(argument, expression.cast(locals));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().getType(type.struct, initialize ? 1 : arguments.size());
|
actual = Definition.TypeToClass(locals.getDefinition().getType(
|
||||||
|
locals.getDefinition().ClassToType(clazz).struct, initialize ? 1 : arguments.size()));
|
||||||
|
array = Definition.defClassToObjectClass(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -86,7 +89,7 @@ public final class ENewArray extends AExpression {
|
||||||
|
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
writer.push(arguments.size());
|
writer.push(arguments.size());
|
||||||
writer.newArray(actual.struct.type);
|
writer.newArray(MethodWriter.getType(array.getComponentType()));
|
||||||
|
|
||||||
for (int index = 0; index < arguments.size(); ++index) {
|
for (int index = 0; index < arguments.size(); ++index) {
|
||||||
AExpression argument = arguments.get(index);
|
AExpression argument = arguments.get(index);
|
||||||
|
@ -94,7 +97,7 @@ public final class ENewArray extends AExpression {
|
||||||
writer.dup();
|
writer.dup();
|
||||||
writer.push(index);
|
writer.push(index);
|
||||||
argument.write(writer, globals);
|
argument.write(writer, globals);
|
||||||
writer.arrayStore(actual.struct.type);
|
writer.arrayStore(MethodWriter.getType(array.getComponentType()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (AExpression argument : arguments) {
|
for (AExpression argument : arguments) {
|
||||||
|
@ -102,9 +105,9 @@ public final class ENewArray extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.size() > 1) {
|
if (arguments.size() > 1) {
|
||||||
writer.visitMultiANewArrayInsn(actual.type.getDescriptor(), actual.type.getDimensions());
|
writer.visitMultiANewArrayInsn(MethodWriter.getType(array).getDescriptor(), arguments.size());
|
||||||
} else {
|
} else {
|
||||||
writer.newArray(actual.struct.type);
|
writer.newArray(MethodWriter.getType(array.getComponentType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,15 +58,13 @@ public final class ENewObj extends AExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
final Type type;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
type = locals.getDefinition().getType(this.type);
|
actual = 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 + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
Struct struct = type.struct;
|
Struct struct = locals.getDefinition().ClassToType(actual).struct;
|
||||||
constructor = struct.constructors.get(new Definition.MethodKey("<init>", arguments.size()));
|
constructor = struct.constructors.get(new Definition.MethodKey("<init>", arguments.size()));
|
||||||
|
|
||||||
if (constructor != null) {
|
if (constructor != null) {
|
||||||
|
@ -81,14 +79,13 @@ public final class ENewObj extends AExpression {
|
||||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||||
AExpression expression = arguments.get(argument);
|
AExpression expression = arguments.get(argument);
|
||||||
|
|
||||||
expression.expected = types[argument];
|
expression.expected = Definition.TypeToClass(types[argument]);
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
arguments.set(argument, expression.cast(locals));
|
arguments.set(argument, expression.cast(locals));
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = true;
|
statement = true;
|
||||||
actual = type;
|
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Unknown new call on type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Unknown new call on type [" + struct.name + "]."));
|
||||||
}
|
}
|
||||||
|
@ -98,7 +95,7 @@ public final class ENewObj extends AExpression {
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
writer.newInstance(actual.type);
|
writer.newInstance(MethodWriter.getType(actual));
|
||||||
|
|
||||||
if (read) {
|
if (read) {
|
||||||
writer.dup();
|
writer.dup();
|
||||||
|
|
|
@ -21,14 +21,13 @@ package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a null constant.
|
* Represents a null constant.
|
||||||
*/
|
*/
|
||||||
|
@ -52,13 +51,14 @@ public final class ENull extends AExpression {
|
||||||
isNull = true;
|
isNull = true;
|
||||||
|
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
if (expected.clazz.isPrimitive()) {
|
if (expected.isPrimitive()) {
|
||||||
throw createError(new IllegalArgumentException("Cannot cast null to a primitive type [" + expected.name + "]."));
|
throw createError(new IllegalArgumentException(
|
||||||
|
"Cannot cast null to a primitive type [" + Definition.ClassToName(expected) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = expected;
|
actual = expected;
|
||||||
} else {
|
} else {
|
||||||
actual = locals.getDefinition().ObjectType;
|
actual = Object.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,16 +19,14 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
|
import org.elasticsearch.painless.Locals;
|
||||||
import org.elasticsearch.painless.Location;
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Locals;
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-decimal numeric constant.
|
* Represents a non-decimal numeric constant.
|
||||||
*/
|
*/
|
||||||
|
@ -62,7 +60,7 @@ public final class ENumeric extends AExpression {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
constant = Double.parseDouble(value.substring(0, value.length() - 1));
|
constant = Double.parseDouble(value.substring(0, value.length() - 1));
|
||||||
actual = locals.getDefinition().doubleType;
|
actual = double.class;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
||||||
}
|
}
|
||||||
|
@ -73,34 +71,34 @@ public final class ENumeric extends AExpression {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
||||||
actual = locals.getDefinition().floatType;
|
actual = float.class;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
||||||
}
|
}
|
||||||
} else if (value.endsWith("l") || value.endsWith("L")) {
|
} else if (value.endsWith("l") || value.endsWith("L")) {
|
||||||
try {
|
try {
|
||||||
constant = Long.parseLong(value.substring(0, value.length() - 1), radix);
|
constant = Long.parseLong(value.substring(0, value.length() - 1), radix);
|
||||||
actual = locals.getDefinition().longType;
|
actual = long.class;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
throw createError(new IllegalArgumentException("Invalid long constant [" + value + "]."));
|
throw createError(new IllegalArgumentException("Invalid long constant [" + value + "]."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
Class<?> sort = expected == null ? int.class : expected.clazz;
|
Class<?> sort = expected == null ? int.class : expected;
|
||||||
int integer = Integer.parseInt(value, radix);
|
int integer = Integer.parseInt(value, radix);
|
||||||
|
|
||||||
if (sort == byte.class && integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) {
|
if (sort == byte.class && integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) {
|
||||||
constant = (byte)integer;
|
constant = (byte)integer;
|
||||||
actual = locals.getDefinition().byteType;
|
actual = byte.class;
|
||||||
} else if (sort == char.class && integer >= Character.MIN_VALUE && integer <= Character.MAX_VALUE) {
|
} else if (sort == char.class && integer >= Character.MIN_VALUE && integer <= Character.MAX_VALUE) {
|
||||||
constant = (char)integer;
|
constant = (char)integer;
|
||||||
actual = locals.getDefinition().charType;
|
actual = char.class;
|
||||||
} else if (sort == short.class && integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) {
|
} else if (sort == short.class && integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) {
|
||||||
constant = (short)integer;
|
constant = (short)integer;
|
||||||
actual = locals.getDefinition().shortType;
|
actual = short.class;
|
||||||
} else {
|
} else {
|
||||||
constant = integer;
|
constant = integer;
|
||||||
actual = locals.getDefinition().intType;
|
actual = int.class;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -20,18 +20,16 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Constant;
|
import org.elasticsearch.painless.Constant;
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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.MethodWriter;
|
||||||
|
import org.elasticsearch.painless.WriterConstants;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
import org.elasticsearch.painless.WriterConstants;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a regex constant. All regexes are constants.
|
* Represents a regex constant. All regexes are constants.
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +73,7 @@ public final class ERegex extends AExpression {
|
||||||
|
|
||||||
constant = new Constant(
|
constant = new Constant(
|
||||||
location, locals.getDefinition().PatternType.type, "regexAt$" + location.getOffset(), this::initializeConstant);
|
location, locals.getDefinition().PatternType.type, "regexAt$" + location.getOffset(), this::initializeConstant);
|
||||||
actual = locals.getDefinition().PatternType;
|
actual = Pattern.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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.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;
|
||||||
|
@ -48,7 +49,7 @@ public final class EStatic extends AExpression {
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
try {
|
try {
|
||||||
actual = locals.getDefinition().getType(type);
|
actual = Definition.TypeToClass(locals.getDefinition().getType(type));
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
throw createError(new IllegalArgumentException("Not a type [" + type + "]."));
|
throw createError(new IllegalArgumentException("Not a type [" + type + "]."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -50,7 +49,7 @@ public final class EString extends AExpression {
|
||||||
throw createError(new IllegalArgumentException("Must read from constant [" + constant + "]."));
|
throw createError(new IllegalArgumentException("Must read from constant [" + constant + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().StringType;
|
actual = String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,22 +19,22 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.AnalyzerCaster;
|
import org.elasticsearch.painless.AnalyzerCaster;
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
import org.elasticsearch.painless.Operation;
|
import org.elasticsearch.painless.Definition;
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
import org.elasticsearch.painless.Operation;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a unary math expression.
|
* Represents a unary math expression.
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,7 @@ public final class EUnary extends AExpression {
|
||||||
private final Operation operation;
|
private final Operation operation;
|
||||||
private AExpression child;
|
private AExpression child;
|
||||||
|
|
||||||
private Type promote;
|
private Class<?> promote;
|
||||||
private boolean originallyExplicit = false; // record whether there was originally an explicit cast
|
private boolean originallyExplicit = false; // record whether there was originally an explicit cast
|
||||||
|
|
||||||
public EUnary(Location location, Operation operation, AExpression child) {
|
public EUnary(Location location, Operation operation, AExpression child) {
|
||||||
|
@ -76,7 +76,7 @@ public final class EUnary extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
void analyzeNot(Locals variables) {
|
void analyzeNot(Locals variables) {
|
||||||
child.expected = variables.getDefinition().booleanType;
|
child.expected = boolean.class;
|
||||||
child.analyze(variables);
|
child.analyze(variables);
|
||||||
child = child.cast(variables);
|
child = child.cast(variables);
|
||||||
|
|
||||||
|
@ -84,34 +84,32 @@ public final class EUnary extends AExpression {
|
||||||
constant = !(boolean)child.constant;
|
constant = !(boolean)child.constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = variables.getDefinition().booleanType;
|
actual = boolean.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
void analyzeBWNot(Locals variables) {
|
void analyzeBWNot(Locals variables) {
|
||||||
child.analyze(variables);
|
child.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), false));
|
promote = AnalyzerCaster.promoteNumeric(child.actual, false);
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply not [~] to type [" + child.actual.name + "]."));
|
throw createError(new ClassCastException("Cannot apply not [~] to type [" + Definition.ClassToName(child.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
child.expected = promote;
|
child.expected = promote;
|
||||||
child = child.cast(variables);
|
child = child.cast(variables);
|
||||||
|
|
||||||
if (child.constant != null) {
|
if (child.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = ~(int)child.constant;
|
constant = ~(int)child.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = ~(long)child.constant;
|
constant = ~(long)child.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promote.dynamic && expected != null) {
|
if (promote == def.class && expected != null) {
|
||||||
actual = expected;
|
actual = expected;
|
||||||
} else {
|
} else {
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
@ -121,32 +119,30 @@ public final class EUnary extends AExpression {
|
||||||
void analyzerAdd(Locals variables) {
|
void analyzerAdd(Locals variables) {
|
||||||
child.analyze(variables);
|
child.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), true));
|
promote = AnalyzerCaster.promoteNumeric(child.actual, true);
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply positive [+] to type [" + child.actual.name + "]."));
|
throw createError(new ClassCastException("Cannot apply positive [+] to type [" + Definition.ClassToName(child.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
child.expected = promote;
|
child.expected = promote;
|
||||||
child = child.cast(variables);
|
child = child.cast(variables);
|
||||||
|
|
||||||
if (child.constant != null) {
|
if (child.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = +(int)child.constant;
|
constant = +(int)child.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = +(long)child.constant;
|
constant = +(long)child.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = +(float)child.constant;
|
constant = +(float)child.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = +(double)child.constant;
|
constant = +(double)child.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promote.dynamic && expected != null) {
|
if (promote == def.class && expected != null) {
|
||||||
actual = expected;
|
actual = expected;
|
||||||
} else {
|
} else {
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
@ -156,32 +152,30 @@ public final class EUnary extends AExpression {
|
||||||
void analyzerSub(Locals variables) {
|
void analyzerSub(Locals variables) {
|
||||||
child.analyze(variables);
|
child.analyze(variables);
|
||||||
|
|
||||||
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), true));
|
promote = AnalyzerCaster.promoteNumeric(child.actual, true);
|
||||||
|
|
||||||
if (promote == null) {
|
if (promote == null) {
|
||||||
throw createError(new ClassCastException("Cannot apply negative [-] to type [" + child.actual.name + "]."));
|
throw createError(new ClassCastException("Cannot apply negative [-] to type [" + Definition.ClassToName(child.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
child.expected = promote;
|
child.expected = promote;
|
||||||
child = child.cast(variables);
|
child = child.cast(variables);
|
||||||
|
|
||||||
if (child.constant != null) {
|
if (child.constant != null) {
|
||||||
Class<?> sort = promote.clazz;
|
if (promote == int.class) {
|
||||||
|
|
||||||
if (sort == int.class) {
|
|
||||||
constant = -(int)child.constant;
|
constant = -(int)child.constant;
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
constant = -(long)child.constant;
|
constant = -(long)child.constant;
|
||||||
} else if (sort == float.class) {
|
} else if (promote == float.class) {
|
||||||
constant = -(float)child.constant;
|
constant = -(float)child.constant;
|
||||||
} else if (sort == double.class) {
|
} else if (promote == double.class) {
|
||||||
constant = -(double)child.constant;
|
constant = -(double)child.constant;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promote.dynamic && expected != null) {
|
if (promote == def.class && expected != null) {
|
||||||
actual = expected;
|
actual = expected;
|
||||||
} else {
|
} else {
|
||||||
actual = promote;
|
actual = promote;
|
||||||
|
@ -205,7 +199,6 @@ public final class EUnary extends AExpression {
|
||||||
writer.push(true);
|
writer.push(true);
|
||||||
writer.mark(end);
|
writer.mark(end);
|
||||||
} else {
|
} else {
|
||||||
Class<?> sort = promote.clazz;
|
|
||||||
child.write(writer, globals);
|
child.write(writer, globals);
|
||||||
|
|
||||||
// Def calls adopt the wanted return value. If there was a narrowing cast,
|
// Def calls adopt the wanted return value. If there was a narrowing cast,
|
||||||
|
@ -216,31 +209,34 @@ public final class EUnary extends AExpression {
|
||||||
defFlags |= DefBootstrap.OPERATOR_EXPLICIT_CAST;
|
defFlags |= DefBootstrap.OPERATOR_EXPLICIT_CAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type actualType = MethodWriter.getType(actual);
|
||||||
|
Type childType = MethodWriter.getType(child.actual);
|
||||||
|
|
||||||
if (operation == Operation.BWNOT) {
|
if (operation == Operation.BWNOT) {
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actual.type, child.actual.type);
|
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actualType, childType);
|
||||||
writer.invokeDefCall("not", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
writer.invokeDefCall("not", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
||||||
} else {
|
} else {
|
||||||
if (sort == int.class) {
|
if (promote == int.class) {
|
||||||
writer.push(-1);
|
writer.push(-1);
|
||||||
} else if (sort == long.class) {
|
} else if (promote == long.class) {
|
||||||
writer.push(-1L);
|
writer.push(-1L);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.math(MethodWriter.XOR, actual.type);
|
writer.math(MethodWriter.XOR, actualType);
|
||||||
}
|
}
|
||||||
} else if (operation == Operation.SUB) {
|
} else if (operation == Operation.SUB) {
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actual.type, child.actual.type);
|
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actualType, childType);
|
||||||
writer.invokeDefCall("neg", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
writer.invokeDefCall("neg", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
||||||
} else {
|
} else {
|
||||||
writer.math(MethodWriter.NEG, actual.type);
|
writer.math(MethodWriter.NEG, actualType);
|
||||||
}
|
}
|
||||||
} else if (operation == Operation.ADD) {
|
} else if (operation == Operation.ADD) {
|
||||||
if (promote.dynamic) {
|
if (promote == def.class) {
|
||||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actual.type, child.actual.type);
|
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(actualType, childType);
|
||||||
writer.invokeDefCall("plus", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
writer.invokeDefCall("plus", descriptor, DefBootstrap.UNARY_OPERATOR, defFlags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
import org.elasticsearch.painless.Definition;
|
||||||
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;
|
||||||
|
@ -58,12 +58,12 @@ 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 = variable.type;
|
actual = Definition.TypeToClass(variable.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.visitVarInsn(actual.type.getOpcode(Opcodes.ILOAD), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(actual).getOpcode(Opcodes.ILOAD), variable.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -77,7 +77,7 @@ public final class EVariable extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalArgumentException("Illegal tree structure.");
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,12 +88,12 @@ public final class EVariable extends AStoreable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void load(MethodWriter writer, Globals globals) {
|
void load(MethodWriter writer, Globals globals) {
|
||||||
writer.visitVarInsn(actual.type.getOpcode(Opcodes.ILOAD), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(actual).getOpcode(Opcodes.ILOAD), variable.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void store(MethodWriter writer, Globals globals) {
|
void store(MethodWriter writer, Globals globals) {
|
||||||
writer.visitVarInsn(actual.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
writer.visitVarInsn(MethodWriter.getType(actual).getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
import org.elasticsearch.painless.Definition;
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
|
@ -57,16 +58,17 @@ public final class PBrace extends AStoreable {
|
||||||
prefix.expected = prefix.actual;
|
prefix.expected = prefix.actual;
|
||||||
prefix = prefix.cast(locals);
|
prefix = prefix.cast(locals);
|
||||||
|
|
||||||
if (prefix.actual.dimensions > 0) {
|
if (prefix.actual.isArray()) {
|
||||||
sub = new PSubBrace(location, prefix.actual, index);
|
sub = new PSubBrace(location, prefix.actual, index);
|
||||||
} else if (prefix.actual.dynamic) {
|
} else if (prefix.actual == def.class) {
|
||||||
sub = new PSubDefArray(location, index);
|
sub = new PSubDefArray(location, index);
|
||||||
} else if (Map.class.isAssignableFrom(prefix.actual.clazz)) {
|
} else if (Map.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubMapShortcut(location, prefix.actual.struct, index);
|
sub = new PSubMapShortcut(location, locals.getDefinition().ClassToType(prefix.actual).struct, index);
|
||||||
} else if (List.class.isAssignableFrom(prefix.actual.clazz)) {
|
} else if (List.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubListShortcut(location, prefix.actual.struct, index);
|
sub = new PSubListShortcut(location, locals.getDefinition().ClassToType(prefix.actual).struct, index);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal array access on type [" + prefix.actual.name + "]."));
|
throw createError(
|
||||||
|
new IllegalArgumentException("Illegal array access on type [" + Definition.ClassToName(prefix.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub.write = write;
|
sub.write = write;
|
||||||
|
@ -89,7 +91,7 @@ public final class PBrace extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
sub.updateActual(actual);
|
sub.updateActual(actual);
|
||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.elasticsearch.painless.Definition;
|
||||||
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.Struct;
|
import org.elasticsearch.painless.Definition.Struct;
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
|
@ -66,14 +67,14 @@ public final class PCallInvoke extends AExpression {
|
||||||
prefix.expected = prefix.actual;
|
prefix.expected = prefix.actual;
|
||||||
prefix = prefix.cast(locals);
|
prefix = prefix.cast(locals);
|
||||||
|
|
||||||
if (prefix.actual.dimensions > 0) {
|
if (prefix.actual.isArray()) {
|
||||||
throw createError(new IllegalArgumentException("Illegal call [" + name + "] on array type."));
|
throw createError(new IllegalArgumentException("Illegal call [" + name + "] on array type."));
|
||||||
}
|
}
|
||||||
|
|
||||||
Struct struct = prefix.actual.struct;
|
Struct struct = locals.getDefinition().ClassToType(prefix.actual).struct;
|
||||||
|
|
||||||
if (prefix.actual.clazz.isPrimitive()) {
|
if (prefix.actual.isPrimitive()) {
|
||||||
struct = locals.getDefinition().getBoxedType(prefix.actual).struct;
|
struct = locals.getDefinition().ClassToType(Definition.getBoxedType(prefix.actual)).struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodKey methodKey = new MethodKey(name, arguments.size());
|
MethodKey methodKey = new MethodKey(name, arguments.size());
|
||||||
|
@ -81,7 +82,7 @@ public final class PCallInvoke extends AExpression {
|
||||||
|
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
sub = new PSubCallInvoke(location, method, prefix.actual, arguments);
|
sub = new PSubCallInvoke(location, method, prefix.actual, arguments);
|
||||||
} else if (prefix.actual.dynamic) {
|
} else if (prefix.actual == def.class) {
|
||||||
sub = new PSubDefCall(location, name, arguments);
|
sub = new PSubDefCall(location, name, arguments);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException(
|
throw createError(new IllegalArgumentException(
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Field;
|
import org.elasticsearch.painless.Definition.Field;
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
import org.elasticsearch.painless.Definition.Struct;
|
import org.elasticsearch.painless.Definition.Struct;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
|
@ -62,12 +62,12 @@ public final class PField extends AStoreable {
|
||||||
prefix.expected = prefix.actual;
|
prefix.expected = prefix.actual;
|
||||||
prefix = prefix.cast(locals);
|
prefix = prefix.cast(locals);
|
||||||
|
|
||||||
if (prefix.actual.dimensions > 0) {
|
if (prefix.actual.isArray()) {
|
||||||
sub = new PSubArrayLength(location, prefix.actual.name, value);
|
sub = new PSubArrayLength(location, Definition.ClassToName(prefix.actual), value);
|
||||||
} else if (prefix.actual.dynamic) {
|
} else if (prefix.actual == def.class) {
|
||||||
sub = new PSubDefField(location, value);
|
sub = new PSubDefField(location, value);
|
||||||
} else {
|
} else {
|
||||||
Struct struct = prefix.actual.struct;
|
Struct struct = locals.getDefinition().ClassToType(prefix.actual).struct;
|
||||||
Field field = prefix instanceof EStatic ? struct.staticMembers.get(value) : struct.members.get(value);
|
Field field = prefix instanceof EStatic ? struct.staticMembers.get(value) : struct.members.get(value);
|
||||||
|
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
|
@ -85,16 +85,16 @@ public final class PField extends AStoreable {
|
||||||
new Definition.MethodKey("set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 1));
|
new Definition.MethodKey("set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 1));
|
||||||
|
|
||||||
if (getter != null || setter != null) {
|
if (getter != null || setter != null) {
|
||||||
sub = new PSubShortcut(location, value, prefix.actual.name, getter, setter);
|
sub = new PSubShortcut(location, value, Definition.ClassToName(prefix.actual), getter, setter);
|
||||||
} else {
|
} else {
|
||||||
EConstant index = new EConstant(location, value);
|
EConstant index = new EConstant(location, value);
|
||||||
index.analyze(locals);
|
index.analyze(locals);
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(prefix.actual.clazz)) {
|
if (Map.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubMapShortcut(location, struct, index);
|
sub = new PSubMapShortcut(location, struct, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (List.class.isAssignableFrom(prefix.actual.clazz)) {
|
if (List.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubListShortcut(location, struct, index);
|
sub = new PSubListShortcut(location, struct, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,8 @@ public final class PField extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sub == null) {
|
if (sub == null) {
|
||||||
throw createError(new IllegalArgumentException("Unknown field [" + value + "] for type [" + prefix.actual.name + "]."));
|
throw createError(new IllegalArgumentException(
|
||||||
|
"Unknown field [" + value + "] for type [" + Definition.ClassToName(prefix.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nullSafe) {
|
if (nullSafe) {
|
||||||
|
@ -129,7 +130,7 @@ public final class PField extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
sub.updateActual(actual);
|
sub.updateActual(actual);
|
||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -56,7 +54,7 @@ final class PSubArrayLength extends AStoreable {
|
||||||
throw createError(new IllegalArgumentException("Cannot write to read-only field [length] for an array."));
|
throw createError(new IllegalArgumentException("Cannot write to read-only field [length] for an array."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = locals.getDefinition().intType;
|
actual = int.class;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Field [" + value + "] does not exist for type [" + type + "]."));
|
throw createError(new IllegalArgumentException("Field [" + value + "] does not exist for type [" + type + "]."));
|
||||||
}
|
}
|
||||||
|
@ -79,7 +77,7 @@ final class PSubArrayLength extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalStateException("Illegal tree structure.");
|
throw new IllegalStateException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -34,13 +32,13 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
final class PSubBrace extends AStoreable {
|
final class PSubBrace extends AStoreable {
|
||||||
|
|
||||||
private final Type type;
|
private final Class<?> clazz;
|
||||||
private AExpression index;
|
private AExpression index;
|
||||||
|
|
||||||
PSubBrace(Location location, Type type, AExpression index) {
|
PSubBrace(Location location, Class<?> clazz, AExpression index) {
|
||||||
super(location);
|
super(location);
|
||||||
|
|
||||||
this.type = Objects.requireNonNull(type);
|
this.clazz = Objects.requireNonNull(clazz);
|
||||||
this.index = Objects.requireNonNull(index);
|
this.index = Objects.requireNonNull(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +49,11 @@ final class PSubBrace extends AStoreable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
index.expected = locals.getDefinition().intType;
|
index.expected = int.class;
|
||||||
index.analyze(locals);
|
index.analyze(locals);
|
||||||
index = index.cast(locals);
|
index = index.cast(locals);
|
||||||
|
|
||||||
actual = locals.getDefinition().getType(type.struct, type.dimensions - 1);
|
actual = clazz.getComponentType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,7 +73,7 @@ final class PSubBrace extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,13 +86,13 @@ final class PSubBrace extends AStoreable {
|
||||||
@Override
|
@Override
|
||||||
void load(MethodWriter writer, Globals globals) {
|
void load(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
writer.arrayLoad(actual.type);
|
writer.arrayLoad(MethodWriter.getType(actual));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void store(MethodWriter writer, Globals globals) {
|
void store(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
writer.arrayStore(actual.type);
|
writer.arrayStore(MethodWriter.getType(actual));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
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;
|
||||||
|
@ -36,10 +36,10 @@ import java.util.Set;
|
||||||
final class PSubCallInvoke extends AExpression {
|
final class PSubCallInvoke extends AExpression {
|
||||||
|
|
||||||
private final Method method;
|
private final Method method;
|
||||||
private final Type box;
|
private final Class<?> box;
|
||||||
private final List<AExpression> arguments;
|
private final List<AExpression> arguments;
|
||||||
|
|
||||||
PSubCallInvoke(Location location, Method method, Type box, List<AExpression> arguments) {
|
PSubCallInvoke(Location location, Method method, Class<?> box, List<AExpression> arguments) {
|
||||||
super(location);
|
super(location);
|
||||||
|
|
||||||
this.method = Objects.requireNonNull(method);
|
this.method = Objects.requireNonNull(method);
|
||||||
|
@ -57,22 +57,22 @@ final class PSubCallInvoke extends AExpression {
|
||||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||||
AExpression expression = arguments.get(argument);
|
AExpression expression = arguments.get(argument);
|
||||||
|
|
||||||
expression.expected = method.arguments.get(argument);
|
expression.expected = Definition.TypeToClass(method.arguments.get(argument));
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
arguments.set(argument, expression.cast(locals));
|
arguments.set(argument, expression.cast(locals));
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = true;
|
statement = true;
|
||||||
actual = method.rtn;
|
actual = Definition.TypeToClass(method.rtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void write(MethodWriter writer, Globals globals) {
|
void write(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
if (box.clazz.isPrimitive()) {
|
if (box.isPrimitive()) {
|
||||||
writer.box(box.type);
|
writer.box(MethodWriter.getType(box));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AExpression argument : arguments) {
|
for (AExpression argument : arguments) {
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -53,7 +53,7 @@ final class PSubDefArray extends AStoreable {
|
||||||
index.expected = index.actual;
|
index.expected = index.actual;
|
||||||
index = index.cast(locals);
|
index = index.cast(locals);
|
||||||
|
|
||||||
actual = expected == null || explicit ? locals.getDefinition().DefType : expected;
|
actual = expected == null || explicit ? def.class : expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,7 +73,7 @@ final class PSubDefArray extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ final class PSubDefArray extends AStoreable {
|
||||||
// Current stack: def
|
// Current stack: def
|
||||||
writer.dup(); // def, def
|
writer.dup(); // def, def
|
||||||
index.write(writer, globals); // def, def, unnormalized_index
|
index.write(writer, globals); // def, def, unnormalized_index
|
||||||
org.objectweb.asm.Type methodType = org.objectweb.asm.Type.getMethodType(
|
Type methodType = Type.getMethodType(
|
||||||
index.actual.type, org.objectweb.asm.Type.getType(Object.class), index.actual.type);
|
MethodWriter.getType(index.actual), Type.getType(Object.class), MethodWriter.getType(index.actual));
|
||||||
writer.invokeDefCall("normalizeIndex", methodType, DefBootstrap.INDEX_NORMALIZE); // def, normalized_index
|
writer.invokeDefCall("normalizeIndex", methodType, DefBootstrap.INDEX_NORMALIZE); // def, normalized_index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +91,8 @@ final class PSubDefArray extends AStoreable {
|
||||||
void load(MethodWriter writer, Globals globals) {
|
void load(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
org.objectweb.asm.Type methodType =
|
Type methodType =
|
||||||
org.objectweb.asm.Type.getMethodType(actual.type, org.objectweb.asm.Type.getType(Object.class), index.actual.type);
|
Type.getMethodType(MethodWriter.getType(actual), Type.getType(Object.class), MethodWriter.getType(index.actual));
|
||||||
writer.invokeDefCall("arrayLoad", methodType, DefBootstrap.ARRAY_LOAD);
|
writer.invokeDefCall("arrayLoad", methodType, DefBootstrap.ARRAY_LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +100,9 @@ final class PSubDefArray extends AStoreable {
|
||||||
void store(MethodWriter writer, Globals globals) {
|
void store(MethodWriter writer, Globals globals) {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
org.objectweb.asm.Type methodType =
|
Type methodType =
|
||||||
org.objectweb.asm.Type.getMethodType(
|
Type.getMethodType(
|
||||||
org.objectweb.asm.Type.getType(void.class), org.objectweb.asm.Type.getType(Object.class), index.actual.type, actual.type);
|
Type.getType(void.class), Type.getType(Object.class), MethodWriter.getType(index.actual), MethodWriter.getType(actual));
|
||||||
writer.invokeDefCall("arrayStore", methodType, DefBootstrap.ARRAY_STORE);
|
writer.invokeDefCall("arrayStore", methodType, DefBootstrap.ARRAY_STORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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;
|
||||||
|
@ -75,7 +77,7 @@ final class PSubDefCall extends AExpression {
|
||||||
totalCaptures += lambda.getCaptureCount();
|
totalCaptures += lambda.getCaptureCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression.actual.clazz == void.class) {
|
if (expression.actual == void.class) {
|
||||||
throw createError(new IllegalArgumentException("Argument(s) cannot be of [void] type when calling method [" + name + "]."));
|
throw createError(new IllegalArgumentException("Argument(s) cannot be of [void] type when calling method [" + name + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ final class PSubDefCall extends AExpression {
|
||||||
arguments.set(argument, expression.cast(locals));
|
arguments.set(argument, expression.cast(locals));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = expected == null || explicit ? locals.getDefinition().DefType : expected;
|
actual = expected == null || explicit ? def.class : expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,7 +99,7 @@ final class PSubDefCall extends AExpression {
|
||||||
|
|
||||||
// append each argument
|
// append each argument
|
||||||
for (AExpression argument : arguments) {
|
for (AExpression argument : arguments) {
|
||||||
parameterTypes.add(argument.actual.type);
|
parameterTypes.add(MethodWriter.getType(argument.actual));
|
||||||
|
|
||||||
if (argument instanceof ILambda) {
|
if (argument instanceof ILambda) {
|
||||||
ILambda lambda = (ILambda) argument;
|
ILambda lambda = (ILambda) argument;
|
||||||
|
@ -108,7 +110,7 @@ final class PSubDefCall extends AExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create method type from return value and arguments
|
// create method type from return value and arguments
|
||||||
Type methodType = Type.getMethodType(actual.type, parameterTypes.toArray(new Type[0]));
|
Type methodType = Type.getMethodType(MethodWriter.getType(actual), parameterTypes.toArray(new Type[0]));
|
||||||
|
|
||||||
List<Object> args = new ArrayList<>();
|
List<Object> args = new ArrayList<>();
|
||||||
args.add(recipe.toString());
|
args.add(recipe.toString());
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.DefBootstrap;
|
import org.elasticsearch.painless.DefBootstrap;
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
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,7 +49,7 @@ final class PSubDefField extends AStoreable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
actual = expected == null || explicit ? locals.getDefinition().DefType : expected;
|
actual = expected == null || explicit ? def.class : expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -57,7 +57,7 @@ final class PSubDefField extends AStoreable {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
org.objectweb.asm.Type methodType =
|
org.objectweb.asm.Type methodType =
|
||||||
org.objectweb.asm.Type.getMethodType(actual.type, org.objectweb.asm.Type.getType(Object.class));
|
org.objectweb.asm.Type.getMethodType(MethodWriter.getType(actual), org.objectweb.asm.Type.getType(Object.class));
|
||||||
writer.invokeDefCall(value, methodType, DefBootstrap.LOAD);
|
writer.invokeDefCall(value, methodType, DefBootstrap.LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ final class PSubDefField extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ final class PSubDefField extends AStoreable {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
org.objectweb.asm.Type methodType =
|
org.objectweb.asm.Type methodType =
|
||||||
org.objectweb.asm.Type.getMethodType(actual.type, org.objectweb.asm.Type.getType(Object.class));
|
org.objectweb.asm.Type.getMethodType(MethodWriter.getType(actual), org.objectweb.asm.Type.getType(Object.class));
|
||||||
writer.invokeDefCall(value, methodType, DefBootstrap.LOAD);
|
writer.invokeDefCall(value, methodType, DefBootstrap.LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ final class PSubDefField extends AStoreable {
|
||||||
writer.writeDebugInfo(location);
|
writer.writeDebugInfo(location);
|
||||||
|
|
||||||
org.objectweb.asm.Type methodType = org.objectweb.asm.Type.getMethodType(
|
org.objectweb.asm.Type methodType = org.objectweb.asm.Type.getMethodType(
|
||||||
org.objectweb.asm.Type.getType(void.class), org.objectweb.asm.Type.getType(Object.class), actual.type);
|
org.objectweb.asm.Type.getType(void.class), org.objectweb.asm.Type.getType(Object.class), MethodWriter.getType(actual));
|
||||||
writer.invokeDefCall(value, methodType, DefBootstrap.STORE);
|
writer.invokeDefCall(value, methodType, DefBootstrap.STORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Field;
|
import org.elasticsearch.painless.Definition.Field;
|
||||||
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;
|
||||||
|
@ -55,7 +55,7 @@ final class PSubField extends AStoreable {
|
||||||
"Cannot write to read-only field [" + field.name + "] for type [" + field.type.name + "]."));
|
"Cannot write to read-only field [" + field.name + "] for type [" + field.type.name + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = field.type;
|
actual = Definition.TypeToClass(field.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,7 +80,7 @@ final class PSubField extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalArgumentException("Illegal tree structure.");
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.painless.node;
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
import org.elasticsearch.painless.Definition.Struct;
|
import org.elasticsearch.painless.Definition.Struct;
|
||||||
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;
|
||||||
|
@ -75,11 +74,11 @@ final class PSubListShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((read || write) && (!read || getter != null) && (!write || setter != null)) {
|
if ((read || write) && (!read || getter != null) && (!write || setter != null)) {
|
||||||
index.expected = locals.getDefinition().intType;
|
index.expected = int.class;
|
||||||
index.analyze(locals);
|
index.analyze(locals);
|
||||||
index = index.cast(locals);
|
index = index.cast(locals);
|
||||||
|
|
||||||
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
actual = setter != null ? Definition.TypeToClass(setter.arguments.get(1)) : Definition.TypeToClass(getter.rtn);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal list shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal list shortcut for type [" + struct.name + "]."));
|
||||||
}
|
}
|
||||||
|
@ -102,7 +101,7 @@ final class PSubListShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalArgumentException("Illegal tree structure.");
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,16 @@
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Struct;
|
|
||||||
import org.elasticsearch.painless.Definition.Type;
|
|
||||||
import org.elasticsearch.painless.Globals;
|
|
||||||
import org.elasticsearch.painless.Location;
|
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
|
import org.elasticsearch.painless.Definition.Struct;
|
||||||
|
import org.elasticsearch.painless.Globals;
|
||||||
|
import org.elasticsearch.painless.Locals;
|
||||||
|
import org.elasticsearch.painless.Location;
|
||||||
|
import org.elasticsearch.painless.MethodWriter;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Locals;
|
|
||||||
import org.elasticsearch.painless.MethodWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a map load/store shortcut. (Internal only.)
|
* Represents a map load/store shortcut. (Internal only.)
|
||||||
*/
|
*/
|
||||||
|
@ -74,11 +72,12 @@ final class PSubMapShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((read || write) && (!read || getter != null) && (!write || setter != null)) {
|
if ((read || write) && (!read || getter != null) && (!write || setter != null)) {
|
||||||
index.expected = setter != null ? setter.arguments.get(0) : getter.arguments.get(0);
|
index.expected = setter != null ?
|
||||||
|
Definition.TypeToClass(setter.arguments.get(0)) : Definition.TypeToClass(getter.arguments.get(0));
|
||||||
index.analyze(locals);
|
index.analyze(locals);
|
||||||
index = index.cast(locals);
|
index = index.cast(locals);
|
||||||
|
|
||||||
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
actual = setter != null ? Definition.TypeToClass(setter.arguments.get(1)) : Definition.TypeToClass(getter.rtn);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal map shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal map shortcut for type [" + struct.name + "]."));
|
||||||
}
|
}
|
||||||
|
@ -108,7 +107,7 @@ final class PSubMapShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalArgumentException("Illegal tree structure.");
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class PSubNullSafeCallInvoke extends AExpression {
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
guarded.analyze(locals);
|
guarded.analyze(locals);
|
||||||
actual = guarded.actual;
|
actual = guarded.actual;
|
||||||
if (actual.clazz.isPrimitive()) {
|
if (actual.isPrimitive()) {
|
||||||
throw new IllegalArgumentException("Result of null safe operator must be nullable");
|
throw new IllegalArgumentException("Result of null safe operator must be nullable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -52,7 +51,7 @@ public class PSubNullSafeField extends AStoreable {
|
||||||
guarded.read = read;
|
guarded.read = read;
|
||||||
guarded.analyze(locals);
|
guarded.analyze(locals);
|
||||||
actual = guarded.actual;
|
actual = guarded.actual;
|
||||||
if (actual.clazz.isPrimitive()) {
|
if (actual.isPrimitive()) {
|
||||||
throw new IllegalArgumentException("Result of null safe operator must be nullable");
|
throw new IllegalArgumentException("Result of null safe operator must be nullable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,7 @@ public class PSubNullSafeField extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
guarded.updateActual(actual);
|
guarded.updateActual(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Method;
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
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;
|
||||||
|
@ -69,7 +69,7 @@ final class PSubShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((getter != null || setter != null) && (!read || getter != null) && (!write || setter != null)) {
|
if ((getter != null || setter != null) && (!read || getter != null) && (!write || setter != null)) {
|
||||||
actual = setter != null ? setter.arguments.get(0) : getter.rtn;
|
actual = setter != null ? Definition.TypeToClass(setter.arguments.get(0)) : Definition.TypeToClass(getter.rtn);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal shortcut on field [" + value + "] for type [" + type + "]."));
|
throw createError(new IllegalArgumentException("Illegal shortcut on field [" + value + "] for type [" + type + "]."));
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ final class PSubShortcut extends AStoreable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateActual(Type actual) {
|
void updateActual(Class<?> actual) {
|
||||||
throw new IllegalArgumentException("Illegal tree structure.");
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -69,7 +70,7 @@ public final class SDeclaration extends AStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.expected = type;
|
expression.expected = Definition.TypeToClass(type);
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -73,7 +72,7 @@ public final class SDo extends AStatement {
|
||||||
throw createError(new IllegalArgumentException("Extraneous do while loop."));
|
throw createError(new IllegalArgumentException("Extraneous do while loop."));
|
||||||
}
|
}
|
||||||
|
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
|
|
||||||
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.Definition.def;
|
||||||
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;
|
||||||
|
@ -78,12 +80,12 @@ public class SEach extends AStatement {
|
||||||
locals = Locals.newLocalScope(locals);
|
locals = Locals.newLocalScope(locals);
|
||||||
Variable variable = locals.addVariable(location, type, name, true);
|
Variable variable = locals.addVariable(location, type, name, true);
|
||||||
|
|
||||||
if (expression.actual.dimensions > 0) {
|
if (expression.actual.isArray()) {
|
||||||
sub = new SSubEachArray(location, variable, expression, block);
|
sub = new SSubEachArray(location, variable, expression, block);
|
||||||
} else if (expression.actual.dynamic || Iterable.class.isAssignableFrom(expression.actual.clazz)) {
|
} else if (expression.actual == def.class || Iterable.class.isAssignableFrom(expression.actual)) {
|
||||||
sub = new SSubEachIterable(location, variable, expression, block);
|
sub = new SSubEachIterable(location, variable, expression, block);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal for each type [" + expression.actual.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal for each type [" + Definition.ClassToName(expression.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub.analyze(locals);
|
sub.analyze(locals);
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -58,9 +59,9 @@ public final class SExpression extends AStatement {
|
||||||
throw createError(new IllegalArgumentException("Not a statement."));
|
throw createError(new IllegalArgumentException("Not a statement."));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rtn = lastSource && !isVoid && expression.actual.clazz != void.class;
|
boolean rtn = lastSource && !isVoid && expression.actual != void.class;
|
||||||
|
|
||||||
expression.expected = rtn ? rtnType : expression.actual;
|
expression.expected = rtn ? Definition.TypeToClass(rtnType) : expression.actual;
|
||||||
expression.internal = rtn;
|
expression.internal = rtn;
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ public final class SExpression extends AStatement {
|
||||||
if (methodEscape) {
|
if (methodEscape) {
|
||||||
writer.returnValue();
|
writer.returnValue();
|
||||||
} else {
|
} else {
|
||||||
writer.writePop(expression.expected.type.getSize());
|
writer.writePop(MethodWriter.getType(expression.expected).getSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -94,7 +93,7 @@ public final class SFor extends AStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
@ -161,7 +160,7 @@ public final class SFor extends AStatement {
|
||||||
AExpression initializer = (AExpression)this.initializer;
|
AExpression initializer = (AExpression)this.initializer;
|
||||||
|
|
||||||
initializer.write(writer, globals);
|
initializer.write(writer, globals);
|
||||||
writer.writePop(initializer.expected.type.getSize());
|
writer.writePop(MethodWriter.getType(initializer.expected).getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.mark(start);
|
writer.mark(start);
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -56,7 +55,7 @@ public final class SIf extends AStatement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -65,7 +64,7 @@ public final class SIfElse extends AStatement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition;
|
||||||
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;
|
||||||
|
@ -47,7 +48,7 @@ public final class SReturn extends AStatement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
expression.expected = locals.getReturnType();
|
expression.expected = Definition.TypeToClass(locals.getReturnType());
|
||||||
expression.internal = true;
|
expression.internal = true;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
@ -68,6 +69,6 @@ public final class SReturn extends AStatement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return singleLineToString(expression);
|
return singleLineToString(expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,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.
|
||||||
array = locals.addVariable(location, expression.actual, "#array" + location.getOffset(), true);
|
Type actualType = locals.getDefinition().ClassToType(expression.actual);
|
||||||
|
array = locals.addVariable(location, actualType, "#array" + location.getOffset(), true);
|
||||||
index = locals.addVariable(location, locals.getDefinition().intType, "#index" + location.getOffset(), true);
|
index = locals.addVariable(location, locals.getDefinition().intType, "#index" + location.getOffset(), true);
|
||||||
indexed = locals.getDefinition().getType(expression.actual.struct, expression.actual.dimensions - 1);
|
indexed = locals.getDefinition().getType(actualType.struct, actualType.dimensions - 1);
|
||||||
cast = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(indexed), Definition.TypeToClass(variable.type), true, true);
|
cast = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(indexed), Definition.TypeToClass(variable.type), true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.elasticsearch.painless.Definition;
|
||||||
import org.elasticsearch.painless.Definition.Cast;
|
import org.elasticsearch.painless.Definition.Cast;
|
||||||
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.Definition.def;
|
import org.elasticsearch.painless.Definition.def;
|
||||||
import org.elasticsearch.painless.Globals;
|
import org.elasticsearch.painless.Globals;
|
||||||
import org.elasticsearch.painless.Locals;
|
import org.elasticsearch.painless.Locals;
|
||||||
|
@ -75,14 +76,15 @@ final class SSubEachIterable extends AStatement {
|
||||||
iterator = locals.addVariable(location, locals.getDefinition().getType("Iterator"),
|
iterator = locals.addVariable(location, locals.getDefinition().getType("Iterator"),
|
||||||
"#itr" + location.getOffset(), true);
|
"#itr" + location.getOffset(), true);
|
||||||
|
|
||||||
if (expression.actual.dynamic) {
|
if (expression.actual == def.class) {
|
||||||
method = null;
|
method = null;
|
||||||
} else {
|
} else {
|
||||||
method = expression.actual.struct.methods.get(new MethodKey("iterator", 0));
|
Type actualType = locals.getDefinition().ClassToType(expression.actual);
|
||||||
|
method = actualType.struct.methods.get(new MethodKey("iterator", 0));
|
||||||
|
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw createError(new IllegalArgumentException(
|
throw createError(new IllegalArgumentException(
|
||||||
"Unable to create iterator for the type [" + expression.actual.name + "]."));
|
"Unable to create iterator for the type [" + actualType.name + "]."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -48,7 +47,7 @@ public final class SThrow extends AStatement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
expression.expected = locals.getDefinition().ExceptionType;
|
expression.expected = Exception.class;
|
||||||
expression.analyze(locals);
|
expression.analyze(locals);
|
||||||
expression = expression.cast(locals);
|
expression = expression.cast(locals);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.node;
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
import org.elasticsearch.painless.Definition;
|
|
||||||
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;
|
||||||
|
@ -59,7 +58,7 @@ public final class SWhile extends AStatement {
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
locals = Locals.newLocalScope(locals);
|
locals = Locals.newLocalScope(locals);
|
||||||
|
|
||||||
condition.expected = locals.getDefinition().booleanType;
|
condition.expected = boolean.class;
|
||||||
condition.analyze(locals);
|
condition.analyze(locals);
|
||||||
condition = condition.cast(locals);
|
condition = condition.cast(locals);
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ public class NodeToStringTests extends ESTestCase {
|
||||||
|
|
||||||
public void testPSubBrace() {
|
public void testPSubBrace() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
PSubBrace node = new PSubBrace(l, definition.intType, new ENumeric(l, "1", 10));
|
PSubBrace node = new PSubBrace(l, int.class, new ENumeric(l, "1", 10));
|
||||||
node.prefix = new EVariable(l, "a");
|
node.prefix = new EVariable(l, "a");
|
||||||
assertEquals("(PSubBrace (EVariable a) (ENumeric 1))", node.toString());
|
assertEquals("(PSubBrace (EVariable a) (ENumeric 1))", node.toString());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue