From c0ffea89c208e8c516cce6ae304706e1990b8e58 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 23 Jan 2018 12:38:31 -0800 Subject: [PATCH] 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. --- .../painless/AnalyzerCaster.java | 239 ++++++++---------- .../elasticsearch/painless/Definition.java | 38 ++- .../painless/node/AExpression.java | 5 +- .../painless/node/EAssignment.java | 43 ++-- .../elasticsearch/painless/node/EBinary.java | 37 ++- .../painless/node/ECapturingFunctionRef.java | 5 +- .../elasticsearch/painless/node/EComp.java | 24 +- .../painless/node/EConditional.java | 3 +- .../elasticsearch/painless/node/EElvis.java | 4 +- .../painless/node/EFunctionRef.java | 5 +- .../elasticsearch/painless/node/ELambda.java | 5 +- .../elasticsearch/painless/node/EUnary.java | 6 +- .../painless/node/SSubEachArray.java | 11 +- .../painless/node/SSubEachIterable.java | 3 +- .../painless/AnalyzerCasterTests.java | 93 ++++--- 15 files changed, 272 insertions(+), 249 deletions(-) diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java index 7bae2c7fcad69..abba62de39c19 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java @@ -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 @@ */ 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 Cast getLegalCast(Location location, Type actualType, Type expectedType, } } - 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 Object constCast(Location location, final Object constant, final Cast cas } 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 Object constCast(Location location, final Object constant, final Cast cas } } - 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 Type promoteConditional(Type from0, Type from1, Object const0, Object con // 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() { + } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java index 52f0c2c63302d..36c072570ec14 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java @@ -591,7 +591,39 @@ public static String ClassToName(Class clazz) { 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 @@ private static String buildFieldCacheKey(String structName, String fieldName, St private final Map structsMap; private final Map simpleTypesMap; - public AnalyzerCaster caster; - public Definition(List whitelists) { structsMap = new HashMap<>(); simpleTypesMap = new HashMap<>(); @@ -814,8 +844,6 @@ public Definition(List whitelists) { IteratorType = getType("Iterator"); ArrayListType = getType("ArrayList"); HashMapType = getType("HashMap"); - - caster = new AnalyzerCaster(this); } private void addStruct(ClassLoader whitelistClassLoader, Whitelist.Struct whitelistStruct) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java index 2ca0b265430f9..eaa13ea9a8b17 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java @@ -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 @@ AExpression cast(Locals locals) { // 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); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java index 873f109e72d47..45ca4601e963d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java @@ -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 @@ private void analyzeCompound(Locals locals) { 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 @@ private void analyzeCompound(Locals locals) { 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; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java index df92d72a3c0c5..55c2145acd8cd 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java @@ -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 @@ private void analyzeMul(Locals variables) { 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 @@ private void analyzeDiv(Locals variables) { 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 @@ private void analyzeRem(Locals variables) { 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 @@ private void analyzeAdd(Locals variables) { 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 @@ private void analyzeSub(Locals variables) { 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 @@ private void analyzeLSH(Locals variables) { 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 @@ private void analyzeRSH(Locals variables) { 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 @@ private void analyzeUSH(Locals variables) { 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 @@ private void analyzeBWAnd(Locals variables) { 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 @@ private void analyzeXor(Locals variables) { 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 @@ private void analyzeBWOr(Locals variables) { 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 " + diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java index 564fcef8eef9f..e736b2779f932 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java @@ -82,11 +82,12 @@ void analyze(Locals locals) { 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); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java index 020ea48cd4c1b..a7bb57a1a35a4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java @@ -89,7 +89,8 @@ private void analyzeEq(Locals variables) { 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 @@ private void analyzeEqR(Locals variables) { 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 @@ private void analyzeNE(Locals variables) { 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 @@ private void analyzeNER(Locals variables) { 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 @@ private void analyzeGTE(Locals variables) { 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 @@ private void analyzeGT(Locals variables) { 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 @@ private void analyzeLTE(Locals variables) { 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 @@ private void analyzeLT(Locals variables) { 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 " + diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java index 571e57cad24db..30a3d0d773f23 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java @@ -79,7 +79,8 @@ void analyze(Locals locals) { 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; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java index e9816c524bf3b..6005a326fe92a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java @@ -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 @@ void analyze(Locals locals) { } 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; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java index ffbb344f29cb9..13289809e49da 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java @@ -82,11 +82,12 @@ void analyze(Locals locals) { 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 diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java index 07de9138e7ca4..68950f5ea2a8b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java @@ -192,11 +192,12 @@ void analyze(Locals locals) { 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; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java index e9971b538f5af..aa81407819eb9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java @@ -90,7 +90,7 @@ void analyzeNot(Locals variables) { 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 @@ void analyzeBWNot(Locals variables) { 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 @@ void analyzerAdd(Locals variables) { 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 + "].")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java index 09c73c525bec0..a4c2eb8cd22cf 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java @@ -64,13 +64,10 @@ void extractVariables(Set variables) { 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 diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java index a51a459f0f3f8..26fb4a2f8459a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java @@ -25,6 +25,7 @@ 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 @@ void analyze(Locals locals) { } } - 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 diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java index b8fe248601764..69abc3481a188 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java @@ -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); } }