Completely remove Painless Type from AnalyzerCaster in favor of Java Class. (#28329)

Second part in a series of PR's to remove Painless Type in favor of Java Class. This completely removes the Painless Type dependency from AnalyzerCaster. Both casting and promotion are now based on Java Class exclusively. This also allows AnalyzerCaster to be decoupled from Definition and make cast checks be static calls again.
This commit is contained in:
Jack Conradson 2018-01-23 12:38:31 -08:00 committed by GitHub
parent 7c5619a29a
commit b945006938
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 272 additions and 249 deletions

View File

@ -20,7 +20,6 @@
package org.elasticsearch.painless;
import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Type;
import org.elasticsearch.painless.Definition.def;
import java.util.Objects;
@ -31,26 +30,9 @@ import java.util.Objects;
*/
public final class AnalyzerCaster {
private Definition definition;
public AnalyzerCaster(Definition definition) {
this.definition = definition;
}
public Cast getLegalCast(Location location, Type actualType, Type expectedType, boolean explicit, boolean internal) {
Objects.requireNonNull(actualType);
Objects.requireNonNull(expectedType);
Class<?> actual = actualType.clazz;
Class<?> expected = expectedType.clazz;
if (actualType.dynamic) {
actual = Definition.ObjectClassTodefClass(actual);
}
if (expectedType.dynamic) {
expected = Definition.ObjectClassTodefClass(expected);
}
public static Cast getLegalCast(Location location, Class<?> actual, Class<?> expected, boolean explicit, boolean internal) {
Objects.requireNonNull(actual);
Objects.requireNonNull(expected);
if (actual == expected) {
return null;
@ -487,7 +469,7 @@ public final class AnalyzerCaster {
}
}
public Object constCast(Location location, final Object constant, final Cast cast) {
public static Object constCast(Location location, Object constant, Cast cast) {
Class<?> fsort = cast.from;
Class<?> tsort = cast.to;
@ -498,7 +480,7 @@ public final class AnalyzerCaster {
} else if (fsort == char.class && tsort == String.class) {
return Utility.charToString((char)constant);
} else if (fsort.isPrimitive() && fsort != boolean.class && tsort.isPrimitive() && tsort != boolean.class) {
final Number number;
Number number;
if (fsort == char.class) {
number = (int)(char)constant;
@ -523,224 +505,201 @@ public final class AnalyzerCaster {
}
}
public Type promoteNumeric(Type from, boolean decimal) {
Class<?> sort = from.clazz;
if (from.dynamic) {
return definition.DefType;
} else if ((sort == double.class) && decimal) {
return definition.doubleType;
} else if ((sort == float.class) && decimal) {
return definition.floatType;
} else if (sort == long.class) {
return definition.longType;
} else if (sort == int.class || sort == char.class || sort == short.class || sort == byte.class) {
return definition.intType;
public static Class<?> promoteNumeric(Class<?> from, boolean decimal) {
if (from == def.class || from == double.class && decimal || from == float.class && decimal || from == long.class) {
return from;
} else if (from == int.class || from == char.class || from == short.class || from == byte.class) {
return int.class;
}
return null;
}
public Type promoteNumeric(Type from0, Type from1, boolean decimal) {
Class<?> sort0 = from0.clazz;
Class<?> sort1 = from1.clazz;
if (from0.dynamic || from1.dynamic) {
return definition.DefType;
public static Class<?> promoteNumeric(Class<?> from0, Class<?> from1, boolean decimal) {
if (from0 == def.class || from1 == def.class) {
return def.class;
}
if (decimal) {
if (sort0 == double.class || sort1 == double.class) {
return definition.doubleType;
} else if (sort0 == float.class || sort1 == float.class) {
return definition.floatType;
if (from0 == double.class || from1 == double.class) {
return double.class;
} else if (from0 == float.class || from1 == float.class) {
return float.class;
}
}
if (sort0 == long.class || sort1 == long.class) {
return definition.longType;
} else if (sort0 == int.class || sort1 == int.class ||
sort0 == char.class || sort1 == char.class ||
sort0 == short.class || sort1 == short.class ||
sort0 == byte.class || sort1 == byte.class) {
return definition.intType;
if (from0 == long.class || from1 == long.class) {
return long.class;
} else if (from0 == int.class || from1 == int.class ||
from0 == char.class || from1 == char.class ||
from0 == short.class || from1 == short.class ||
from0 == byte.class || from1 == byte.class) {
return int.class;
}
return null;
}
public Type promoteAdd(Type from0, Type from1) {
Class<?> sort0 = from0.clazz;
Class<?> sort1 = from1.clazz;
if (sort0 == String.class || sort1 == String.class) {
return definition.StringType;
public static Class<?> promoteAdd(Class<?> from0, Class<?> from1) {
if (from0 == String.class || from1 == String.class) {
return String.class;
}
return promoteNumeric(from0, from1, true);
}
public Type promoteXor(Type from0, Type from1) {
Class<?> sort0 = from0.clazz;
Class<?> sort1 = from1.clazz;
if (from0.dynamic || from1.dynamic) {
return definition.DefType;
public static Class<?> promoteXor(Class<?> from0, Class<?> from1) {
if (from0 == def.class || from1 == def.class) {
return def.class;
}
if (sort0 == boolean.class || sort1 == boolean.class) {
return definition.booleanType;
if (from0 == boolean.class || from1 == boolean.class) {
return boolean.class;
}
return promoteNumeric(from0, from1, false);
}
public Type promoteEquality(Type from0, Type from1) {
Class<?> sort0 = from0.clazz;
Class<?> sort1 = from1.clazz;
if (from0.dynamic || from1.dynamic) {
return definition.DefType;
public static Class<?> promoteEquality(Class<?> from0, Class<?> from1) {
if (from0 == def.class || from1 == def.class) {
return def.class;
}
if (sort0.isPrimitive() && sort1.isPrimitive()) {
if (sort0 == boolean.class && sort1 == boolean.class) {
return definition.booleanType;
if (from0.isPrimitive() && from1.isPrimitive()) {
if (from0 == boolean.class && from1 == boolean.class) {
return boolean.class;
}
return promoteNumeric(from0, from1, true);
}
return definition.ObjectType;
return Object.class;
}
public Type promoteConditional(Type from0, Type from1, Object const0, Object const1) {
if (from0.equals(from1)) {
public static Class<?> promoteConditional(Class<?> from0, Class<?> from1, Object const0, Object const1) {
if (from0 == from1) {
return from0;
}
Class<?> sort0 = from0.clazz;
Class<?> sort1 = from1.clazz;
if (from0.dynamic || from1.dynamic) {
return definition.DefType;
if (from0 == def.class || from1 == def.class) {
return def.class;
}
if (sort0.isPrimitive() && sort1.isPrimitive()) {
if (sort0 == boolean.class && sort1 == boolean.class) {
return definition.booleanType;
if (from0.isPrimitive() && from1.isPrimitive()) {
if (from0 == boolean.class && from1 == boolean.class) {
return boolean.class;
}
if (sort0 == double.class || sort1 == double.class) {
return definition.doubleType;
} else if (sort0 == float.class || sort1 == float.class) {
return definition.floatType;
} else if (sort0 == long.class || sort1 == long.class) {
return definition.longType;
if (from0 == double.class || from1 == double.class) {
return double.class;
} else if (from0 == float.class || from1 == float.class) {
return float.class;
} else if (from0 == long.class || from1 == long.class) {
return long.class;
} else {
if (sort0 == byte.class) {
if (sort1 == byte.class) {
return definition.byteType;
} else if (sort1 == short.class) {
if (from0 == byte.class) {
if (from1 == byte.class) {
return byte.class;
} else if (from1 == short.class) {
if (const1 != null) {
final short constant = (short)const1;
if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.shortType;
} else if (sort1 == char.class) {
return definition.intType;
} else if (sort1 == int.class) {
return short.class;
} else if (from1 == char.class) {
return int.class;
} else if (from1 == int.class) {
if (const1 != null) {
final int constant = (int)const1;
if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.intType;
return int.class;
}
} else if (sort0 == short.class) {
if (sort1 == byte.class) {
} else if (from0 == short.class) {
if (from1 == byte.class) {
if (const0 != null) {
final short constant = (short)const0;
if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.shortType;
} else if (sort1 == short.class) {
return definition.shortType;
} else if (sort1 == char.class) {
return definition.intType;
} else if (sort1 == int.class) {
return short.class;
} else if (from1 == short.class) {
return short.class;
} else if (from1 == char.class) {
return int.class;
} else if (from1 == int.class) {
if (const1 != null) {
final int constant = (int)const1;
if (constant <= Short.MAX_VALUE && constant >= Short.MIN_VALUE) {
return definition.shortType;
return short.class;
}
}
return definition.intType;
return int.class;
}
} else if (sort0 == char.class) {
if (sort1 == byte.class) {
return definition.intType;
} else if (sort1 == short.class) {
return definition.intType;
} else if (sort1 == char.class) {
return definition.charType;
} else if (sort1 == int.class) {
} else if (from0 == char.class) {
if (from1 == byte.class) {
return int.class;
} else if (from1 == short.class) {
return int.class;
} else if (from1 == char.class) {
return char.class;
} else if (from1 == int.class) {
if (const1 != null) {
final int constant = (int)const1;
if (constant <= Character.MAX_VALUE && constant >= Character.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.intType;
return int.class;
}
} else if (sort0 == int.class) {
if (sort1 == byte.class) {
} else if (from0 == int.class) {
if (from1 == byte.class) {
if (const0 != null) {
final int constant = (int)const0;
if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.intType;
} else if (sort1 == short.class) {
return int.class;
} else if (from1 == short.class) {
if (const0 != null) {
final int constant = (int)const0;
if (constant <= Short.MAX_VALUE && constant >= Short.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.intType;
} else if (sort1 == char.class) {
return int.class;
} else if (from1 == char.class) {
if (const0 != null) {
final int constant = (int)const0;
if (constant <= Character.MAX_VALUE && constant >= Character.MIN_VALUE) {
return definition.byteType;
return byte.class;
}
}
return definition.intType;
} else if (sort1 == int.class) {
return definition.intType;
return int.class;
} else if (from1 == int.class) {
return int.class;
}
}
}
@ -750,6 +709,10 @@ public final class AnalyzerCaster {
// TODO: to calculate the highest upper bound for the two types and return that.
// TODO: However, for now we just return objectType that may require an extra cast.
return definition.ObjectType;
return Object.class;
}
private AnalyzerCaster() {
}
}

View File

@ -591,7 +591,39 @@ public final class Definition {
return "def";
}
return clazz.getCanonicalName();
return clazz.getCanonicalName().replace('$', '.');
}
public Type ClassToType(Class<?> clazz) {
if (clazz == null) {
return null;
} else if (clazz.isArray()) {
Class<?> component = clazz.getComponentType();
int dimensions = 1;
while (component.isArray()) {
component = component.getComponentType();
++dimensions;
}
if (clazz == def.class) {
return getType(structsMap.get("def"), dimensions);
} else {
return getType(runtimeMap.get(clazz).struct, dimensions);
}
} else if (clazz == def.class) {
return getType(structsMap.get("def"), 0);
}
return getType(structsMap.get(ClassToName(clazz)), 0);
}
public static Class<?> TypeToClass (Type type) {
if (type.dynamic) {
return ObjectClassTodefClass(type.clazz);
}
return type.clazz;
}
public RuntimeClass getRuntimeClass(Class<?> clazz) {
@ -631,8 +663,6 @@ public final class Definition {
private final Map<String, Struct> structsMap;
private final Map<String, Type> simpleTypesMap;
public AnalyzerCaster caster;
public Definition(List<Whitelist> whitelists) {
structsMap = new HashMap<>();
simpleTypesMap = new HashMap<>();
@ -814,8 +844,6 @@ public final class Definition {
IteratorType = getType("Iterator");
ArrayListType = getType("ArrayList");
HashMapType = getType("HashMap");
caster = new AnalyzerCaster(this);
}
private void addStruct(ClassLoader whitelistClassLoader, Whitelist.Struct whitelistStruct) {

View File

@ -119,7 +119,8 @@ public abstract class AExpression extends ANode {
* @return The new child node for the parent node calling this method.
*/
AExpression cast(Locals locals) {
Cast cast = locals.getDefinition().caster.getLegalCast(location, actual, expected, explicit, internal);
Cast cast =
AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(actual), Definition.TypeToClass(expected), explicit, internal);
if (cast == null) {
if (constant == null || this instanceof EConstant) {
@ -167,7 +168,7 @@ public abstract class AExpression extends ANode {
// from this node because the output data for the EConstant
// will already be the same.
constant = locals.getDefinition().caster.constCast(location, constant, cast);
constant = AnalyzerCaster.constCast(location, constant, cast);
EConstant econstant = new EConstant(location, constant);
econstant.analyze(locals);

View File

@ -19,7 +19,10 @@
package org.elasticsearch.painless.node;
import org.elasticsearch.painless.AnalyzerCaster;
import org.elasticsearch.painless.DefBootstrap;
import org.elasticsearch.painless.Definition;
import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Type;
import org.elasticsearch.painless.Globals;
@ -139,33 +142,41 @@ public final class EAssignment extends AExpression {
boolean shift = false;
if (operation == Operation.MUL) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, rhs.actual, true);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
} else if (operation == Operation.DIV) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, rhs.actual, true);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
} else if (operation == Operation.REM) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, rhs.actual, true);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
} else if (operation == Operation.ADD) {
promote = locals.getDefinition().caster.promoteAdd(lhs.actual, rhs.actual);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteAdd(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
} else if (operation == Operation.SUB) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, rhs.actual, true);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), true));
} else if (operation == Operation.LSH) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, false);
shiftDistance = locals.getDefinition().caster.promoteNumeric(rhs.actual, false);
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
shift = true;
} else if (operation == Operation.RSH) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, false);
shiftDistance = locals.getDefinition().caster.promoteNumeric(rhs.actual, false);
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
shift = true;
} else if (operation == Operation.USH) {
promote = locals.getDefinition().caster.promoteNumeric(lhs.actual, false);
shiftDistance = locals.getDefinition().caster.promoteNumeric(rhs.actual, false);
promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(lhs.actual), false));
shiftDistance = locals.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(rhs.actual), false));
shift = true;
} else if (operation == Operation.BWAND) {
promote = locals.getDefinition().caster.promoteXor(lhs.actual, rhs.actual);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
} else if (operation == Operation.XOR) {
promote = locals.getDefinition().caster.promoteXor(lhs.actual, rhs.actual);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
} else if (operation == Operation.BWOR) {
promote = locals.getDefinition().caster.promoteXor(lhs.actual, rhs.actual);
promote = locals.getDefinition().ClassToType(
AnalyzerCaster.promoteXor(Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual)));
} else {
throw createError(new IllegalStateException("Illegal tree structure."));
}
@ -199,8 +210,8 @@ public final class EAssignment extends AExpression {
rhs = rhs.cast(locals);
there = locals.getDefinition().caster.getLegalCast(location, lhs.actual, promote, false, false);
back = locals.getDefinition().caster.getLegalCast(location, promote, lhs.actual, true, false);
there = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(lhs.actual), Definition.TypeToClass(promote), false, false);
back = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(promote), Definition.TypeToClass(lhs.actual), true, false);
this.statement = true;
this.actual = read ? lhs.actual : locals.getDefinition().voidType;

View File

@ -19,6 +19,7 @@
package org.elasticsearch.painless.node;
import org.elasticsearch.painless.AnalyzerCaster;
import org.elasticsearch.painless.DefBootstrap;
import org.elasticsearch.painless.Definition;
import org.elasticsearch.painless.Definition.Type;
@ -101,7 +102,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
@ -145,7 +147,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply divide [/] to types " +
@ -194,7 +197,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
@ -243,7 +247,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteAdd(left.actual, right.actual);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteAdd(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply add [+] to types " +
@ -303,7 +308,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
@ -362,8 +368,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
Type lhspromote = variables.getDefinition().caster.promoteNumeric(left.actual, false);
Type rhspromote = variables.getDefinition().caster.promoteNumeric(right.actual, false);
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
if (lhspromote == null || rhspromote == null) {
throw createError(new ClassCastException("Cannot apply left shift [<<] to types " +
@ -411,8 +417,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
Type lhspromote = variables.getDefinition().caster.promoteNumeric(left.actual, false);
Type rhspromote = variables.getDefinition().caster.promoteNumeric(right.actual, false);
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
if (lhspromote == null || rhspromote == null) {
throw createError(new ClassCastException("Cannot apply right shift [>>] to types " +
@ -460,8 +466,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
Type lhspromote = variables.getDefinition().caster.promoteNumeric(left.actual, false);
Type rhspromote = variables.getDefinition().caster.promoteNumeric(right.actual, false);
Type lhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), false));
Type rhspromote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(right.actual), false));
actual = promote = lhspromote;
shiftDistance = rhspromote;
@ -509,7 +515,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, false);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), false));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply and [&] to types " +
@ -550,7 +557,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteXor(left.actual, right.actual);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteXor(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply xor [^] to types " +
@ -592,7 +600,8 @@ public final class EBinary extends AExpression {
left.analyze(variables);
right.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, false);
promote = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), false));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply or [|] to types " +

View File

@ -82,11 +82,12 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
Definition.Type from = ref.interfaceMethod.arguments.get(i);
Definition.Type to = ref.delegateMethod.arguments.get(i);
locals.getDefinition().caster.getLegalCast(location, from, to, false, true);
AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(from), Definition.TypeToClass(to), false, true);
}
if (ref.interfaceMethod.rtn.equals(locals.getDefinition().voidType) == false) {
locals.getDefinition().caster.getLegalCast(location, ref.delegateMethod.rtn, ref.interfaceMethod.rtn, false, true);
AnalyzerCaster.getLegalCast(location,
Definition.TypeToClass(ref.delegateMethod.rtn), Definition.TypeToClass(ref.interfaceMethod.rtn), false, true);
}
} catch (IllegalArgumentException e) {
throw createError(e);

View File

@ -89,7 +89,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteEquality(left.actual, right.actual);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply equals [==] to types " +
@ -140,7 +141,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteEquality(left.actual, right.actual);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
@ -182,7 +184,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteEquality(left.actual, right.actual);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
@ -233,7 +236,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteEquality(left.actual, right.actual);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteEquality(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual)));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
@ -275,7 +279,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
@ -316,7 +321,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
@ -357,7 +363,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
@ -398,7 +405,8 @@ public final class EComp extends AExpression {
left.analyze(variables);
right.analyze(variables);
promotedType = variables.getDefinition().caster.promoteNumeric(left.actual, right.actual, true);
promotedType = variables.getDefinition().ClassToType(
AnalyzerCaster.promoteNumeric(Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), true));
if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply less than [>=] to types " +

View File

@ -79,7 +79,8 @@ public final class EConditional extends AExpression {
right.analyze(locals);
if (expected == null) {
final Type promote = locals.getDefinition().caster.promoteConditional(left.actual, right.actual, left.constant, right.constant);
Type promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteConditional(
Definition.TypeToClass(left.actual), Definition.TypeToClass(right.actual), left.constant, right.constant));
left.expected = promote;
right.expected = promote;

View File

@ -20,6 +20,7 @@
package org.elasticsearch.painless.node;
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.Locals;
@ -81,7 +82,8 @@ public class EElvis extends AExpression {
}
if (expected == null) {
final Type promote = locals.getDefinition().caster.promoteConditional(lhs.actual, rhs.actual, lhs.constant, rhs.constant);
Type promote = locals.getDefinition().ClassToType(AnalyzerCaster.promoteConditional(
Definition.TypeToClass(lhs.actual), Definition.TypeToClass(rhs.actual), lhs.constant, rhs.constant));
lhs.expected = promote;
rhs.expected = promote;

View File

@ -82,11 +82,12 @@ public final class EFunctionRef extends AExpression implements ILambda {
for (int i = 0; i < interfaceMethod.arguments.size(); ++i) {
Definition.Type from = interfaceMethod.arguments.get(i);
Definition.Type to = delegateMethod.arguments.get(i);
locals.getDefinition().caster.getLegalCast(location, from, to, false, true);
AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(from), Definition.TypeToClass(to), false, true);
}
if (interfaceMethod.rtn.equals(locals.getDefinition().voidType) == false) {
locals.getDefinition().caster.getLegalCast(location, delegateMethod.rtn, interfaceMethod.rtn, false, true);
AnalyzerCaster.getLegalCast(
location, Definition.TypeToClass(delegateMethod.rtn), Definition.TypeToClass(interfaceMethod.rtn), false, true);
}
} else {
// whitelist lookup

View File

@ -192,11 +192,12 @@ public final class ELambda extends AExpression implements ILambda {
for (int i = 0; i < interfaceMethod.arguments.size(); ++i) {
Type from = interfaceMethod.arguments.get(i);
Type to = desugared.parameters.get(i + captures.size()).type;
locals.getDefinition().caster.getLegalCast(location, from, to, false, true);
AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(from), Definition.TypeToClass(to), false, true);
}
if (interfaceMethod.rtn.equals(locals.getDefinition().voidType) == false) {
locals.getDefinition().caster.getLegalCast(location, desugared.rtnType, interfaceMethod.rtn, false, true);
AnalyzerCaster.getLegalCast(
location, Definition.TypeToClass(desugared.rtnType), Definition.TypeToClass(interfaceMethod.rtn), false, true);
}
actual = expected;

View File

@ -90,7 +90,7 @@ public final class EUnary extends AExpression {
void analyzeBWNot(Locals variables) {
child.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(child.actual, false);
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), false));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply not [~] to type [" + child.actual.name + "]."));
@ -121,7 +121,7 @@ public final class EUnary extends AExpression {
void analyzerAdd(Locals variables) {
child.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(child.actual, true);
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply positive [+] to type [" + child.actual.name + "]."));
@ -156,7 +156,7 @@ public final class EUnary extends AExpression {
void analyzerSub(Locals variables) {
child.analyze(variables);
promote = variables.getDefinition().caster.promoteNumeric(child.actual, true);
promote = variables.getDefinition().ClassToType(AnalyzerCaster.promoteNumeric(Definition.TypeToClass(child.actual), true));
if (promote == null) {
throw createError(new ClassCastException("Cannot apply negative [-] to type [" + child.actual.name + "]."));

View File

@ -64,13 +64,10 @@ final class SSubEachArray extends AStatement {
void analyze(Locals locals) {
// 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.
array = locals.addVariable(location, expression.actual, "#array" + 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);
cast = locals.getDefinition().caster.getLegalCast(location, indexed, variable.type, true, true);
array = locals.addVariable(location, expression.actual, "#array" + 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);
cast = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(indexed), Definition.TypeToClass(variable.type), true, true);
}
@Override

View File

@ -25,6 +25,7 @@ import org.elasticsearch.painless.Definition;
import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Method;
import org.elasticsearch.painless.Definition.MethodKey;
import org.elasticsearch.painless.Definition.def;
import org.elasticsearch.painless.Globals;
import org.elasticsearch.painless.Locals;
import org.elasticsearch.painless.Locals.Variable;
@ -85,7 +86,7 @@ final class SSubEachIterable extends AStatement {
}
}
cast = locals.getDefinition().caster.getLegalCast(location, locals.getDefinition().DefType, variable.type, true, true);
cast = AnalyzerCaster.getLegalCast(location, def.class, Definition.TypeToClass(variable.type), true, true);
}
@Override

View File

@ -20,7 +20,6 @@
package org.elasticsearch.painless;
import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Type;
import org.elasticsearch.painless.spi.Whitelist;
import org.elasticsearch.test.ESTestCase;
@ -28,73 +27,73 @@ public class AnalyzerCasterTests extends ESTestCase {
private static final Definition definition = new Definition(Whitelist.BASE_WHITELISTS);
private static void assertCast(Type actual, Type expected, boolean mustBeExplicit) {
private static void assertCast(Class<?> actual, Class<?> expected, boolean mustBeExplicit) {
Location location = new Location("dummy", 0);
if (actual.equals(expected)) {
assertFalse(mustBeExplicit);
assertNull(definition.caster.getLegalCast(location, actual, expected, false, false));
assertNull(definition.caster.getLegalCast(location, actual, expected, true, false));
assertNull(AnalyzerCaster.getLegalCast(location, actual, expected, false, false));
assertNull(AnalyzerCaster.getLegalCast(location, actual, expected, true, false));
return;
}
Cast cast = definition.caster.getLegalCast(location, actual, expected, true, false);
assertEquals(actual.clazz, cast.from);
assertEquals(expected.clazz, cast.to);
Cast cast = AnalyzerCaster.getLegalCast(location, actual, expected, true, false);
assertEquals(actual, cast.from);
assertEquals(expected, cast.to);
if (mustBeExplicit) {
ClassCastException error = expectThrows(ClassCastException.class,
() -> definition.caster.getLegalCast(location, actual, expected, false, false));
() -> AnalyzerCaster.getLegalCast(location, actual, expected, false, false));
assertTrue(error.getMessage().startsWith("Cannot cast"));
} else {
cast = definition.caster.getLegalCast(location, actual, expected, false, false);
assertEquals(actual.clazz, cast.from);
assertEquals(expected.clazz, cast.to);
cast = AnalyzerCaster.getLegalCast(location, actual, expected, false, false);
assertEquals(actual, cast.from);
assertEquals(expected, cast.to);
}
}
public void testNumericCasts() {
assertCast(definition.byteType, definition.byteType, false);
assertCast(definition.byteType, definition.shortType, false);
assertCast(definition.byteType, definition.intType, false);
assertCast(definition.byteType, definition.longType, false);
assertCast(definition.byteType, definition.floatType, false);
assertCast(definition.byteType, definition.doubleType, false);
assertCast(byte.class, byte.class, false);
assertCast(byte.class, short.class, false);
assertCast(byte.class, int.class, false);
assertCast(byte.class, long.class, false);
assertCast(byte.class, float.class, false);
assertCast(byte.class, double.class, false);
assertCast(definition.shortType, definition.byteType, true);
assertCast(definition.shortType, definition.shortType, false);
assertCast(definition.shortType, definition.intType, false);
assertCast(definition.shortType, definition.longType, false);
assertCast(definition.shortType, definition.floatType, false);
assertCast(definition.shortType, definition.doubleType, false);
assertCast(short.class, byte.class, true);
assertCast(short.class, short.class, false);
assertCast(short.class, int.class, false);
assertCast(short.class, long.class, false);
assertCast(short.class, float.class, false);
assertCast(short.class, double.class, false);
assertCast(definition.intType, definition.byteType, true);
assertCast(definition.intType, definition.shortType, true);
assertCast(definition.intType, definition.intType, false);
assertCast(definition.intType, definition.longType, false);
assertCast(definition.intType, definition.floatType, false);
assertCast(definition.intType, definition.doubleType, false);
assertCast(int.class, byte.class, true);
assertCast(int.class, short.class, true);
assertCast(int.class, int.class, false);
assertCast(int.class, long.class, false);
assertCast(int.class, float.class, false);
assertCast(int.class, double.class, false);
assertCast(definition.longType, definition.byteType, true);
assertCast(definition.longType, definition.shortType, true);
assertCast(definition.longType, definition.intType, true);
assertCast(definition.longType, definition.longType, false);
assertCast(definition.longType, definition.floatType, false);
assertCast(definition.longType, definition.doubleType, false);
assertCast(long.class, byte.class, true);
assertCast(long.class, short.class, true);
assertCast(long.class, int.class, true);
assertCast(long.class, long.class, false);
assertCast(long.class, float.class, false);
assertCast(long.class, double.class, false);
assertCast(definition.floatType, definition.byteType, true);
assertCast(definition.floatType, definition.shortType, true);
assertCast(definition.floatType, definition.intType, true);
assertCast(definition.floatType, definition.longType, true);
assertCast(definition.floatType, definition.floatType, false);
assertCast(definition.floatType, definition.doubleType, false);
assertCast(float.class, byte.class, true);
assertCast(float.class, short.class, true);
assertCast(float.class, int.class, true);
assertCast(float.class, long.class, true);
assertCast(float.class, float.class, false);
assertCast(float.class, double.class, false);
assertCast(definition.doubleType, definition.byteType, true);
assertCast(definition.doubleType, definition.shortType, true);
assertCast(definition.doubleType, definition.intType, true);
assertCast(definition.doubleType, definition.longType, true);
assertCast(definition.doubleType, definition.floatType, true);
assertCast(definition.doubleType, definition.doubleType, false);
assertCast(double.class, byte.class, true);
assertCast(double.class, short.class, true);
assertCast(double.class, int.class, true);
assertCast(double.class, long.class, true);
assertCast(double.class, float.class, true);
assertCast(double.class, double.class, false);
}
}