diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java index f215e39ad01..e81e828c875 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java @@ -26,10 +26,10 @@ import org.elasticsearch.painless.node.SSource; * Runs the analysis phase of compilation using the Painless AST. */ final class Analyzer { - static Variables analyze(final CompilerSettings settings, final Definition definition, + static Variables analyze(final CompilerSettings settings, final Reserved shortcut, final SSource root) { - final Variables variables = new Variables(settings, definition, shortcut); - root.analyze(settings, definition, variables); + final Variables variables = new Variables(settings, shortcut); + root.analyze(variables); return variables; } 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 3228ff47e92..a16a9818ab3 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,223 +20,770 @@ package org.elasticsearch.painless; import org.elasticsearch.painless.Definition.Cast; -import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Sort; -import org.elasticsearch.painless.Definition.Transform; import org.elasticsearch.painless.Definition.Type; -import java.lang.reflect.InvocationTargetException; - /** * Used during the analysis phase to collect legal type casts and promotions * for type-checking and later to write necessary casts in the bytecode. */ public final class AnalyzerCaster { - public static Cast getLegalCast(final Definition definition, - final String location, final Type actual, final Type expected, final boolean explicit) { - final Cast cast = new Cast(actual, expected, explicit); - + public static Cast getLegalCast(String location, Type actual, Type expected, boolean explicit, boolean internal) { if (actual.equals(expected)) { return null; } - Cast transform = definition.transformsMap.get(cast); + switch (actual.sort) { + case BOOL: + switch (expected.sort) { + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case BOOL_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + } - if (transform == null && explicit) { - transform = definition.transformsMap.get(new Cast(actual, expected, false)); + break; + case BYTE: + switch (expected.sort) { + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit); + case CHAR: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case BYTE_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case SHORT_OBJ: + if (internal) + return new Cast(actual,Definition.SHORT_TYPE, explicit, false, false, false, true); + + break; + case INT_OBJ: + if (internal) + return new Cast(actual, Definition.INT_TYPE, explicit, false, false, false, true); + + break; + case LONG_OBJ: + if (internal) + return new Cast(actual, Definition.LONG_TYPE, explicit, false, false, false, true); + + break; + case FLOAT_OBJ: + if (internal) + return new Cast(actual, Definition.FLOAT_TYPE, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, explicit, false, false, false, true); + + break; + } + + break; + case SHORT: + switch (expected.sort) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit); + case BYTE: + case CHAR: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case SHORT_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case INT_OBJ: + if (internal) + return new Cast(actual, Definition.INT_TYPE, explicit, false, false, false, true); + + break; + case LONG_OBJ: + if (internal) + return new Cast(actual, Definition.LONG_TYPE, explicit, false, false, false, true); + + break; + case FLOAT_OBJ: + if (internal) + return new Cast(actual, Definition.FLOAT_TYPE, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, true, false, false, false, true); + + break; + } + + break; + case CHAR: + switch (expected.sort) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit); + case BYTE: + case SHORT: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case CHAR_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case STRING: + return new Cast(actual, Definition.STRING_TYPE, explicit, false, false, false, false); + case INT_OBJ: + if (internal) + return new Cast(actual, Definition.INT_TYPE, explicit, false, false, false, true); + + break; + case LONG_OBJ: + if (internal) + return new Cast(actual, Definition.LONG_TYPE, explicit, false, false, false, true); + + break; + case FLOAT_OBJ: + if (internal) + return new Cast(actual, Definition.FLOAT_TYPE, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case SHORT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.SHORT_TYPE, true, false, false, false, true); + + break; + } + + break; + case INT: + switch (expected.sort) { + case LONG: + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit); + case BYTE: + case SHORT: + case CHAR: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case INT_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case LONG_OBJ: + if (internal) + return new Cast(actual, Definition.LONG_TYPE, explicit, false, false, false, true); + + break; + case FLOAT_OBJ: + if (internal) + return new Cast(actual, Definition.FLOAT_TYPE, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case SHORT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.SHORT_TYPE, true, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, true, false, false, false, true); + + break; + } + + break; + case LONG: + switch (expected.sort) { + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit); + case BYTE: + case SHORT: + case CHAR: + case INT: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case LONG_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case FLOAT_OBJ: + if (internal) + return new Cast(actual, Definition.FLOAT_TYPE, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case SHORT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.SHORT_TYPE, true, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, true, false, false, false, true); + + break; + case INT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.INT_TYPE, true, false, false, false, true); + + break; + } + + break; + case FLOAT: + switch (expected.sort) { + case DOUBLE: + return new Cast(actual, expected, explicit); + case BYTE: + case SHORT: + case CHAR: + case INT: + case FLOAT: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case FLOAT_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, Definition.DOUBLE_TYPE, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case SHORT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.SHORT_TYPE, true, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, true, false, false, false, true); + + break; + case INT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.INT_TYPE, true, false, false, false, true); + + break; + case LONG_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.LONG_TYPE, true, false, false, false, true); + + break; + } + + break; + case DOUBLE: + switch (expected.sort) { + case BYTE: + case SHORT: + case CHAR: + case INT: + case FLOAT: + if (explicit) + return new Cast(actual, expected, true); + + break; + case DEF: + return new Cast(actual, Definition.DEF_TYPE, explicit, false, false, true, false); + case OBJECT: + case NUMBER: + case DOUBLE_OBJ: + if (internal) + return new Cast(actual, actual, explicit, false, false, false, true); + + break; + case BYTE_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.BYTE_TYPE, true, false, false, false, true); + + break; + case SHORT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.SHORT_TYPE, true, false, false, false, true); + + break; + case CHAR_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.CHAR_TYPE, true, false, false, false, true); + + break; + case INT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.INT_TYPE, true, false, false, false, true); + + break; + case LONG_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.LONG_TYPE, true, false, false, false, true); + + break; + case FLOAT_OBJ: + if (explicit && internal) + return new Cast(actual, Definition.FLOAT_TYPE, true, false, false, false, true); + + break; + } + + break; + case OBJECT: + case NUMBER: + switch (expected.sort) { + case BYTE: + if (internal && explicit) + return new Cast(actual, Definition.BYTE_OBJ_TYPE, true, false, true, false, false); + + break; + case SHORT: + if (internal && explicit) + return new Cast(actual, Definition.SHORT_OBJ_TYPE, true, false, true, false, false); + + break; + case CHAR: + if (internal && explicit) + return new Cast(actual, Definition.CHAR_OBJ_TYPE, true, false, true, false, false); + + break; + case INT: + if (internal && explicit) + return new Cast(actual, Definition.INT_OBJ_TYPE, true, false, true, false, false); + + break; + case LONG: + if (internal && explicit) + return new Cast(actual, Definition.LONG_OBJ_TYPE, true, false, true, false, false); + + break; + case FLOAT: + if (internal && explicit) + return new Cast(actual, Definition.FLOAT_OBJ_TYPE, true, false, true, false, false); + + break; + case DOUBLE: + if (internal && explicit) + return new Cast(actual, Definition.DOUBLE_OBJ_TYPE, true, false, true, false, false); + + break; + } + + break; + case BOOL_OBJ: + switch (expected.sort) { + case BOOL: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + } + + break; + case BYTE_OBJ: + switch (expected.sort) { + case BYTE: + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case CHAR: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case SHORT_OBJ: + switch (expected.sort) { + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case CHAR: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case CHAR_OBJ: + switch (expected.sort) { + case CHAR: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case SHORT: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case INT_OBJ: + switch (expected.sort) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case SHORT: + case CHAR: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case LONG_OBJ: + switch (expected.sort) { + case LONG: + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case FLOAT_OBJ: + switch (expected.sort) { + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + case LONG: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case DOUBLE_OBJ: + switch (expected.sort) { + case FLOAT: + case DOUBLE: + if (internal) + return new Cast(actual, expected, explicit, true, false, false, false); + + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + case LONG: + if (internal && explicit) + return new Cast(actual, expected, true, true, false, false, false); + + break; + } + + break; + case DEF: + switch (expected.sort) { + case BOOL: + case BYTE: + case SHORT: + case CHAR: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return new Cast(actual, expected, explicit, true, false, false, false); + } + + break; + case STRING: + switch (expected.sort) { + case CHAR: + if (explicit) + return new Cast(actual, expected, true, false, false, false, false); + + break; + } + + break; } - if (transform != null) { - return transform; - } - - if (expected.clazz.isAssignableFrom(actual.clazz) || - ((explicit || expected.sort == Sort.DEF) && actual.clazz.isAssignableFrom(expected.clazz))) { - return cast; + if (actual.sort == Sort.DEF || expected.sort == Sort.DEF || + expected.clazz.isAssignableFrom(actual.clazz) || + explicit && actual.clazz.isAssignableFrom(expected.clazz)) { + return new Cast(actual, expected, explicit); } else { throw new ClassCastException("Error" + location + ": Cannot cast from [" + actual.name + "] to [" + expected.name + "]."); } } public static Object constCast(final String location, final Object constant, final Cast cast) { - if (cast instanceof Transform) { - final Transform transform = (Transform)cast; - return invokeTransform(location, transform, constant); + final Sort fsort = cast.from.sort; + final Sort tsort = cast.to.sort; + + if (fsort == tsort) { + return constant; + } else if (fsort == Sort.STRING && tsort == Sort.CHAR) { + return Utility.StringTochar((String)constant); + } else if (fsort == Sort.CHAR && tsort == Sort.STRING) { + return Utility.charToString((char)constant); + } else if (fsort.numeric && tsort.numeric) { + final Number number; + + if (fsort == Sort.CHAR) { + number = (int)(char)constant; + } else { + number = (Number)constant; + } + + switch (tsort) { + case BYTE: return number.byteValue(); + case SHORT: return number.shortValue(); + case CHAR: return (char)number.intValue(); + case INT: return number.intValue(); + case LONG: return number.longValue(); + case FLOAT: return number.floatValue(); + case DOUBLE: return number.doubleValue(); + default: + throw new IllegalStateException("Error" + location + ": Cannot cast from " + + "[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."); + } } else { - final Sort fsort = cast.from.sort; - final Sort tsort = cast.to.sort; - - if (fsort == tsort) { - return constant; - } else if (fsort.numeric && tsort.numeric) { - Number number; - - if (fsort == Sort.CHAR) { - number = (int)(char)constant; - } else { - number = (Number)constant; - } - - switch (tsort) { - case BYTE: return number.byteValue(); - case SHORT: return number.shortValue(); - case CHAR: return (char)number.intValue(); - case INT: return number.intValue(); - case LONG: return number.longValue(); - case FLOAT: return number.floatValue(); - case DOUBLE: return number.doubleValue(); - default: - throw new IllegalStateException("Error" + location + ": Cannot cast from " + - "[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."); - } - } else { - throw new IllegalStateException("Error" + location + ": Cannot cast from " + - "[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."); - } + throw new IllegalStateException("Error" + location + ": Cannot cast from " + + "[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."); } } - private static Object invokeTransform(final String location, final Transform transform, final Object object) { - final Method method = transform.method; - final java.lang.reflect.Method jmethod = method.reflect; - final int modifiers = jmethod.getModifiers(); - - try { - if (java.lang.reflect.Modifier.isStatic(modifiers)) { - return jmethod.invoke(null, object); - } else { - return jmethod.invoke(object); - } - } catch (final IllegalAccessException | IllegalArgumentException | - InvocationTargetException | NullPointerException | ExceptionInInitializerError exception) { - throw new ClassCastException( - "Error" + location + ": Cannot cast from [" + transform.from.name + "] to [" + transform.to.name + "]."); - } - } - - public static Type promoteNumeric(final Definition definition, final Type from, final boolean decimal, final boolean primitive) { + public static Type promoteNumeric(Type from, boolean decimal) { final Sort sort = from.sort; if (sort == Sort.DEF) { - return definition.defType; - } else if ((sort == Sort.DOUBLE || sort == Sort.DOUBLE_OBJ) && decimal) { - return primitive ? definition.doubleType : definition.doubleobjType; - } else if ((sort == Sort.FLOAT || sort == Sort.FLOAT_OBJ) && decimal) { - return primitive ? definition.floatType : definition.floatobjType; - } else if (sort == Sort.LONG || sort == Sort.LONG_OBJ) { - return primitive ? definition.longType : definition.longobjType; - } else if (sort == Sort.INT || sort == Sort.INT_OBJ || - sort == Sort.CHAR || sort == Sort.CHAR_OBJ || - sort == Sort.SHORT || sort == Sort.SHORT_OBJ || - sort == Sort.BYTE || sort == Sort.BYTE_OBJ) { - return primitive ? definition.intType : definition.intobjType; + return Definition.DEF_TYPE; + } else if ((sort == Sort.DOUBLE) && decimal) { + return Definition.DOUBLE_TYPE; + } else if ((sort == Sort.FLOAT) && decimal) { + return Definition.FLOAT_TYPE; + } else if (sort == Sort.LONG) { + return Definition.LONG_TYPE; + } else if (sort == Sort.INT || sort == Sort.CHAR || sort == Sort.SHORT || sort == Sort.BYTE) { + return Definition.INT_TYPE; } return null; } - public static Type promoteNumeric(final Definition definition, - final Type from0, final Type from1, final boolean decimal, final boolean primitive) { + public static Type promoteNumeric(Type from0, Type from1, boolean decimal) { final Sort sort0 = from0.sort; final Sort sort1 = from1.sort; if (sort0 == Sort.DEF || sort1 == Sort.DEF) { - return definition.defType; + return Definition.DEF_TYPE; } if (decimal) { - if (sort0 == Sort.DOUBLE || sort0 == Sort.DOUBLE_OBJ || - sort1 == Sort.DOUBLE || sort1 == Sort.DOUBLE_OBJ) { - return primitive ? definition.doubleType : definition.doubleobjType; - } else if (sort0 == Sort.FLOAT || sort0 == Sort.FLOAT_OBJ || sort1 == Sort.FLOAT || sort1 == Sort.FLOAT_OBJ) { - return primitive ? definition.floatType : definition.floatobjType; + if (sort0 == Sort.DOUBLE || sort1 == Sort.DOUBLE) { + return Definition.DOUBLE_TYPE; + } else if (sort0 == Sort.FLOAT || sort1 == Sort.FLOAT) { + return Definition.FLOAT_TYPE; } } - if (sort0 == Sort.LONG || sort0 == Sort.LONG_OBJ || - sort1 == Sort.LONG || sort1 == Sort.LONG_OBJ) { - return primitive ? definition.longType : definition.longobjType; - } else if (sort0 == Sort.INT || sort0 == Sort.INT_OBJ || - sort1 == Sort.INT || sort1 == Sort.INT_OBJ || - sort0 == Sort.CHAR || sort0 == Sort.CHAR_OBJ || - sort1 == Sort.CHAR || sort1 == Sort.CHAR_OBJ || - sort0 == Sort.SHORT || sort0 == Sort.SHORT_OBJ || - sort1 == Sort.SHORT || sort1 == Sort.SHORT_OBJ || - sort0 == Sort.BYTE || sort0 == Sort.BYTE_OBJ || - sort1 == Sort.BYTE || sort1 == Sort.BYTE_OBJ) { - return primitive ? definition.intType : definition.intobjType; + if (sort0 == Sort.LONG || sort1 == Sort.LONG) { + return Definition.LONG_TYPE; + } else if (sort0 == Sort.INT || sort1 == Sort.INT || + sort0 == Sort.CHAR || sort1 == Sort.CHAR || + sort0 == Sort.SHORT || sort1 == Sort.SHORT || + sort0 == Sort.BYTE || sort1 == Sort.BYTE) { + return Definition.INT_TYPE; } return null; } - public static Type promoteAdd(final Definition definition, final Type from0, final Type from1) { + public static Type promoteAdd(final Type from0, final Type from1) { final Sort sort0 = from0.sort; final Sort sort1 = from1.sort; if (sort0 == Sort.STRING || sort1 == Sort.STRING) { - return definition.stringType; + return Definition.STRING_TYPE; } - return promoteNumeric(definition, from0, from1, true, true); + return promoteNumeric(from0, from1, true); } - public static Type promoteXor(final Definition definition, final Type from0, final Type from1) { + public static Type promoteXor(final Type from0, final Type from1) { final Sort sort0 = from0.sort; final Sort sort1 = from1.sort; if (sort0.bool || sort1.bool) { - return definition.booleanType; + return Definition.BOOLEAN_TYPE; } - return promoteNumeric(definition, from0, from1, false, true); + return promoteNumeric(from0, from1, false); } - public static Type promoteEquality(final Definition definition, final Type from0, final Type from1) { + public static Type promoteEquality(final Type from0, final Type from1) { final Sort sort0 = from0.sort; final Sort sort1 = from1.sort; if (sort0 == Sort.DEF || sort1 == Sort.DEF) { - return definition.defType; - } - - final boolean primitive = sort0.primitive && sort1.primitive; - - if (sort0.bool && sort1.bool) { - return primitive ? definition.booleanType : definition.booleanobjType; - } - - if (sort0.numeric && sort1.numeric) { - return promoteNumeric(definition, from0, from1, true, primitive); - } - - return definition.objectType; - } - - public static Type promoteReference(final Definition definition, final Type from0, final Type from1) { - final Sort sort0 = from0.sort; - final Sort sort1 = from1.sort; - - if (sort0 == Sort.DEF || sort1 == Sort.DEF) { - return definition.defType; + return Definition.DEF_TYPE; } if (sort0.primitive && sort1.primitive) { if (sort0.bool && sort1.bool) { - return definition.booleanType; + return Definition.BOOLEAN_TYPE; } if (sort0.numeric && sort1.numeric) { - return promoteNumeric(definition, from0, from1, true, true); + return promoteNumeric(from0, from1, true); } } - return definition.objectType; + return Definition.OBJECT_TYPE; } - public static Type promoteConditional(final Definition definition, - final Type from0, final Type from1, final Object const0, final Object const1) { + public static Type promoteConditional(final Type from0, final Type from1, final Object const0, final Object const1) { if (from0.equals(from1)) { return from0; } @@ -245,126 +792,124 @@ public final class AnalyzerCaster { final Sort sort1 = from1.sort; if (sort0 == Sort.DEF || sort1 == Sort.DEF) { - return definition.defType; + return Definition.DEF_TYPE; } - final boolean primitive = sort0.primitive && sort1.primitive; + if (sort0.primitive && sort1.primitive) { + if (sort0.bool && sort1.bool) { + return Definition.BOOLEAN_TYPE; + } - if (sort0.bool && sort1.bool) { - return primitive ? definition.booleanType : definition.booleanobjType; - } - - if (sort0.numeric && sort1.numeric) { - if (sort0 == Sort.DOUBLE || sort0 == Sort.DOUBLE_OBJ || sort1 == Sort.DOUBLE || sort1 == Sort.DOUBLE_OBJ) { - return primitive ? definition.doubleType : definition.doubleobjType; - } else if (sort0 == Sort.FLOAT || sort0 == Sort.FLOAT_OBJ || sort1 == Sort.FLOAT || sort1 == Sort.FLOAT_OBJ) { - return primitive ? definition.floatType : definition.floatobjType; - } else if (sort0 == Sort.LONG || sort0 == Sort.LONG_OBJ || sort1 == Sort.LONG || sort1 == Sort.LONG_OBJ) { - return sort0.primitive && sort1.primitive ? definition.longType : definition.longobjType; + if (sort0 == Sort.DOUBLE || sort1 == Sort.DOUBLE) { + return Definition.DOUBLE_TYPE; + } else if (sort0 == Sort.FLOAT || sort1 == Sort.FLOAT) { + return Definition.FLOAT_TYPE; + } else if (sort0 == Sort.LONG || sort1 == Sort.LONG) { + return Definition.LONG_TYPE; } else { - if (sort0 == Sort.BYTE || sort0 == Sort.BYTE_OBJ) { - if (sort1 == Sort.BYTE || sort1 == Sort.BYTE_OBJ) { - return primitive ? definition.byteType : definition.byteobjType; - } else if (sort1 == Sort.SHORT || sort1 == Sort.SHORT_OBJ) { + if (sort0 == Sort.BYTE) { + if (sort1 == Sort.BYTE) { + return Definition.BYTE_TYPE; + } else if (sort1 == Sort.SHORT) { if (const1 != null) { final short constant = (short)const1; if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.shortType : definition.shortobjType; - } else if (sort1 == Sort.CHAR || sort1 == Sort.CHAR_OBJ) { - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.INT || sort1 == Sort.INT_OBJ) { + return Definition.SHORT_TYPE; + } else if (sort1 == Sort.CHAR) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.INT) { if (const1 != null) { final int constant = (int)const1; if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.intType : definition.intobjType; + return Definition.INT_TYPE; } - } else if (sort0 == Sort.SHORT || sort0 == Sort.SHORT_OBJ) { - if (sort1 == Sort.BYTE || sort1 == Sort.BYTE_OBJ) { + } else if (sort0 == Sort.SHORT) { + if (sort1 == Sort.BYTE) { if (const0 != null) { final short constant = (short)const0; if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.shortType : definition.shortobjType; - } else if (sort1 == Sort.SHORT || sort1 == Sort.SHORT_OBJ) { - return primitive ? definition.shortType : definition.shortobjType; - } else if (sort1 == Sort.CHAR || sort1 == Sort.CHAR_OBJ) { - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.INT || sort1 == Sort.INT_OBJ) { + return Definition.SHORT_TYPE; + } else if (sort1 == Sort.SHORT) { + return Definition.SHORT_TYPE; + } else if (sort1 == Sort.CHAR) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.INT) { if (const1 != null) { final int constant = (int)const1; if (constant <= Short.MAX_VALUE && constant >= Short.MIN_VALUE) { - return primitive ? definition.shortType : definition.shortobjType; + return Definition.SHORT_TYPE; } } - return primitive ? definition.intType : definition.intobjType; + return Definition.INT_TYPE; } - } else if (sort0 == Sort.CHAR || sort0 == Sort.CHAR_OBJ) { - if (sort1 == Sort.BYTE || sort1 == Sort.BYTE_OBJ) { - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.SHORT || sort1 == Sort.SHORT_OBJ) { - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.CHAR || sort1 == Sort.CHAR_OBJ) { - return primitive ? definition.charType : definition.charobjType; - } else if (sort1 == Sort.INT || sort1 == Sort.INT_OBJ) { + } else if (sort0 == Sort.CHAR) { + if (sort1 == Sort.BYTE) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.SHORT) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.CHAR) { + return Definition.CHAR_TYPE; + } else if (sort1 == Sort.INT) { if (const1 != null) { final int constant = (int)const1; if (constant <= Character.MAX_VALUE && constant >= Character.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.intType : definition.intobjType; + return Definition.INT_TYPE; } - } else if (sort0 == Sort.INT || sort0 == Sort.INT_OBJ) { - if (sort1 == Sort.BYTE || sort1 == Sort.BYTE_OBJ) { + } else if (sort0 == Sort.INT) { + if (sort1 == Sort.BYTE) { if (const0 != null) { final int constant = (int)const0; if (constant <= Byte.MAX_VALUE && constant >= Byte.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.SHORT || sort1 == Sort.SHORT_OBJ) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.SHORT) { if (const0 != null) { final int constant = (int)const0; if (constant <= Short.MAX_VALUE && constant >= Short.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.CHAR || sort1 == Sort.CHAR_OBJ) { + return Definition.INT_TYPE; + } else if (sort1 == Sort.CHAR) { if (const0 != null) { final int constant = (int)const0; if (constant <= Character.MAX_VALUE && constant >= Character.MIN_VALUE) { - return primitive ? definition.byteType : definition.byteobjType; + return Definition.BYTE_TYPE; } } - return primitive ? definition.intType : definition.intobjType; - } else if (sort1 == Sort.INT || sort1 == Sort.INT_OBJ) { - return primitive ? definition.intType : definition.intobjType; + return Definition.INT_TYPE; + } else if (sort1 == Sort.INT) { + return Definition.INT_TYPE; } } } @@ -374,7 +919,7 @@ public final class AnalyzerCaster { // to calculate the highest upper bound for the two types and return that. // However, for now we just return objectType that may require an extra cast. - return definition.objectType; + return Definition.OBJECT_TYPE; } private AnalyzerCaster() {} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java index c487dddba71..16ad355177f 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java @@ -112,10 +112,10 @@ final class Compiler { } final Reserved reserved = new Reserved(); - final SSource root = Walker.buildPainlessTree(source, reserved); - final Variables variables = Analyzer.analyze(settings, Definition.INSTANCE, reserved, root); + final SSource root = Walker.buildPainlessTree(source, reserved, settings); + final Variables variables = Analyzer.analyze(settings, reserved, root); - return Writer.write(settings, Definition.INSTANCE, name, source, variables, root); + return Writer.write(settings, name, source, variables, root); } /** diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java index 9ec26bf345a..4cafe32bb56 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java @@ -24,47 +24,16 @@ package org.elasticsearch.painless; */ public final class CompilerSettings { - /** - * Constant to be used when specifying numeric overflow when compiling a script. - */ - public static final String NUMERIC_OVERFLOW = "numeric_overflow"; - /** * Constant to be used when specifying the maximum loop counter when compiling a script. */ public static final String MAX_LOOP_COUNTER = "max_loop_counter"; - /** - * Whether or not to allow numeric values to overflow without exception. - */ - private boolean numericOverflow = true; - /** * The maximum number of statements allowed to be run in a loop. */ private int maxLoopCounter = 10000; - /** - * Returns {@code true} if numeric operations should overflow, {@code false} - * if they should signal an exception. - *

- * If this value is {@code true} (default), then things behave like java: - * overflow for integer types can result in unexpected values / unexpected - * signs, and overflow for floating point types can result in infinite or - * {@code NaN} values. - */ - public final boolean getNumericOverflow() { - return numericOverflow; - } - - /** - * Set {@code true} for numerics to overflow, false to deliver exceptions. - * @see #getNumericOverflow - */ - public final void setNumericOverflow(boolean allow) { - this.numericOverflow = allow; - } - /** * Returns the value for the cumulative total number of statements that can be made in all loops * in a script before an exception is thrown. This attempts to prevent infinite loops. Note if diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java index 9226fc3f098..bd8e09f504b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java @@ -52,9 +52,10 @@ public final class Def { // TODO: Once Java has a factory for those in java.lang.invoke.MethodHandles, use it: /** Helper class for isolating MethodHandles and methods to get the length of arrays - * (to emulate a "arraystore" byteoode using MethodHandles). + * (to emulate a "arraystore" bytecode using MethodHandles). * This should really be a method in {@link MethodHandles} class! */ + @SuppressWarnings("unused") // getArrayLength() methods are are actually used, javac just does not know :) private static final class ArrayLengthHelper { private static final Lookup PRIV_LOOKUP = MethodHandles.lookup(); @@ -134,17 +135,16 @@ public final class Def { * @param receiverClass Class of the object to invoke the method on. * @param name Name of the method. * @param type Callsite signature. Need not match exactly, except the number of parameters. - * @param definition Whitelist to check. * @return pointer to matching method to invoke. never returns null. * @throws IllegalArgumentException if no matching whitelisted method was found. */ - static MethodHandle lookupMethod(Class receiverClass, String name, MethodType type, Definition definition) { + static MethodHandle lookupMethod(Class receiverClass, String name, MethodType type) { // we don't consider receiver an argument/counting towards arity type = type.dropParameterTypes(0, 1); Definition.MethodKey key = new Definition.MethodKey(name, type.parameterCount()); // check whitelist for matching method for (Class clazz = receiverClass; clazz != null; clazz = clazz.getSuperclass()) { - RuntimeClass struct = definition.runtimeMap.get(clazz); + RuntimeClass struct = Definition.getRuntimeClass(clazz); if (struct != null) { Method method = struct.methods.get(key); @@ -154,7 +154,7 @@ public final class Def { } for (final Class iface : clazz.getInterfaces()) { - struct = definition.runtimeMap.get(iface); + struct = Definition.getRuntimeClass(iface); if (struct != null) { Method method = struct.methods.get(key); @@ -192,14 +192,13 @@ public final class Def { *

* @param receiverClass Class of the object to retrieve the field from. * @param name Name of the field. - * @param definition Whitelist to check. * @return pointer to matching field. never returns null. * @throws IllegalArgumentException if no matching whitelisted field was found. */ - static MethodHandle lookupGetter(Class receiverClass, String name, Definition definition) { + static MethodHandle lookupGetter(Class receiverClass, String name) { // first try whitelist for (Class clazz = receiverClass; clazz != null; clazz = clazz.getSuperclass()) { - RuntimeClass struct = definition.runtimeMap.get(clazz); + RuntimeClass struct = Definition.getRuntimeClass(clazz); if (struct != null) { MethodHandle handle = struct.getters.get(name); @@ -209,7 +208,7 @@ public final class Def { } for (final Class iface : clazz.getInterfaces()) { - struct = definition.runtimeMap.get(iface); + struct = Definition.getRuntimeClass(iface); if (struct != null) { MethodHandle handle = struct.getters.get(name); @@ -263,14 +262,13 @@ public final class Def { *

* @param receiverClass Class of the object to retrieve the field from. * @param name Name of the field. - * @param definition Whitelist to check. * @return pointer to matching field. never returns null. * @throws IllegalArgumentException if no matching whitelisted field was found. */ - static MethodHandle lookupSetter(Class receiverClass, String name, Definition definition) { + static MethodHandle lookupSetter(Class receiverClass, String name) { // first try whitelist for (Class clazz = receiverClass; clazz != null; clazz = clazz.getSuperclass()) { - RuntimeClass struct = definition.runtimeMap.get(clazz); + RuntimeClass struct = Definition.getRuntimeClass(clazz); if (struct != null) { MethodHandle handle = struct.setters.get(name); @@ -280,7 +278,7 @@ public final class Def { } for (final Class iface : clazz.getInterfaces()) { - struct = definition.runtimeMap.get(iface); + struct = Definition.getRuntimeClass(iface); if (struct != null) { MethodHandle handle = struct.setters.get(name); @@ -971,6 +969,10 @@ public final class Def { // Conversion methods for Def to primitive types. + public static boolean DefToboolean(final Object value) { + return (boolean)value; + } + public static byte DefTobyteImplicit(final Object value) { return (byte)value; } @@ -1051,79 +1053,6 @@ public final class Def { } } - public static Byte DefToByteImplicit(final Object value) { - return (Byte)value; - } - - public static Short DefToShortImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte) { - return ((Byte)value).shortValue(); - } else { - return (Short)value; - } - } - - public static Character DefToCharacterImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte) { - return (char)(byte)value; - } else { - return (Character)value; - } - } - - public static Integer DefToIntegerImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte || value instanceof Short) { - return ((Number)value).intValue(); - } else if (value instanceof Character) { - return (int)(char)value; - } else { - return (Integer)value; - } - } - - public static Long DefToLongImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte || value instanceof Short || value instanceof Integer) { - return ((Number)value).longValue(); - } else if (value instanceof Character) { - return (long)(char)value; - } else { - return (Long)value; - } - } - - public static Float DefToFloatImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) { - return ((Number)value).floatValue(); - } else if (value instanceof Character) { - return (float)(char)value; - } else { - return (Float)value; - } - } - - public static Double DefToDoubleImplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Byte || value instanceof Short || - value instanceof Integer || value instanceof Long || value instanceof Float) { - return ((Number)value).doubleValue(); - } else if (value instanceof Character) { - return (double)(char)value; - } else { - return (Double)value; - } - } - public static byte DefTobyteExplicit(final Object value) { if (value instanceof Character) { return (byte)(char)value; @@ -1179,74 +1108,4 @@ public final class Def { return ((Number)value).doubleValue(); } } - - public static Byte DefToByteExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (byte)(char)value; - } else { - return ((Number)value).byteValue(); - } - } - - public static Short DefToShortExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (short)(char)value; - } else { - return ((Number)value).shortValue(); - } - } - - public static Character DefToCharacterExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return ((Character)value); - } else { - return (char)((Number)value).intValue(); - } - } - - public static Integer DefToIntegerExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (int)(char)value; - } else { - return ((Number)value).intValue(); - } - } - - public static Long DefToLongExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (long)(char)value; - } else { - return ((Number)value).longValue(); - } - } - - public static Float DefToFloatExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (float)(char)value; - } else { - return ((Number)value).floatValue(); - } - } - - public static Double DefToDoubleExplicit(final Object value) { - if (value == null) { - return null; - } else if (value instanceof Character) { - return (double)(char)value; - } else { - return ((Number)value).doubleValue(); - } - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java index 380f5455ab3..40b9cc6cbe8 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java @@ -94,11 +94,11 @@ public final class DefBootstrap { private static MethodHandle lookup(int flavor, Class clazz, String name, MethodType type) { switch(flavor) { case METHOD_CALL: - return Def.lookupMethod(clazz, name, type, Definition.INSTANCE); + return Def.lookupMethod(clazz, name, type); case LOAD: - return Def.lookupGetter(clazz, name, Definition.INSTANCE); + return Def.lookupGetter(clazz, name); case STORE: - return Def.lookupSetter(clazz, name, Definition.INSTANCE); + return Def.lookupSetter(clazz, name); case ARRAY_LOAD: return Def.lookupArrayLoad(clazz); case ARRAY_STORE: 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 f44db5cb504..05c12c30239 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 @@ -19,34 +19,51 @@ package org.elasticsearch.painless; -import org.elasticsearch.common.geo.GeoPoint; -import org.elasticsearch.index.fielddata.ScriptDocValues; - +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import java.util.ArrayList; +import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; /** * The entire API for Painless. Also used as a whitelist for checking for legal * methods and fields during at both compile-time and runtime. */ public final class Definition { + + private static final String DEFINITION_FILE = "definition.txt"; - /** - * The default language API to be used with Painless. The second construction is used - * to finalize all the variables, so there is no mistake of modification afterwards. - */ - static Definition INSTANCE = new Definition(new Definition()); + private static final Definition INSTANCE = new Definition(); + + /** Some native types as constants: */ + public static final Type VOID_TYPE = getType("void"); + public static final Type BOOLEAN_TYPE = getType("boolean"); + public static final Type BOOLEAN_OBJ_TYPE = getType("Boolean"); + public static final Type BYTE_TYPE = getType("byte"); + public static final Type BYTE_OBJ_TYPE = getType("Byte"); + public static final Type SHORT_TYPE = getType("short"); + public static final Type SHORT_OBJ_TYPE = getType("Short"); + public static final Type INT_TYPE = getType("int"); + public static final Type INT_OBJ_TYPE = getType("Integer"); + public static final Type LONG_TYPE = getType("long"); + public static final Type LONG_OBJ_TYPE = getType("Long"); + public static final Type FLOAT_TYPE = getType("float"); + public static final Type FLOAT_OBJ_TYPE = getType("Float"); + public static final Type DOUBLE_TYPE = getType("double"); + public static final Type DOUBLE_OBJ_TYPE = getType("Double"); + public static final Type CHAR_TYPE = getType("char"); + public static final Type CHAR_OBJ_TYPE = getType("Character"); + public static final Type OBJECT_TYPE = getType("Object"); + public static final Type DEF_TYPE = getType("def"); + public static final Type STRING_TYPE = getType("String"); + public static final Type EXCEPTION_TYPE = getType("Exception"); public enum Sort { VOID( void.class , 0 , true , false , false , false ), @@ -178,17 +195,15 @@ public final class Definition { public static final class Field { public final String name; public final Struct owner; - public final Type generic; public final Type type; public final java.lang.reflect.Field reflect; public final MethodHandle getter; public final MethodHandle setter; - private Field(final String name, final Struct owner, final Type generic, final Type type, + private Field(final String name, final Struct owner, final Type type, final java.lang.reflect.Field reflect, final MethodHandle getter, final MethodHandle setter) { this.name = name; this.owner = owner; - this.generic = generic; this.type = type; this.reflect = reflect; this.getter = getter; @@ -275,7 +290,7 @@ public final class Definition { staticMembers = new HashMap<>(); members = new HashMap<>(); } - + private Struct(final Struct struct) { name = struct.name; clazz = struct.clazz; @@ -289,6 +304,10 @@ public final class Definition { members = Collections.unmodifiableMap(struct.members); } + private Struct freeze() { + return new Struct(this); + } + @Override public boolean equals(Object object) { if (this == object) { @@ -314,50 +333,32 @@ public final class Definition { public final Type from; public final Type to; public final boolean explicit; + public final boolean unboxFrom; + public final boolean unboxTo; + public final boolean boxFrom; + public final boolean boxTo; public Cast(final Type from, final Type to, final boolean explicit) { this.from = from; this.to = to; this.explicit = explicit; + this.unboxFrom = false; + this.unboxTo = false; + this.boxFrom = false; + this.boxTo = false; } - @Override - public boolean equals(final Object object) { - if (this == object) { - return true; - } - - if (object == null || getClass() != object.getClass()) { - return false; - } - - final Cast cast = (Cast)object; - - return from.equals(cast.from) && to.equals(cast.to) && explicit == cast.explicit; + public Cast(final Type from, final Type to, final boolean explicit, + final boolean unboxFrom, final boolean unboxTo, final boolean boxFrom, final boolean boxTo) { + this.from = from; + this.to = to; + this.explicit = explicit; + this.unboxFrom = unboxFrom; + this.unboxTo = unboxTo; + this.boxFrom = boxFrom; + this.boxTo = boxTo; } - @Override - public int hashCode() { - int result = from.hashCode(); - result = 31 * result + to.hashCode(); - result = 31 * result + (explicit ? 1 : 0); - - return result; - } - } - - public static final class Transform extends Cast { - public final Method method; - public final Type upcast; - public final Type downcast; - - public Transform(final Cast cast, Method method, final Type upcast, final Type downcast) { - super(cast.from, cast.to, cast.explicit); - - this.method = method; - this.upcast = upcast; - this.downcast = downcast; - } } public static final class RuntimeClass { @@ -367,1224 +368,150 @@ public final class Definition { private RuntimeClass(final Map methods, final Map getters, final Map setters) { - this.methods = methods; - this.getters = getters; - this.setters = setters; + this.methods = Collections.unmodifiableMap(methods); + this.getters = Collections.unmodifiableMap(getters); + this.setters = Collections.unmodifiableMap(setters); } } - public final Map structsMap; - public final Map transformsMap; - public final Map, RuntimeClass> runtimeMap; + /** Gets the type given by its name */ + public static Type getType(final String name) { + return INSTANCE.getTypeInternal(name); + } - public final Type voidType; - public final Type booleanType; - public final Type byteType; - public final Type shortType; - public final Type charType; - public final Type intType; - public final Type longType; - public final Type floatType; - public final Type doubleType; - - public final Type voidobjType; - public final Type booleanobjType; - public final Type byteobjType; - public final Type shortobjType; - public final Type charobjType; - public final Type intobjType; - public final Type longobjType; - public final Type floatobjType; - public final Type doubleobjType; - - public final Type objectType; - public final Type defType; - public final Type numberType; - public final Type charseqType; - public final Type stringType; - public final Type mathType; - public final Type utilityType; - public final Type defobjType; - - public final Type itrType; - public final Type oitrType; - public final Type sitrType; - - public final Type collectionType; - public final Type ocollectionType; - public final Type scollectionType; - - public final Type listType; - public final Type arraylistType; - public final Type olistType; - public final Type oarraylistType; - public final Type slistType; - public final Type sarraylistType; - - public final Type setType; - public final Type hashsetType; - public final Type osetType; - public final Type ohashsetType; - public final Type ssetType; - public final Type shashsetType; - - public final Type mapType; - public final Type hashmapType; - public final Type oomapType; - public final Type oohashmapType; - public final Type smapType; - public final Type shashmapType; - public final Type somapType; - public final Type sohashmapType; - - public final Type execType; - - public final Type exceptionType; - public final Type arithexcepType; - public final Type iargexcepType; - public final Type istateexceptType; - public final Type nfexcepType; - - // docvalues accessors - public final Type geoPointType; - public final Type stringsType; - // TODO: add ReadableDateTime? or don't expose the joda stuff? - public final Type longsType; - public final Type doublesType; - public final Type geoPointsType; - - // for testing features not currently "used" by the whitelist (we should not rush the API for that!) - public final Type featureTestType; + /** Creates an array type from the given Struct. */ + public static Type getType(final Struct struct, final int dimensions) { + return INSTANCE.getTypeInternal(struct, dimensions); + } + + public static RuntimeClass getRuntimeClass(Class clazz) { + return INSTANCE.runtimeMap.get(clazz); + } + + // INTERNAL IMPLEMENTATION: + + private final Map, RuntimeClass> runtimeMap; + private final Map structsMap; + private final Map simpleTypesMap; private Definition() { structsMap = new HashMap<>(); - transformsMap = new HashMap<>(); + simpleTypesMap = new HashMap<>(); runtimeMap = new HashMap<>(); - addStructs(); - - voidType = getType("void"); - booleanType = getType("boolean"); - byteType = getType("byte"); - shortType = getType("short"); - charType = getType("char"); - intType = getType("int"); - longType = getType("long"); - floatType = getType("float"); - doubleType = getType("double"); - - voidobjType = getType("Void"); - booleanobjType = getType("Boolean"); - byteobjType = getType("Byte"); - shortobjType = getType("Short"); - charobjType = getType("Character"); - intobjType = getType("Integer"); - longobjType = getType("Long"); - floatobjType = getType("Float"); - doubleobjType = getType("Double"); - - objectType = getType("Object"); - defType = getType("def"); - numberType = getType("Number"); - charseqType = getType("CharSequence"); - stringType = getType("String"); - mathType = getType("Math"); - utilityType = getType("Utility"); - defobjType = getType("Def"); - - itrType = getType("Iterator"); - oitrType = getType("Iterator"); - sitrType = getType("Iterator"); - - collectionType = getType("Collection"); - ocollectionType = getType("Collection"); - scollectionType = getType("Collection"); - - listType = getType("List"); - arraylistType = getType("ArrayList"); - olistType = getType("List"); - oarraylistType = getType("ArrayList"); - slistType = getType("List"); - sarraylistType = getType("ArrayList"); - - setType = getType("Set"); - hashsetType = getType("HashSet"); - osetType = getType("Set"); - ohashsetType = getType("HashSet"); - ssetType = getType("Set"); - shashsetType = getType("HashSet"); - - mapType = getType("Map"); - hashmapType = getType("HashMap"); - oomapType = getType("Map"); - oohashmapType = getType("HashMap"); - smapType = getType("Map"); - shashmapType = getType("HashMap"); - somapType = getType("Map"); - sohashmapType = getType("HashMap"); - - execType = getType("Executable"); - - exceptionType = getType("Exception"); - arithexcepType = getType("ArithmeticException"); - iargexcepType = getType("IllegalArgumentException"); - istateexceptType = getType("IllegalStateException"); - nfexcepType = getType("NumberFormatException"); - - geoPointType = getType("GeoPoint"); - stringsType = getType("Strings"); - longsType = getType("Longs"); - doublesType = getType("Doubles"); - geoPointsType = getType("GeoPoints"); - - featureTestType = getType("FeatureTest"); - + // parse the classes and return hierarchy (map of class name -> superclasses/interfaces) + Map> hierarchy = addStructs(); + // add every method for each class addElements(); - copyStructs(); - addTransforms(); - addRuntimeClasses(); - } - - private Definition(final Definition definition) { - final Map structs = new HashMap<>(); - - for (final Struct struct : definition.structsMap.values()) { - structs.put(struct.name, new Struct(struct)); + // apply hierarchy: this means e.g. copying Object's methods into String (thats how subclasses work) + for (Map.Entry> clazz : hierarchy.entrySet()) { + copyStruct(clazz.getKey(), clazz.getValue()); + } + // precompute runtime classes + for (Struct struct : structsMap.values()) { + addRuntimeClass(struct); + } + // copy all structs to make them unmodifiable for outside users: + for (final Map.Entry entry : structsMap.entrySet()) { + entry.setValue(entry.getValue().freeze()); } - - this.structsMap = Collections.unmodifiableMap(structs); - this.transformsMap = Collections.unmodifiableMap(definition.transformsMap); - this.runtimeMap = Collections.unmodifiableMap(definition.runtimeMap); - - this.voidType = definition.voidType; - this.booleanType = definition.booleanType; - this.byteType = definition.byteType; - this.shortType = definition.shortType; - this.charType = definition.charType; - this.intType = definition.intType; - this.longType = definition.longType; - this.floatType = definition.floatType; - this.doubleType = definition.doubleType; - - this.voidobjType = definition.voidobjType; - this.booleanobjType = definition.booleanobjType; - this.byteobjType = definition.byteobjType; - this.shortobjType = definition.shortobjType; - this.charobjType = definition.charobjType; - this.intobjType = definition.intobjType; - this.longobjType = definition.longobjType; - this.floatobjType = definition.floatobjType; - this.doubleobjType = definition.doubleobjType; - - this.objectType = definition.objectType; - this.defType = definition.defType; - this.numberType = definition.numberType; - this.charseqType = definition.charseqType; - this.stringType = definition.stringType; - this.mathType = definition.mathType; - this.utilityType = definition.utilityType; - this.defobjType = definition.defobjType; - - this.itrType = definition.itrType; - this.oitrType = definition.oitrType; - this.sitrType = definition.sitrType; - - this.collectionType = definition.collectionType; - this.ocollectionType = definition.ocollectionType; - this.scollectionType = definition.scollectionType; - - this.listType = definition.listType; - this.arraylistType = definition.arraylistType; - this.olistType = definition.olistType; - this.oarraylistType = definition.oarraylistType; - this.slistType = definition.slistType; - this.sarraylistType = definition.sarraylistType; - - this.setType = definition.setType; - this.hashsetType = definition.hashsetType; - this.osetType = definition.osetType; - this.ohashsetType = definition.ohashsetType; - this.ssetType = definition.ssetType; - this.shashsetType = definition.shashsetType; - - this.mapType = definition.mapType; - this.hashmapType = definition.hashmapType; - this.oomapType = definition.oomapType; - this.oohashmapType = definition.oohashmapType; - this.smapType = definition.smapType; - this.shashmapType = definition.shashmapType; - this.somapType = definition.somapType; - this.sohashmapType = definition.sohashmapType; - - this.execType = definition.execType; - - this.exceptionType = definition.exceptionType; - this.arithexcepType = definition.arithexcepType; - this.iargexcepType = definition.iargexcepType; - this.istateexceptType = definition.istateexceptType; - this.nfexcepType = definition.nfexcepType; - - this.geoPointType = definition.geoPointType; - this.stringsType = definition.stringsType; - this.longsType = definition.longsType; - this.doublesType = definition.doublesType; - this.geoPointsType = definition.geoPointsType; - - this.featureTestType = definition.featureTestType; } - private void addStructs() { - addStruct( "void" , void.class ); - addStruct( "boolean" , boolean.class ); - addStruct( "byte" , byte.class ); - addStruct( "short" , short.class ); - addStruct( "char" , char.class ); - addStruct( "int" , int.class ); - addStruct( "long" , long.class ); - addStruct( "float" , float.class ); - addStruct( "double" , double.class ); - - addStruct( "Void" , Void.class ); - addStruct( "Boolean" , Boolean.class ); - addStruct( "Byte" , Byte.class ); - addStruct( "Short" , Short.class ); - addStruct( "Character" , Character.class ); - addStruct( "Integer" , Integer.class ); - addStruct( "Long" , Long.class ); - addStruct( "Float" , Float.class ); - addStruct( "Double" , Double.class ); - - addStruct( "Object" , Object.class ); - addStruct( "def" , Object.class ); - addStruct( "Number" , Number.class ); - addStruct( "CharSequence" , CharSequence.class ); - addStruct( "String" , String.class ); - addStruct( "Math" , Math.class ); - addStruct( "Utility" , Utility.class ); - addStruct( "Def" , Def.class ); - - addStruct( "Iterator" , Iterator.class ); - addStruct( "Iterator" , Iterator.class ); - addStruct( "Iterator" , Iterator.class ); - - addStruct( "Collection" , Collection.class ); - addStruct( "Collection" , Collection.class ); - addStruct( "Collection" , Collection.class ); - - addStruct( "List" , List.class ); - addStruct( "ArrayList" , ArrayList.class ); - addStruct( "List" , List.class ); - addStruct( "ArrayList" , ArrayList.class ); - addStruct( "List" , List.class ); - addStruct( "ArrayList" , ArrayList.class ); - - addStruct( "Set" , Set.class ); - addStruct( "HashSet" , HashSet.class ); - addStruct( "Set" , Set.class ); - addStruct( "HashSet" , HashSet.class ); - addStruct( "Set" , Set.class ); - addStruct( "HashSet" , HashSet.class ); - - addStruct( "Map" , Map.class ); - addStruct( "HashMap" , HashMap.class ); - addStruct( "Map" , Map.class ); - addStruct( "HashMap" , HashMap.class ); - addStruct( "Map" , Map.class ); - addStruct( "HashMap" , HashMap.class ); - addStruct( "Map" , Map.class ); - addStruct( "HashMap" , HashMap.class ); - - addStruct( "Executable" , Executable.class ); - - addStruct( "Exception" , Exception.class); - addStruct( "ArithmeticException" , ArithmeticException.class); - addStruct( "IllegalArgumentException" , IllegalArgumentException.class); - addStruct( "IllegalStateException" , IllegalStateException.class); - addStruct( "NumberFormatException" , NumberFormatException.class); - - addStruct( "GeoPoint" , GeoPoint.class); - addStruct( "Strings" , ScriptDocValues.Strings.class); - addStruct( "Longs" , ScriptDocValues.Longs.class); - addStruct( "Doubles" , ScriptDocValues.Doubles.class); - addStruct( "GeoPoints" , ScriptDocValues.GeoPoints.class); - - addStruct( "FeatureTest", FeatureTest.class); + /** adds classes from definition. returns hierarchy */ + private Map> addStructs() { + final Map> hierarchy = new HashMap<>(); + int currentLine = -1; + try { + try (InputStream stream = Definition.class.getResourceAsStream(DEFINITION_FILE); + LineNumberReader reader = new LineNumberReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + String line = null; + while ((line = reader.readLine()) != null) { + currentLine = reader.getLineNumber(); + line = line.trim(); + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + if (line.startsWith("class ")) { + String elements[] = line.split("\u0020"); + assert elements[2].equals("->"); + if (elements.length == 7) { + hierarchy.put(elements[1], Arrays.asList(elements[5].split(","))); + } else { + assert elements.length == 5; + } + String className = elements[1]; + String javaPeer = elements[3]; + final Class javaClazz; + switch (javaPeer) { + case "void": + javaClazz = void.class; + break; + case "boolean": + javaClazz = boolean.class; + break; + case "byte": + javaClazz = byte.class; + break; + case "short": + javaClazz = short.class; + break; + case "char": + javaClazz = char.class; + break; + case "int": + javaClazz = int.class; + break; + case "long": + javaClazz = long.class; + break; + case "float": + javaClazz = float.class; + break; + case "double": + javaClazz = double.class; + break; + default: + javaClazz = Class.forName(javaPeer); + break; + } + addStruct(className, javaClazz); + } + } + } + } catch (Exception e) { + throw new RuntimeException("syntax error in definition line: " + currentLine, e); + } + return hierarchy; } + /** adds class methods/fields/ctors */ private void addElements() { - addMethod("Object", "equals", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Object", "hashCode", null, false, intType, new Type[] {}, null, null); - addMethod("Object", "toString", null, false, stringType, new Type[] {}, null, null); - - addMethod("def", "equals", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("def", "hashCode", null, false, intType, new Type[] {}, null, null); - addMethod("def", "toString", null, false, stringType, new Type[] {}, null, null); - - addConstructor("Boolean", "new", new Type[] {booleanType}, null); - addMethod("Boolean", "booleanValue", null, false, booleanType, new Type[] {}, null, null); - addMethod("Boolean", "compare", null, true, intType, new Type[] {booleanType,booleanType}, null, null); - addMethod("Boolean", "compareTo", null, false, intType, new Type[] {booleanobjType}, null, null); - addMethod("Boolean", "parseBoolean", null, true, booleanType, new Type[] {stringType}, null, null); - addMethod("Boolean", "valueOf", null, true, booleanobjType, new Type[] {booleanType}, null, null); - addField("Boolean", "FALSE", null, true, booleanobjType, null); - addField("Boolean", "TRUE", null, true, booleanobjType, null); - - addConstructor("Byte", "new", new Type[] {byteType}, null); - addMethod("Byte", "compare", null, true, intType, new Type[] {byteType,byteType}, null, null); - addMethod("Byte", "compareTo", null, false, intType, new Type[] {byteobjType}, null, null); - addMethod("Byte", "parseByte", null, true, byteType, new Type[] {stringType}, null, null); - addMethod("Byte", "valueOf", null, true, byteobjType, new Type[] {byteType}, null, null); - addField("Byte", "MIN_VALUE", null, true, byteType, null); - addField("Byte", "MAX_VALUE", null, true, byteType, null); - - addConstructor("Short", "new", new Type[] {shortType}, null); - addMethod("Short", "compare", null, true, intType, new Type[] {shortType,shortType}, null, null); - addMethod("Short", "compareTo", null, false, intType, new Type[] {shortobjType}, null, null); - addMethod("Short", "parseShort", null, true, shortType, new Type[] {stringType}, null, null); - addMethod("Short", "valueOf", null, true, shortobjType, new Type[] {shortType}, null, null); - addField("Short", "MIN_VALUE", null, true, shortType, null); - addField("Short", "MAX_VALUE", null, true, shortType, null); - - addConstructor("Character", "new", new Type[] {charType}, null); - addMethod("Character", "charCount", null, true, intType, new Type[] {intType}, null, null); - addMethod("Character", "charValue", null, false, charType, new Type[] {}, null, null); - addMethod("Character", "compare", null, true, intType, new Type[] {charType,charType}, null, null); - addMethod("Character", "compareTo", null, false, intType, new Type[] {charobjType}, null, null); - addMethod("Character", "digit", null, true, intType, new Type[] {intType,intType}, null, null); - addMethod("Character", "forDigit", null, true, charType, new Type[] {intType,intType}, null, null); - addMethod("Character", "getName", null, true, stringType, new Type[] {intType}, null, null); - addMethod("Character", "getNumericValue", null, true, intType, new Type[] {intType}, null, null); - addMethod("Character", "isAlphabetic", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isDefined", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isDigit", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isIdeographic", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isLetter", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isLetterOrDigit", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isLowerCase", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isMirrored", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isSpaceChar", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isTitleCase", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isUpperCase", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "isWhitespace", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Character", "valueOf", null, true, charobjType, new Type[] {charType}, null, null); - addField("Character", "MIN_VALUE", null, true, charType, null); - addField("Character", "MAX_VALUE", null, true, charType, null); - - addConstructor("Integer", "new", new Type[] {intType}, null); - addMethod("Integer", "compare", null, true, intType, new Type[] {intType,intType}, null, null); - addMethod("Integer", "compareTo", null, false, intType, new Type[] {intobjType}, null, null); - addMethod("Integer", "min", null, true, intType, new Type[] {intType,intType}, null, null); - addMethod("Integer", "max", null, true, intType, new Type[] {intType,intType}, null, null); - addMethod("Integer", "parseInt", null, true, intType, new Type[] {stringType}, null, null); - addMethod("Integer", "signum", null, true, intType, new Type[] {intType}, null, null); - addMethod("Integer", "toHexString", null, true, stringType, new Type[] {intType}, null, null); - addMethod("Integer", "valueOf", null, true, intobjType, new Type[] {intType}, null, null); - addField("Integer", "MIN_VALUE", null, true, intType, null); - addField("Integer", "MAX_VALUE", null, true, intType, null); - - addConstructor("Long", "new", new Type[] {longType}, null); - addMethod("Long", "compare", null, true, intType, new Type[] {longType,longType}, null, null); - addMethod("Long", "compareTo", null, false, intType, new Type[] {longobjType}, null, null); - addMethod("Long", "min", null, true, longType, new Type[] {longType,longType}, null, null); - addMethod("Long", "max", null, true, longType, new Type[] {longType,longType}, null, null); - addMethod("Long", "parseLong", null, true, longType, new Type[] {stringType}, null, null); - addMethod("Long", "signum", null, true, intType, new Type[] {longType}, null, null); - addMethod("Long", "toHexString", null, true, stringType, new Type[] {longType}, null, null); - addMethod("Long", "valueOf", null, true, longobjType, new Type[] {longType}, null, null); - addField("Long", "MIN_VALUE", null, true, longType, null); - addField("Long", "MAX_VALUE", null, true, longType, null); - - addConstructor("Float", "new", new Type[] {floatType}, null); - addMethod("Float", "compare", null, true, intType, new Type[] {floatType,floatType}, null, null); - addMethod("Float", "compareTo", null, false, intType, new Type[] {floatobjType}, null, null); - addMethod("Float", "min", null, true, floatType, new Type[] {floatType,floatType}, null, null); - addMethod("Float", "max", null, true, floatType, new Type[] {floatType,floatType}, null, null); - addMethod("Float", "parseFloat", null, true, floatType, new Type[] {stringType}, null, null); - addMethod("Float", "toHexString", null, true, stringType, new Type[] {floatType}, null, null); - addMethod("Float", "valueOf", null, true, floatobjType, new Type[] {floatType}, null, null); - addField("Float", "MIN_VALUE", null, true, floatType, null); - addField("Float", "MAX_VALUE", null, true, floatType, null); - - addConstructor("Double", "new", new Type[] {doubleType}, null); - addMethod("Double", "compare", null, true, intType, new Type[] {doubleType,doubleType}, null, null); - addMethod("Double", "compareTo", null, false, intType, new Type[] {doubleobjType}, null, null); - addMethod("Double", "min", null, true, doubleType, new Type[] {doubleType,doubleType}, null, null); - addMethod("Double", "max", null, true, doubleType, new Type[] {doubleType,doubleType}, null, null); - addMethod("Double", "parseDouble", null, true, doubleType, new Type[] {stringType}, null, null); - addMethod("Double", "toHexString", null, true, stringType, new Type[] {doubleType}, null, null); - addMethod("Double", "valueOf", null, true, doubleobjType, new Type[] {doubleType}, null, null); - addField("Double", "MIN_VALUE", null, true, doubleType, null); - addField("Double", "MAX_VALUE", null, true, doubleType, null); - - addMethod("Number", "byteValue", null, false, byteType, new Type[] {}, null, null); - addMethod("Number", "shortValue", null, false, shortType, new Type[] {}, null, null); - addMethod("Number", "intValue", null, false, intType, new Type[] {}, null, null); - addMethod("Number", "longValue", null, false, longType, new Type[] {}, null, null); - addMethod("Number", "floatValue", null, false, floatType, new Type[] {}, null, null); - addMethod("Number", "doubleValue", null, false, doubleType, new Type[] {}, null, null); - - addMethod("CharSequence", "charAt", null, false, charType, new Type[] {intType}, null, null); - addMethod("CharSequence", "length", null, false, intType, new Type[] {}, null, null); - - addConstructor("String", "new", new Type[] {}, null); - addMethod("String", "codePointAt", null, false, intType, new Type[] {intType}, null, null); - addMethod("String", "compareTo", null, false, intType, new Type[] {stringType}, null, null); - addMethod("String", "concat", null, false, stringType, new Type[] {stringType}, null, null); - addMethod("String", "endsWith", null, false, booleanType, new Type[] {stringType}, null, null); - addMethod("String", "indexOf", null, false, intType, new Type[] {stringType}, null, null); - addMethod("String", "indexOf", null, false, intType, new Type[] {stringType, intType}, null, null); - addMethod("String", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("String", "replace", null, false, stringType, new Type[] {charseqType, charseqType}, null, null); - addMethod("String", "startsWith", null, false, booleanType, new Type[] {stringType}, null, null); - addMethod("String", "substring", null, false, stringType, new Type[] {intType, intType}, null, null); - addMethod("String", "toCharArray", null, false, getType(charType.struct, 1), new Type[] {}, null, null); - addMethod("String", "trim", null, false, stringType, new Type[] {}, null, null); - - addMethod("Utility", "NumberToboolean", null, true, booleanType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberTochar", null, true, charType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToBoolean", null, true, booleanobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToByte", null, true, byteobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToShort", null, true, shortobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToCharacter", null, true, charobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToInteger", null, true, intobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToLong", null, true, longobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToFloat", null, true, floatobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "NumberToDouble", null, true, doubleobjType, new Type[] {numberType}, null, null); - addMethod("Utility", "booleanTobyte", null, true, byteType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanToshort", null, true, shortType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanTochar", null, true, charType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanToint", null, true, intType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanTolong", null, true, longType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanTofloat", null, true, floatType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanTodouble", null, true, doubleType, new Type[] {booleanType}, null, null); - addMethod("Utility", "booleanToInteger", null, true, intobjType, new Type[] {booleanType}, null, null); - addMethod("Utility", "BooleanTobyte", null, true, byteType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToshort", null, true, shortType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanTochar", null, true, charType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToint", null, true, intType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanTolong", null, true, longType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanTofloat", null, true, floatType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanTodouble", null, true, doubleType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToByte", null, true, byteobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToShort", null, true, shortobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToCharacter", null, true, charobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToInteger", null, true, intobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToLong", null, true, longobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToFloat", null, true, floatobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "BooleanToDouble", null, true, doubleobjType, new Type[] {booleanobjType}, null, null); - addMethod("Utility", "byteToboolean", null, true, booleanType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToShort", null, true, shortobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToCharacter", null, true, charobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToInteger", null, true, intobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToLong", null, true, longobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToFloat", null, true, floatobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "byteToDouble", null, true, doubleobjType, new Type[] {byteType}, null, null); - addMethod("Utility", "ByteToboolean", null, true, booleanType, new Type[] {byteobjType}, null, null); - addMethod("Utility", "ByteTochar", null, true, charType, new Type[] {byteobjType}, null, null); - addMethod("Utility", "shortToboolean", null, true, booleanType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToByte", null, true, byteobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToCharacter", null, true, charobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToInteger", null, true, intobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToLong", null, true, longobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToFloat", null, true, floatobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "shortToDouble", null, true, doubleobjType, new Type[] {shortType}, null, null); - addMethod("Utility", "ShortToboolean", null, true, booleanType, new Type[] {shortobjType}, null, null); - addMethod("Utility", "ShortTochar", null, true, charType, new Type[] {shortobjType}, null, null); - addMethod("Utility", "charToboolean", null, true, booleanType, new Type[] {charType}, null, null); - addMethod("Utility", "charToByte", null, true, byteobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToShort", null, true, shortobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToInteger", null, true, intobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToLong", null, true, longobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToFloat", null, true, floatobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToDouble", null, true, doubleobjType, new Type[] {charType}, null, null); - addMethod("Utility", "charToString", null, true, stringType, new Type[] {charType}, null, null); - addMethod("Utility", "CharacterToboolean", null, true, booleanType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterTobyte", null, true, byteType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToshort", null, true, shortType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToint", null, true, intType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterTolong", null, true, longType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterTofloat", null, true, floatType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterTodouble", null, true, doubleType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToBoolean", null, true, booleanobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToByte", null, true, byteobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToShort", null, true, shortobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToInteger", null, true, intobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToLong", null, true, longobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToFloat", null, true, floatobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToDouble", null, true, doubleobjType, new Type[] {charobjType}, null, null); - addMethod("Utility", "CharacterToString", null, true, stringType, new Type[] {charobjType}, null, null); - addMethod("Utility", "intToboolean", null, true, booleanType, new Type[] {intType}, null, null); - addMethod("Utility", "intToByte", null, true, byteobjType, new Type[] {intType}, null, null); - addMethod("Utility", "intToShort", null, true, shortobjType, new Type[] {intType}, null, null); - addMethod("Utility", "intToCharacter", null, true, charobjType, new Type[] {intType}, null, null); - addMethod("Utility", "intToLong", null, true, longobjType, new Type[] {intType}, null, null); - addMethod("Utility", "intToFloat", null, true, floatobjType, new Type[] {intType}, null, null); - addMethod("Utility", "intToDouble", null, true, doubleobjType, new Type[] {intType}, null, null); - addMethod("Utility", "IntegerToboolean", null, true, booleanType, new Type[] {intobjType}, null, null); - addMethod("Utility", "IntegerTochar", null, true, charType, new Type[] {intobjType}, null, null); - addMethod("Utility", "longToboolean", null, true, booleanType, new Type[] {longType}, null, null); - addMethod("Utility", "longToByte", null, true, byteobjType, new Type[] {longType}, null, null); - addMethod("Utility", "longToShort", null, true, shortobjType, new Type[] {longType}, null, null); - addMethod("Utility", "longToCharacter", null, true, charobjType, new Type[] {longType}, null, null); - addMethod("Utility", "longToInteger", null, true, intobjType, new Type[] {longType}, null, null); - addMethod("Utility", "longToFloat", null, true, floatobjType, new Type[] {longType}, null, null); - addMethod("Utility", "longToDouble", null, true, doubleobjType, new Type[] {longType}, null, null); - addMethod("Utility", "LongToboolean", null, true, booleanType, new Type[] {longobjType}, null, null); - addMethod("Utility", "LongTochar", null, true, charType, new Type[] {longobjType}, null, null); - addMethod("Utility", "floatToboolean", null, true, booleanType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToByte", null, true, byteobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToShort", null, true, shortobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToCharacter", null, true, charobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToInteger", null, true, intobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToLong", null, true, longobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "floatToDouble", null, true, doubleobjType, new Type[] {floatType}, null, null); - addMethod("Utility", "FloatToboolean", null, true, booleanType, new Type[] {floatobjType}, null, null); - addMethod("Utility", "FloatTochar", null, true, charType, new Type[] {floatobjType}, null, null); - addMethod("Utility", "doubleToboolean", null, true, booleanType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToByte", null, true, byteobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToShort", null, true, shortobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToCharacter", null, true, charobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToInteger", null, true, intobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToLong", null, true, longobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "doubleToFloat", null, true, floatobjType, new Type[] {doubleType}, null, null); - addMethod("Utility", "DoubleToboolean", null, true, booleanType, new Type[] {doubleobjType}, null, null); - addMethod("Utility", "DoubleTochar", null, true, charType, new Type[] {doubleobjType}, null, null); - addMethod("Utility", "StringTochar", null, true, charType, new Type[] {stringType}, null, null); - addMethod("Utility", "StringToCharacter", null, true, charobjType, new Type[] {stringType}, null, null); - - addMethod("Math", "abs", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "acos", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "asin", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "atan", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "atan2", null, true, doubleType, new Type[] {doubleType, doubleType}, null, null); - addMethod("Math", "cbrt", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "ceil", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "cos", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "cosh", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "exp", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "expm1", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "floor", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "hypot", null, true, doubleType, new Type[] {doubleType, doubleType}, null, null); - addMethod("Math", "log", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "log10", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "log1p", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "max", null, true, doubleType, new Type[] {doubleType, doubleType}, null, null); - addMethod("Math", "min", null, true, doubleType, new Type[] {doubleType, doubleType}, null, null); - addMethod("Math", "pow", null, true, doubleType, new Type[] {doubleType, doubleType}, null, null); - addMethod("Math", "random", null, true, doubleType, new Type[] {}, null, null); - addMethod("Math", "rint", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "round", null, true, longType, new Type[] {doubleType}, null, null); - addMethod("Math", "sin", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "sinh", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "sqrt", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "tan", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "tanh", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "toDegrees", null, true, doubleType, new Type[] {doubleType}, null, null); - addMethod("Math", "toRadians", null, true, doubleType, new Type[] {doubleType}, null, null); - addField("Math", "E", null, true, doubleType, null); - addField("Math", "PI", null, true, doubleType, null); - - addMethod("Def", "DefTobyteImplicit", null, true, byteType, new Type[] {defType}, null, null); - addMethod("Def", "DefToshortImplicit", null, true, shortType, new Type[] {defType}, null, null); - addMethod("Def", "DefTocharImplicit", null, true, charType, new Type[] {defType}, null, null); - addMethod("Def", "DefTointImplicit", null, true, intType, new Type[] {defType}, null, null); - addMethod("Def", "DefTolongImplicit", null, true, longType, new Type[] {defType}, null, null); - addMethod("Def", "DefTofloatImplicit", null, true, floatType, new Type[] {defType}, null, null); - addMethod("Def", "DefTodoubleImplicit", null, true, doubleType, new Type[] {defType}, null, null); - addMethod("Def", "DefToByteImplicit", null, true, byteobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToShortImplicit", null, true, shortobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToCharacterImplicit", null, true, charobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToIntegerImplicit", null, true, intobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToLongImplicit", null, true, longobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToFloatImplicit", null, true, floatobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToDoubleImplicit", null, true, doubleobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefTobyteExplicit", null, true, byteType, new Type[] {defType}, null, null); - addMethod("Def", "DefToshortExplicit", null, true, shortType, new Type[] {defType}, null, null); - addMethod("Def", "DefTocharExplicit", null, true, charType, new Type[] {defType}, null, null); - addMethod("Def", "DefTointExplicit", null, true, intType, new Type[] {defType}, null, null); - addMethod("Def", "DefTolongExplicit", null, true, longType, new Type[] {defType}, null, null); - addMethod("Def", "DefTofloatExplicit", null, true, floatType, new Type[] {defType}, null, null); - addMethod("Def", "DefTodoubleExplicit", null, true, doubleType, new Type[] {defType}, null, null); - addMethod("Def", "DefToByteExplicit", null, true, byteobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToShortExplicit", null, true, shortobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToCharacterExplicit", null, true, charobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToIntegerExplicit", null, true, intobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToLongExplicit", null, true, longobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToFloatExplicit", null, true, floatobjType, new Type[] {defType}, null, null); - addMethod("Def", "DefToDoubleExplicit", null, true, doubleobjType, new Type[] {defType}, null, null); - - addMethod("Iterator", "hasNext", null, false, booleanType, new Type[] {}, null, null); - addMethod("Iterator", "next", null, false, objectType, new Type[] {}, defType, null); - addMethod("Iterator", "remove", null, false, voidType, new Type[] {}, null, null); - - addMethod("Iterator", "hasNext", null, false, booleanType, new Type[] {}, null, null); - addMethod("Iterator", "next", null, false, objectType, new Type[] {}, null, null); - addMethod("Iterator", "remove", null, false, voidType, new Type[] {}, null, null); - - addMethod("Iterator", "hasNext", null, false, booleanType, new Type[] {}, null, null); - addMethod("Iterator", "next", null, false, objectType, new Type[] {}, stringType, null); - addMethod("Iterator", "remove", null, false, voidType, new Type[] {}, null, null); - - addMethod("Collection", "add", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Collection", "clear", null, false, voidType, new Type[] {}, null, null); - addMethod("Collection", "contains", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Collection", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Collection", "iterator", null, false, itrType, new Type[] {}, null, null); - addMethod("Collection", "remove", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Collection", "size", null, false, intType, new Type[] {}, null, null); - - addMethod("Collection", "add", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Collection", "clear", null, false, voidType, new Type[] {}, null, null); - addMethod("Collection", "contains", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Collection", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Collection", "iterator", null, false, oitrType, new Type[] {}, null, null); - addMethod("Collection", "remove", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Collection", "size", null, false, intType, new Type[] {}, null, null); - - addMethod("Collection", "add", null, false, booleanType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Collection", "clear", null, false, voidType, new Type[] {}, null, null); - addMethod("Collection", "contains", null, false, booleanType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Collection", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Collection", "iterator", null, false, sitrType, new Type[] {}, null, null); - addMethod("Collection", "remove", null, false, booleanType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Collection", "size", null, false, intType, new Type[] {}, null, null); - - addMethod("List", "set", null, false, objectType, new Type[] {intType, objectType}, defType, new Type[] {intType, defType}); - addMethod("List", "get", null, false, objectType, new Type[] {intType}, defType, null); - addMethod("List", "remove", null, false, objectType, new Type[] {intType}, defType, null); - addMethod("List", "getLength", "size", false, intType, new Type[] {}, null, null); - - addConstructor("ArrayList", "new", new Type[] {}, null); - - addMethod("List", "set", null, false, objectType, new Type[] {intType, objectType}, null, null); - addMethod("List", "get", null, false, objectType, new Type[] {intType}, null, null); - addMethod("List", "remove", null, false, objectType, new Type[] {intType}, null, null); - addMethod("List", "getLength", "size", false, intType, new Type[] {}, null, null); - - addConstructor("ArrayList", "new", new Type[] {}, null); - - addMethod("List", "set", null, false, objectType, new Type[] {intType, objectType}, stringType, - new Type[] {intType, stringType}); - addMethod("List", "get", null, false, objectType, new Type[] {intType}, stringType, null); - addMethod("List", "remove", null, false, objectType, new Type[] {intType}, stringType, null); - addMethod("List", "getLength", "size", false, intType, new Type[] {}, null, null); - - addConstructor("ArrayList", "new", new Type[] {}, null); - - addConstructor("HashSet", "new", new Type[] {}, null); - - addConstructor("HashSet", "new", new Type[] {}, null); - - addConstructor("HashSet", "new", new Type[] {}, null); - - addMethod("Map", "put", null, false, objectType, new Type[] {objectType, objectType}, defType, new Type[] {defType, defType}); - addMethod("Map", "get", null, false, objectType, new Type[] {objectType}, defType, new Type[] {defType}); - addMethod("Map", "remove", null, false, objectType, new Type[] {objectType}, null, null); - addMethod("Map", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Map", "size", null, false, intType, new Type[] {}, null, null); - addMethod("Map", "containsKey", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Map", "containsValue", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Map", "keySet", null, false, osetType, new Type[] {}, setType, null); - addMethod("Map", "values", null, false, ocollectionType, new Type[] {}, collectionType, null); - - addConstructor("HashMap", "new", new Type[] {}, null); - - addMethod("Map", "put", null, false, objectType, new Type[] {objectType, objectType}, null, null); - addMethod("Map", "get", null, false, objectType, new Type[] {objectType}, null, null); - addMethod("Map", "remove", null, false, objectType, new Type[] {objectType}, null, null); - addMethod("Map", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Map", "size", null, false, intType, new Type[] {}, null, null); - addMethod("Map", "containsKey", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Map", "containsValue", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Map", "keySet", null, false, osetType, new Type[] {}, null, null); - addMethod("Map", "values", null, false, ocollectionType, new Type[] {}, null, null); - - addConstructor("HashMap", "new", new Type[] {}, null); - - addMethod("Map", "put", null, false, objectType, new Type[] {objectType, objectType}, defType, - new Type[] {stringType, defType}); - addMethod("Map", "get", null, false, objectType, new Type[] {objectType}, defType, new Type[] {stringType}); - addMethod("Map", "remove", null, false, objectType, new Type[] {objectType}, defType, new Type[] {stringType}); - addMethod("Map", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Map", "size", null, false, intType, new Type[] {}, null, null); - addMethod("Map", "containsKey", null, false, booleanType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Map", "containsValue", null, false, booleanType, new Type[] {objectType}, null, new Type[] {defType}); - addMethod("Map", "keySet", null, false, osetType, new Type[] {}, ssetType, null); - addMethod("Map", "values", null, false, ocollectionType, new Type[] {}, collectionType, null); - - addConstructor("HashMap", "new", new Type[] {}, null); - - addMethod("Map", "put", null, false, objectType, new Type[] {objectType, objectType}, null, - new Type[] {stringType, objectType}); - addMethod("Map", "get", null, false, objectType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Map", "remove", null, false, objectType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Map", "isEmpty", null, false, booleanType, new Type[] {}, null, null); - addMethod("Map", "size", null, false, intType, new Type[] {}, null, null); - addMethod("Map", "containsKey", null, false, booleanType, new Type[] {objectType}, null, new Type[] {stringType}); - addMethod("Map", "containsValue", null, false, booleanType, new Type[] {objectType}, null, null); - addMethod("Map", "keySet", null, false, osetType, new Type[] {}, ssetType, null); - addMethod("Map", "values", null, false, ocollectionType, new Type[] {}, null, null); - - addConstructor("HashMap", "new", new Type[] {}, null); - - addMethod("Exception", "getMessage", null, false, stringType, new Type[] {}, null, null); - - addConstructor("ArithmeticException", "new", new Type[] {stringType}, null); - - addConstructor("IllegalArgumentException", "new", new Type[] {stringType}, null); - - addConstructor("IllegalStateException", "new", new Type[] {stringType}, null); - - addConstructor("NumberFormatException", "new", new Type[] {stringType}, null); - - addMethod("GeoPoint", "getLat", null, false, doubleType, new Type[] {}, null, null); - addMethod("GeoPoint", "getLon", null, false, doubleType, new Type[] {}, null, null); - addMethod("Strings", "getValue", null, false, stringType, new Type[] {}, null, null); - addMethod("Strings", "getValues", null, false, slistType, new Type[] {}, null, null); - addMethod("Longs", "getValue", null, false, longType, new Type[] {}, null, null); - addMethod("Longs", "getValues", null, false, olistType, new Type[] {}, null, null); - // TODO: add better date support for Longs here? (carefully?) - addMethod("Doubles", "getValue", null, false, doubleType, new Type[] {}, null, null); - addMethod("Doubles", "getValues", null, false, olistType, new Type[] {}, null, null); - addMethod("GeoPoints", "getValue", null, false, geoPointType, new Type[] {}, null, null); - addMethod("GeoPoints", "getValues", null, false, olistType, new Type[] {}, null, null); - addMethod("GeoPoints", "getLat", null, false, doubleType, new Type[] {}, null, null); - addMethod("GeoPoints", "getLon", null, false, doubleType, new Type[] {}, null, null); - addMethod("GeoPoints", "getLats", null, false, getType(doubleType.struct, 1), new Type[] {}, null, null); - addMethod("GeoPoints", "getLons", null, false, getType(doubleType.struct, 1), new Type[] {}, null, null); - // geo distance functions... so many... - addMethod("GeoPoints", "factorDistance", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "factorDistanceWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "factorDistance02", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "factorDistance13", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistance", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistanceWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistanceInKm", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistanceInKmWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistanceInMiles", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "arcDistanceInMilesWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distance", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distanceWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distanceInKm", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distanceInKmWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distanceInMiles", null, false, doubleType, - new Type[] { doubleType, doubleType }, null, null); - addMethod("GeoPoints", "distanceInMilesWithDefault", null, false, doubleType, - new Type[] { doubleType, doubleType, doubleType }, null, null); - addMethod("GeoPoints", "geohashDistance", null, false, doubleType, - new Type[] { stringType }, null, null); - addMethod("GeoPoints", "geohashDistanceInKm", null, false, doubleType, - new Type[] { stringType }, null, null); - addMethod("GeoPoints", "geohashDistanceInMiles", null, false, doubleType, - new Type[] { stringType }, null, null); - - // currently FeatureTest exposes overloaded constructor, field load store, and overloaded static methods - addConstructor("FeatureTest", "new", new Type[] {}, null); - addConstructor("FeatureTest", "new", new Type[] {intType, intType}, null); - addMethod("FeatureTest", "getX", null, false, intType, new Type[] {}, null, null); - addMethod("FeatureTest", "getY", null, false, intType, new Type[] {}, null, null); - addMethod("FeatureTest", "setX", null, false, voidType, new Type[] {intType}, null, null); - addMethod("FeatureTest", "setY", null, false, voidType, new Type[] {intType}, null, null); - addMethod("FeatureTest", "overloadedStatic", null, true, booleanType, new Type[] {}, null, null); - addMethod("FeatureTest", "overloadedStatic", null, true, booleanType, new Type[] {booleanType}, null, null); - } - - private void copyStructs() { - copyStruct("Void", "Object"); - copyStruct("Boolean", "Object"); - copyStruct("Byte", "Number", "Object"); - copyStruct("Short", "Number", "Object"); - copyStruct("Character", "Object"); - copyStruct("Integer", "Number", "Object"); - copyStruct("Long", "Number", "Object"); - copyStruct("Float", "Number", "Object"); - copyStruct("Double", "Number", "Object"); - - copyStruct("Number", "Object"); - copyStruct("CharSequence", "Object"); - copyStruct("String", "CharSequence", "Object"); - - copyStruct("List", "Collection", "Object"); - copyStruct("ArrayList", "List", "Collection", "Object"); - copyStruct("List", "Collection", "Object"); - copyStruct("ArrayList", "List", "Collection", "Object"); - copyStruct("List", "Collection", "Object"); - copyStruct("ArrayList", "List", "Collection", "Object"); - - copyStruct("Set", "Collection", "Object"); - copyStruct("HashSet", "Set", "Collection", "Object"); - copyStruct("Set", "Collection", "Object"); - copyStruct("HashSet", "Set", "Collection", "Object"); - copyStruct("Set", "Collection", "Object"); - copyStruct("HashSet", "Set", "Collection", "Object"); - - copyStruct("Map", "Object"); - copyStruct("HashMap", "Map", "Object"); - copyStruct("Map", "Object"); - copyStruct("HashMap", "Map", "Object"); - copyStruct("Map", "Object"); - copyStruct("HashMap", "Map", "Object"); - copyStruct("Map", "Object"); - copyStruct("HashMap", "Map", "Object"); - - copyStruct("Executable", "Object"); - - copyStruct("Exception", "Object"); - copyStruct("ArithmeticException", "Exception", "Object"); - copyStruct("IllegalArgumentException", "Exception", "Object"); - copyStruct("IllegalStateException", "Exception", "Object"); - copyStruct("NumberFormatException", "Exception", "Object"); - - copyStruct("GeoPoint", "Object"); - copyStruct("Strings", "List", "Collection", "Object"); - copyStruct("Longs", "List", "Collection", "Object"); - copyStruct("Doubles", "List", "Collection", "Object"); - copyStruct("GeoPoints", "List", "Collection", "Object"); - - copyStruct("FeatureTest", "Object"); - } - - private void addTransforms() { - addTransform(booleanType, objectType, "Boolean", "valueOf", true, false); - addTransform(booleanType, defType, "Boolean", "valueOf", true, false); - addTransform(booleanType, booleanobjType, "Boolean", "valueOf", true, false); - - addTransform(byteType, shortType, false); - addTransform(byteType, charType, true); - addTransform(byteType, intType, false); - addTransform(byteType, longType, false); - addTransform(byteType, floatType, false); - addTransform(byteType, doubleType, false); - addTransform(byteType, objectType, "Byte", "valueOf", true, false); - addTransform(byteType, defType, "Byte", "valueOf", true, false); - addTransform(byteType, numberType, "Byte", "valueOf", true, false); - addTransform(byteType, byteobjType, "Byte", "valueOf", true, false); - addTransform(byteType, shortobjType, "Utility", "byteToShort", true, false); - addTransform(byteType, charobjType, "Utility", "byteToCharacter", true, true); - addTransform(byteType, intobjType, "Utility", "byteToInteger", true, false); - addTransform(byteType, longobjType, "Utility", "byteToLong", true, false); - addTransform(byteType, floatobjType, "Utility", "byteToFloat", true, false); - addTransform(byteType, doubleobjType, "Utility", "byteToDouble", true, false); - - addTransform(shortType, byteType, true); - addTransform(shortType, charType, true); - addTransform(shortType, intType, false); - addTransform(shortType, longType, false); - addTransform(shortType, floatType, false); - addTransform(shortType, doubleType, false); - addTransform(shortType, objectType, "Short", "valueOf", true, false); - addTransform(shortType, defType, "Short", "valueOf", true, false); - addTransform(shortType, numberType, "Short", "valueOf", true, false); - addTransform(shortType, byteobjType, "Utility", "shortToByte", true, true); - addTransform(shortType, shortobjType, "Short", "valueOf", true, false); - addTransform(shortType, charobjType, "Utility", "shortToCharacter", true, true); - addTransform(shortType, intobjType, "Utility", "shortToInteger", true, false); - addTransform(shortType, longobjType, "Utility", "shortToLong", true, false); - addTransform(shortType, floatobjType, "Utility", "shortToFloat", true, false); - addTransform(shortType, doubleobjType, "Utility", "shortToDouble", true, false); - - addTransform(charType, byteType, true); - addTransform(charType, shortType, true); - addTransform(charType, intType, false); - addTransform(charType, longType, false); - addTransform(charType, floatType, false); - addTransform(charType, doubleType, false); - addTransform(charType, objectType, "Character", "valueOf", true, false); - addTransform(charType, defType, "Character", "valueOf", true, false); - addTransform(charType, numberType, "Utility", "charToInteger", true, false); - addTransform(charType, byteobjType, "Utility", "charToByte", true, true); - addTransform(charType, shortobjType, "Utility", "charToShort", true, true); - addTransform(charType, charobjType, "Character", "valueOf", true, false); - addTransform(charType, intobjType, "Utility", "charToInteger", true, false); - addTransform(charType, longobjType, "Utility", "charToLong", true, false); - addTransform(charType, floatobjType, "Utility", "charToFloat", true, false); - addTransform(charType, doubleobjType, "Utility", "charToDouble", true, false); - addTransform(charType, stringType, "Utility", "charToString", true, true); - - addTransform(intType, byteType, true); - addTransform(intType, shortType, true); - addTransform(intType, charType, true); - addTransform(intType, longType, false); - addTransform(intType, floatType, false); - addTransform(intType, doubleType, false); - addTransform(intType, objectType, "Integer", "valueOf", true, false); - addTransform(intType, defType, "Integer", "valueOf", true, false); - addTransform(intType, numberType, "Integer", "valueOf", true, false); - addTransform(intType, byteobjType, "Utility", "intToByte", true, true); - addTransform(intType, shortobjType, "Utility", "intToShort", true, true); - addTransform(intType, charobjType, "Utility", "intToCharacter", true, true); - addTransform(intType, intobjType, "Integer", "valueOf", true, false); - addTransform(intType, longobjType, "Utility", "intToLong", true, false); - addTransform(intType, floatobjType, "Utility", "intToFloat", true, false); - addTransform(intType, doubleobjType, "Utility", "intToDouble", true, false); - - addTransform(longType, byteType, true); - addTransform(longType, shortType, true); - addTransform(longType, charType, true); - addTransform(longType, intType, false); - addTransform(longType, floatType, false); - addTransform(longType, doubleType, false); - addTransform(longType, objectType, "Long", "valueOf", true, false); - addTransform(longType, defType, "Long", "valueOf", true, false); - addTransform(longType, numberType, "Long", "valueOf", true, false); - addTransform(longType, byteobjType, "Utility", "longToByte", true, true); - addTransform(longType, shortobjType, "Utility", "longToShort", true, true); - addTransform(longType, charobjType, "Utility", "longToCharacter", true, true); - addTransform(longType, intobjType, "Utility", "longToInteger", true, true); - addTransform(longType, longobjType, "Long", "valueOf", true, false); - addTransform(longType, floatobjType, "Utility", "longToFloat", true, false); - addTransform(longType, doubleobjType, "Utility", "longToDouble", true, false); - - addTransform(floatType, byteType, true); - addTransform(floatType, shortType, true); - addTransform(floatType, charType, true); - addTransform(floatType, intType, true); - addTransform(floatType, longType, false); - addTransform(floatType, doubleType, false); - addTransform(floatType, objectType, "Float", "valueOf", true, false); - addTransform(floatType, defType, "Float", "valueOf", true, false); - addTransform(floatType, numberType, "Float", "valueOf", true, false); - addTransform(floatType, byteobjType, "Utility", "floatToByte", true, true); - addTransform(floatType, shortobjType, "Utility", "floatToShort", true, true); - addTransform(floatType, charobjType, "Utility", "floatToCharacter", true, true); - addTransform(floatType, intobjType, "Utility", "floatToInteger", true, true); - addTransform(floatType, longobjType, "Utility", "floatToLong", true, true); - addTransform(floatType, floatobjType, "Float", "valueOf", true, false); - addTransform(floatType, doubleobjType, "Utility", "floatToDouble", true, false); - - addTransform(doubleType, byteType, true); - addTransform(doubleType, shortType, true); - addTransform(doubleType, charType, true); - addTransform(doubleType, intType, true); - addTransform(doubleType, longType, true); - addTransform(doubleType, floatType, false); - addTransform(doubleType, objectType, "Double", "valueOf", true, false); - addTransform(doubleType, defType, "Double", "valueOf", true, false); - addTransform(doubleType, numberType, "Double", "valueOf", true, false); - addTransform(doubleType, byteobjType, "Utility", "doubleToByte", true, true); - addTransform(doubleType, shortobjType, "Utility", "doubleToShort", true, true); - addTransform(doubleType, charobjType, "Utility", "doubleToCharacter", true, true); - addTransform(doubleType, intobjType, "Utility", "doubleToInteger", true, true); - addTransform(doubleType, longobjType, "Utility", "doubleToLong", true, true); - addTransform(doubleType, floatobjType, "Utility", "doubleToFloat", true, true); - addTransform(doubleType, doubleobjType, "Double", "valueOf", true, false); - - addTransform(objectType, booleanType, "Boolean", "booleanValue", false, true); - addTransform(objectType, byteType, "Number", "byteValue", false, true); - addTransform(objectType, shortType, "Number", "shortValue", false, true); - addTransform(objectType, charType, "Character", "charValue", false, true); - addTransform(objectType, intType, "Number", "intValue", false, true); - addTransform(objectType, longType, "Number", "longValue", false, true); - addTransform(objectType, floatType, "Number", "floatValue", false, true); - addTransform(objectType, doubleType, "Number", "doubleValue", false, true); - - addTransform(defType, booleanType, "Boolean", "booleanValue", false, false); - addTransform(defType, byteType, "Def", "DefTobyteImplicit", true, false); - addTransform(defType, shortType, "Def", "DefToshortImplicit", true, false); - addTransform(defType, charType, "Def", "DefTocharImplicit", true, false); - addTransform(defType, intType, "Def", "DefTointImplicit", true, false); - addTransform(defType, longType, "Def", "DefTolongImplicit", true, false); - addTransform(defType, floatType, "Def", "DefTofloatImplicit", true, false); - addTransform(defType, doubleType, "Def", "DefTodoubleImplicit", true, false); - addTransform(defType, byteobjType, "Def", "DefToByteImplicit", true, false); - addTransform(defType, shortobjType, "Def", "DefToShortImplicit", true, false); - addTransform(defType, charobjType, "Def", "DefToCharacterImplicit", true, false); - addTransform(defType, intobjType, "Def", "DefToIntegerImplicit", true, false); - addTransform(defType, longobjType, "Def", "DefToLongImplicit", true, false); - addTransform(defType, floatobjType, "Def", "DefToFloatImplicit", true, false); - addTransform(defType, doubleobjType, "Def", "DefToDoubleImplicit", true, false); - addTransform(defType, byteType, "Def", "DefTobyteExplicit", true, true); - addTransform(defType, shortType, "Def", "DefToshortExplicit", true, true); - addTransform(defType, charType, "Def", "DefTocharExplicit", true, true); - addTransform(defType, intType, "Def", "DefTointExplicit", true, true); - addTransform(defType, longType, "Def", "DefTolongExplicit", true, true); - addTransform(defType, floatType, "Def", "DefTofloatExplicit", true, true); - addTransform(defType, doubleType, "Def", "DefTodoubleExplicit", true, true); - addTransform(defType, byteobjType, "Def", "DefToByteExplicit", true, true); - addTransform(defType, shortobjType, "Def", "DefToShortExplicit", true, true); - addTransform(defType, charobjType, "Def", "DefToCharacterExplicit", true, true); - addTransform(defType, intobjType, "Def", "DefToIntegerExplicit", true, true); - addTransform(defType, longobjType, "Def", "DefToLongExplicit", true, true); - addTransform(defType, floatobjType, "Def", "DefToFloatExplicit", true, true); - addTransform(defType, doubleobjType, "Def", "DefToDoubleExplicit", true, true); - - addTransform(numberType, byteType, "Number", "byteValue", false, true); - addTransform(numberType, shortType, "Number", "shortValue", false, true); - addTransform(numberType, charType, "Utility", "NumberTochar", true, true); - addTransform(numberType, intType, "Number", "intValue", false, true); - addTransform(numberType, longType, "Number", "longValue", false, true); - addTransform(numberType, floatType, "Number", "floatValue", false, true); - addTransform(numberType, doubleType, "Number", "doubleValue", false, true); - addTransform(numberType, booleanobjType, "Utility", "NumberToBoolean", true, true); - addTransform(numberType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(numberType, shortobjType, "Utility", "NumberToShort", true, true); - addTransform(numberType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(numberType, intobjType, "Utility", "NumberToInteger", true, true); - addTransform(numberType, longobjType, "Utility", "NumberToLong", true, true); - addTransform(numberType, floatobjType, "Utility", "NumberToFloat", true, true); - addTransform(numberType, doubleobjType, "Utility", "NumberToDouble", true, true); - - addTransform(booleanobjType, booleanType, "Boolean", "booleanValue", false, false); - - addTransform(byteobjType, byteType, "Byte", "byteValue", false, false); - addTransform(byteobjType, shortType, "Byte", "shortValue", false, false); - addTransform(byteobjType, charType, "Utility", "ByteTochar", true, false); - addTransform(byteobjType, intType, "Byte", "intValue", false, false); - addTransform(byteobjType, longType, "Byte", "longValue", false, false); - addTransform(byteobjType, floatType, "Byte", "floatValue", false, false); - addTransform(byteobjType, doubleType, "Byte", "doubleValue", false, false); - addTransform(byteobjType, shortobjType, "Utility", "NumberToShort", true, false); - addTransform(byteobjType, charobjType, "Utility", "NumberToCharacter", true, false); - addTransform(byteobjType, intobjType, "Utility", "NumberToInteger", true, false); - addTransform(byteobjType, longobjType, "Utility", "NumberToLong", true, false); - addTransform(byteobjType, floatobjType, "Utility", "NumberToFloat", true, false); - addTransform(byteobjType, doubleobjType, "Utility", "NumberToDouble", true, false); - - addTransform(shortobjType, byteType, "Short", "byteValue", false, true); - addTransform(shortobjType, shortType, "Short", "shortValue", false, true); - addTransform(shortobjType, charType, "Utility", "ShortTochar", true, false); - addTransform(shortobjType, intType, "Short", "intValue", false, false); - addTransform(shortobjType, longType, "Short", "longValue", false, false); - addTransform(shortobjType, floatType, "Short", "floatValue", false, false); - addTransform(shortobjType, doubleType, "Short", "doubleValue", false, false); - addTransform(shortobjType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(shortobjType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(shortobjType, intobjType, "Utility", "NumberToInteger", true, false); - addTransform(shortobjType, longobjType, "Utility", "NumberToLong", true, false); - addTransform(shortobjType, floatobjType, "Utility", "NumberToFloat", true, false); - addTransform(shortobjType, doubleobjType, "Utility", "NumberToDouble", true, false); - - addTransform(charobjType, byteType, "Utility", "CharacterTobyte", true, true); - addTransform(charobjType, shortType, "Utility", "CharacterToshort", true, false); - addTransform(charobjType, charType, "Character", "charValue", false, true); - addTransform(charobjType, intType, "Utility", "CharacterToint", true, false); - addTransform(charobjType, longType, "Utility", "CharacterTolong", true, false); - addTransform(charobjType, floatType, "Utility", "CharacterTofloat", true, false); - addTransform(charobjType, doubleType, "Utility", "CharacterTodouble", true, false); - addTransform(charobjType, byteobjType, "Utility", "CharacterToByte", true, true); - addTransform(charobjType, shortobjType, "Utility", "CharacterToShort", true, true); - addTransform(charobjType, intobjType, "Utility", "CharacterToInteger", true, false); - addTransform(charobjType, longobjType, "Utility", "CharacterToLong", true, false); - addTransform(charobjType, floatobjType, "Utility", "CharacterToFloat", true, false); - addTransform(charobjType, doubleobjType, "Utility", "CharacterToDouble", true, false); - addTransform(charobjType, stringType, "Utility", "CharacterToString", true, true); - - addTransform(intobjType, byteType, "Integer", "byteValue", false, true); - addTransform(intobjType, shortType, "Integer", "shortValue", false, true); - addTransform(intobjType, charType, "Utility", "IntegerTochar", true, true); - addTransform(intobjType, intType, "Integer", "intValue", false, false); - addTransform(intobjType, longType, "Integer", "longValue", false, false); - addTransform(intobjType, floatType, "Integer", "floatValue", false, false); - addTransform(intobjType, doubleType, "Integer", "doubleValue", false, false); - addTransform(intobjType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(intobjType, shortobjType, "Utility", "NumberToShort", true, true); - addTransform(intobjType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(intobjType, longobjType, "Utility", "NumberToLong", true, false); - addTransform(intobjType, floatobjType, "Utility", "NumberToFloat", true, false); - addTransform(intobjType, doubleobjType, "Utility", "NumberToDouble", true, false); - - addTransform(longobjType, byteType, "Long", "byteValue", false, true); - addTransform(longobjType, shortType, "Long", "shortValue", false, true); - addTransform(longobjType, charType, "Utility", "LongTochar", true, true); - addTransform(longobjType, intType, "Long", "intValue", false, true); - addTransform(longobjType, longType, "Long", "longValue", false, false); - addTransform(longobjType, floatType, "Long", "floatValue", false, false); - addTransform(longobjType, doubleType, "Long", "doubleValue", false, false); - addTransform(longobjType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(longobjType, shortobjType, "Utility", "NumberToShort", true, true); - addTransform(longobjType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(longobjType, intobjType, "Utility", "NumberToInteger", true, true); - addTransform(longobjType, floatobjType, "Utility", "NumberToFloat", true, false); - addTransform(longobjType, doubleobjType, "Utility", "NumberToDouble", true, false); - - addTransform(floatobjType, byteType, "Float", "byteValue", false, true); - addTransform(floatobjType, shortType, "Float", "shortValue", false, true); - addTransform(floatobjType, charType, "Utility", "FloatTochar", true, true); - addTransform(floatobjType, intType, "Float", "intValue", false, true); - addTransform(floatobjType, longType, "Float", "longValue", false, true); - addTransform(floatobjType, floatType, "Float", "floatValue", false, false); - addTransform(floatobjType, doubleType, "Float", "doubleValue", false, false); - addTransform(floatobjType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(floatobjType, shortobjType, "Utility", "NumberToShort", true, true); - addTransform(floatobjType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(floatobjType, intobjType, "Utility", "NumberToInteger", true, true); - addTransform(floatobjType, longobjType, "Utility", "NumberToLong", true, true); - addTransform(floatobjType, doubleobjType, "Utility", "NumberToDouble", true, false); - - addTransform(doubleobjType, byteType, "Double", "byteValue", false, true); - addTransform(doubleobjType, shortType, "Double", "shortValue", false, true); - addTransform(doubleobjType, charType, "Utility", "DoubleTochar", true, true); - addTransform(doubleobjType, intType, "Double", "intValue", false, true); - addTransform(doubleobjType, longType, "Double", "longValue", false, true); - addTransform(doubleobjType, floatType, "Double", "floatValue", false, true); - addTransform(doubleobjType, doubleType, "Double", "doubleValue", false, false); - addTransform(doubleobjType, byteobjType, "Utility", "NumberToByte", true, true); - addTransform(doubleobjType, shortobjType, "Utility", "NumberToShort", true, true); - addTransform(doubleobjType, charobjType, "Utility", "NumberToCharacter", true, true); - addTransform(doubleobjType, intobjType, "Utility", "NumberToInteger", true, true); - addTransform(doubleobjType, longobjType, "Utility", "NumberToLong", true, true); - addTransform(doubleobjType, floatobjType, "Utility", "NumberToFloat", true, true); - - addTransform(stringType, charType, "Utility", "StringTochar", true, true); - addTransform(stringType, charobjType, "Utility", "StringToCharacter", true, true); - } - - private void addRuntimeClasses() { - addRuntimeClass(booleanType.struct); - addRuntimeClass(byteType.struct); - addRuntimeClass(shortType.struct); - addRuntimeClass(charType.struct); - addRuntimeClass(intType.struct); - addRuntimeClass(longType.struct); - addRuntimeClass(floatType.struct); - addRuntimeClass(doubleType.struct); - - addRuntimeClass(booleanobjType.struct); - addRuntimeClass(byteobjType.struct); - addRuntimeClass(shortobjType.struct); - addRuntimeClass(charobjType.struct); - addRuntimeClass(intobjType.struct); - addRuntimeClass(longobjType.struct); - addRuntimeClass(floatobjType.struct); - addRuntimeClass(doubleobjType.struct); - - addRuntimeClass(objectType.struct); - addRuntimeClass(numberType.struct); - addRuntimeClass(charseqType.struct); - addRuntimeClass(stringType.struct); - - addRuntimeClass(oitrType.struct); - addRuntimeClass(ocollectionType.struct); - addRuntimeClass(olistType.struct); - addRuntimeClass(oarraylistType.struct); - addRuntimeClass(osetType.struct); - addRuntimeClass(ohashsetType.struct); - addRuntimeClass(oomapType.struct); - addRuntimeClass(oohashmapType.struct); - - addRuntimeClass(exceptionType.struct); - - addRuntimeClass(geoPointType.struct); - addRuntimeClass(stringsType.struct); - addRuntimeClass(longsType.struct); - addRuntimeClass(doublesType.struct); - addRuntimeClass(geoPointsType.struct); - - addRuntimeClass(featureTestType.struct); + int currentLine = -1; + try { + try (InputStream stream = Definition.class.getResourceAsStream(DEFINITION_FILE); + LineNumberReader reader = new LineNumberReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + String line = null; + String currentClass = null; + while ((line = reader.readLine()) != null) { + currentLine = reader.getLineNumber(); + line = line.trim(); + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } else if (line.startsWith("class ")) { + assert currentClass == null; + currentClass = line.split("\u0020")[1]; + } else if (line.equals("}")) { + assert currentClass != null; + currentClass = null; + } else { + assert currentClass != null; + addSignature(currentClass, line); + } + } + } + } catch (Exception e) { + throw new RuntimeException("syntax error in definition line: " + currentLine, e); + } } private final void addStruct(final String name, final Class clazz) { @@ -1599,9 +526,10 @@ public final class Definition { final Struct struct = new Struct(name, clazz, org.objectweb.asm.Type.getType(clazz)); structsMap.put(name, struct); + simpleTypesMap.put(name, getTypeInternal(name)); } - private final void addConstructor(final String struct, final String name, final Type[] args, final Type[] genargs) { + private final void addConstructorInternal(final String struct, final String name, final Type[] args) { final Struct owner = structsMap.get(struct); if (owner == null) { @@ -1634,14 +562,6 @@ public final class Definition { final Class[] classes = new Class[args.length]; for (int count = 0; count < classes.length; ++count) { - if (genargs != null) { - if (!args[count].clazz.isAssignableFrom(genargs[count].clazz)) { - throw new ClassCastException("Generic argument [" + genargs[count].name + "]" + - " is not a sub class of [" + args[count].name + "] in the constructor" + - " [" + name + " ] from the struct [" + owner.name + "]."); - } - } - classes[count] = args[count].clazz; } @@ -1655,79 +575,96 @@ public final class Definition { } final org.objectweb.asm.commons.Method asm = org.objectweb.asm.commons.Method.getMethod(reflect); - final Constructor constructor = - new Constructor(name, owner, Arrays.asList(genargs != null ? genargs : args), asm, reflect); + final Constructor constructor = new Constructor(name, owner, Arrays.asList(args), asm, reflect); owner.constructors.put(methodKey, constructor); } - private final void addMethod(final String struct, final String name, final String alias, final boolean statik, - final Type rtn, final Type[] args, final Type genrtn, final Type[] genargs) { + /** + * Adds a new signature to the definition. + *

+ * Signatures have the following forms: + *

    + *
  • {@code void method(String,int)} + *
  • {@code boolean field} + *
  • {@code Class (String)} + *
+ * no spaces allowed. + */ + private final void addSignature(String className, String signature) { + String elements[] = signature.split("\u0020"); + if (elements.length != 2) { + throw new IllegalArgumentException("Malformed signature: " + signature); + } + // method or field type (e.g. return type) + Type rtn = getTypeInternal(elements[0]); + int parenIndex = elements[1].indexOf('('); + if (parenIndex != -1) { + // method or ctor + int parenEnd = elements[1].indexOf(')'); + final Type args[]; + if (parenEnd > parenIndex + 1) { + String arguments[] = elements[1].substring(parenIndex + 1, parenEnd).split(","); + args = new Type[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + args[i] = getTypeInternal(arguments[i]); + } + } else { + args = new Type[0]; + } + String methodName = elements[1].substring(0, parenIndex); + if (methodName.equals("")) { + if (!elements[0].equals(className)) { + throw new IllegalArgumentException("Constructors must return their own type"); + } + addConstructorInternal(className, "new", args); + } else { + if (methodName.indexOf('/') >= 0) { + String nameAndAlias[] = methodName.split("/"); + if (nameAndAlias.length != 2) { + throw new IllegalArgumentException("Currently only two aliases are allowed!"); + } + addMethodInternal(className, nameAndAlias[0], nameAndAlias[1], rtn, args); + } else { + addMethodInternal(className, methodName, null, rtn, args); + } + } + } else { + // field + addFieldInternal(className, elements[1], null, rtn); + } + } + + private final void addMethodInternal(final String struct, final String name, final String alias, + final Type rtn, final Type[] args) { final Struct owner = structsMap.get(struct); if (owner == null) { throw new IllegalArgumentException("Owner struct [" + struct + "] not defined" + - " for " + (statik ? "function" : "method") + " [" + name + "]."); + " for method [" + name + "]."); } if (!name.matches("^[_a-zA-Z][_a-zA-Z0-9]*$")) { - throw new IllegalArgumentException("Invalid " + (statik ? "static method" : "method") + - " name [" + name + "] with the struct [" + owner.name + "]."); + throw new IllegalArgumentException("Invalid method name" + + " [" + name + "] with the struct [" + owner.name + "]."); } MethodKey methodKey = new MethodKey(name, args.length); if (owner.constructors.containsKey(methodKey)) { - throw new IllegalArgumentException("Constructors and " + (statik ? "static methods" : "methods") + + throw new IllegalArgumentException("Constructors and methods" + " may not have the same signature [" + methodKey + "] within the same struct" + " [" + owner.name + "]."); } - if (owner.staticMethods.containsKey(methodKey)) { - if (statik) { - throw new IllegalArgumentException( - "Duplicate static method signature [" + methodKey + "] found within the struct [" + owner.name + "]."); - } else { - throw new IllegalArgumentException("Static methods and methods may not have the same signature" + - " [" + methodKey + "] within the same struct [" + owner.name + "]."); - } - } - - if (owner.methods.containsKey(methodKey)) { - if (statik) { - throw new IllegalArgumentException("Static methods and methods may not have the same signature" + - " [" + methodKey + "] within the same struct [" + owner.name + "]."); - } else { - throw new IllegalArgumentException("Duplicate method signature [" + methodKey + "]" + - " found within the struct [" + owner.name + "]."); - } - } - - if (genrtn != null) { - if (!rtn.clazz.isAssignableFrom(genrtn.clazz)) { - throw new ClassCastException("Generic return [" + genrtn.clazz.getCanonicalName() + "]" + - " is not a sub class of [" + rtn.clazz.getCanonicalName() + "] in the method" + - " [" + name + " ] from the struct [" + owner.name + "]."); - } - } - - if (genargs != null && genargs.length != args.length) { - throw new IllegalArgumentException("Generic arguments arity [" + genargs.length + "] is not the same as " + - (statik ? "function" : "method") + " [" + name + "] arguments arity" + - " [" + args.length + "] within the struct [" + owner.name + "]."); + if (owner.staticMethods.containsKey(methodKey) || owner.methods.containsKey(methodKey)) { + throw new IllegalArgumentException( + "Duplicate method signature [" + methodKey + "] found within the struct [" + owner.name + "]."); } final Class[] classes = new Class[args.length]; for (int count = 0; count < classes.length; ++count) { - if (genargs != null) { - if (!args[count].clazz.isAssignableFrom(genargs[count].clazz)) { - throw new ClassCastException("Generic argument [" + genargs[count].name + "] is not a sub class" + - " of [" + args[count].name + "] in the " + (statik ? "function" : "method") + - " [" + name + " ] from the struct [" + owner.name + "]."); - } - } - classes[count] = args[count].clazz; } @@ -1736,15 +673,15 @@ public final class Definition { try { reflect = owner.clazz.getMethod(alias == null ? name : alias, classes); } catch (final NoSuchMethodException exception) { - throw new IllegalArgumentException((statik ? "Function" : "Method") + - " [" + (alias == null ? name : alias) + "] not found for class [" + owner.clazz.getName() + "]" + + throw new IllegalArgumentException("Method [" + (alias == null ? name : alias) + + "] not found for class [" + owner.clazz.getName() + "]" + " with arguments " + Arrays.toString(classes) + "."); } if (!reflect.getReturnType().equals(rtn.clazz)) { throw new IllegalArgumentException("Specified return type class [" + rtn.clazz + "]" + - " does not match the found return type class [" + reflect.getReturnType() + "] for the " + - (statik ? "function" : "method") + " [" + name + "]" + + " does not match the found return type class [" + reflect.getReturnType() + "] for the" + + " method [" + name + "]" + " within the struct [" + owner.name + "]."); } @@ -1760,67 +697,33 @@ public final class Definition { " with arguments " + Arrays.toString(classes) + "."); } - final Method method = new Method(name, owner, genrtn != null ? genrtn : rtn, - Arrays.asList(genargs != null ? genargs : args), asm, reflect, handle); + final Method method = new Method(name, owner, rtn, Arrays.asList(args), asm, reflect, handle); final int modifiers = reflect.getModifiers(); - if (statik) { - if (!java.lang.reflect.Modifier.isStatic(modifiers)) { - throw new IllegalArgumentException("Function [" + name + "]" + - " within the struct [" + owner.name + "] is not linked to a static Java method."); - } - + if (java.lang.reflect.Modifier.isStatic(modifiers)) { owner.staticMethods.put(methodKey, method); } else { - if (java.lang.reflect.Modifier.isStatic(modifiers)) { - throw new IllegalArgumentException("Method [" + name + "]" + - " within the struct [" + owner.name + "] is not linked to a non-static Java method."); - } - owner.methods.put(methodKey, method); } } - private final void addField(final String struct, final String name, final String alias, - final boolean statik, final Type type, final Type generic) { + private final void addFieldInternal(final String struct, final String name, final String alias, + final Type type) { final Struct owner = structsMap.get(struct); if (owner == null) { throw new IllegalArgumentException("Owner struct [" + struct + "] not defined for " + - (statik ? "static" : "member") + " [" + name + "]."); + " field [" + name + "]."); } if (!name.matches("^[_a-zA-Z][_a-zA-Z0-9]*$")) { - throw new IllegalArgumentException("Invalid " + (statik ? "static" : "member") + + throw new IllegalArgumentException("Invalid field " + " name [" + name + "] with the struct [" + owner.name + "]."); } - if (owner.staticMembers.containsKey(name)) { - if (statik) { - throw new IllegalArgumentException("Duplicate static name [" + name + "]" + - " found within the struct [" + owner.name + "]."); - } else { - throw new IllegalArgumentException("Statics and members may not have the same name " + - "[" + name + "] within the same struct [" + owner.name + "]."); - } - } - - if (owner.members.containsKey(name)) { - if (statik) { - throw new IllegalArgumentException("Statics and members may not have the same name " + - "[" + name + "] within the same struct [" + owner.name + "]."); - } else { - throw new IllegalArgumentException("Duplicate member name [" + name + "]" + - " found within the struct [" + owner.name + "]."); - } - } - - if (generic != null) { - if (!type.clazz.isAssignableFrom(generic.clazz)) { - throw new ClassCastException("Generic type [" + generic.clazz.getCanonicalName() + "]" + - " is not a sub class of [" + type.clazz.getCanonicalName() + "] for the field" + - " [" + name + " ] from the struct [" + owner.name + "]."); - } + if (owner.staticMembers.containsKey(name) || owner.members.containsKey(name)) { + throw new IllegalArgumentException("Duplicate field name [" + name + "]" + + " found within the struct [" + owner.name + "]."); } java.lang.reflect.Field reflect; @@ -1832,11 +735,14 @@ public final class Definition { " not found for class [" + owner.clazz.getName() + "]."); } + final int modifiers = reflect.getModifiers(); + boolean isStatic = java.lang.reflect.Modifier.isStatic(modifiers); + MethodHandle getter = null; MethodHandle setter = null; try { - if (!statik) { + if (!isStatic) { getter = MethodHandles.publicLookup().unreflectGetter(reflect); setter = MethodHandles.publicLookup().unreflectSetter(reflect); } @@ -1845,42 +751,33 @@ public final class Definition { " not found for class [" + owner.clazz.getName() + "]."); } - final Field field = new Field(name, owner, generic == null ? type : generic, type, reflect, getter, setter); - final int modifiers = reflect.getModifiers(); - - if (statik) { - if (!java.lang.reflect.Modifier.isStatic(modifiers)) { - throw new IllegalArgumentException(); - } + final Field field = new Field(name, owner, type, reflect, getter, setter); + if (isStatic) { + // require that all static fields are static final if (!java.lang.reflect.Modifier.isFinal(modifiers)) { throw new IllegalArgumentException("Static [" + name + "]" + - " within the struct [" + owner.name + "] is not linked to static Java field."); + " within the struct [" + owner.name + "] is not final."); } owner.staticMembers.put(alias == null ? name : alias, field); } else { - if (java.lang.reflect.Modifier.isStatic(modifiers)) { - throw new IllegalArgumentException("Member [" + name + "]" + - " within the struct [" + owner.name + "] is not linked to non-static Java field."); - } - owner.members.put(alias == null ? name : alias, field); } } - private final void copyStruct(final String struct, final String... children) { + private final void copyStruct(final String struct, List children) { final Struct owner = structsMap.get(struct); if (owner == null) { throw new IllegalArgumentException("Owner struct [" + struct + "] not defined for copy."); } - for (int count = 0; count < children.length; ++count) { - final Struct child = structsMap.get(children[count]); + for (int count = 0; count < children.size(); ++count) { + final Struct child = structsMap.get(children.get(count)); if (struct == null) { - throw new IllegalArgumentException("Child struct [" + children[count] + "]" + + throw new IllegalArgumentException("Child struct [" + children.get(count) + "]" + " not defined for copy to owner struct [" + owner.name + "]."); } @@ -1944,143 +841,12 @@ public final class Definition { } owner.members.put(field.name, - new Field(field.name, owner, field.type, field.generic, reflect, getter, setter)); + new Field(field.name, owner, field.type, reflect, getter, setter)); } } } } - private final void addTransform(final Type from, final Type to, final boolean explicit) { - if (from.equals(to)) { - throw new IllegalArgumentException("Transform cannot" + - " have cast type from [" + from.name + "] be the same as cast type to [" + to.name + "]."); - } - - if (!from.sort.primitive || !to.sort.primitive) { - throw new IllegalArgumentException("Only transforms between two primitives may be a simple cast, but" + - "found [" + from.name + "] and [" + to.name + "]."); - } - - final Cast cast = new Cast(from, to, explicit); - - if (transformsMap.containsKey(cast)) { - throw new IllegalArgumentException("Transform with " + - " cast type from [" + from.name + "] to cast type to [" + to.name + "] already defined."); - } - - transformsMap.put(cast, cast); - } - - private final void addTransform(final Type from, final Type to, final String struct, - final String name, final boolean statik, final boolean explicit) { - final Struct owner = structsMap.get(struct); - - if (owner == null) { - throw new IllegalArgumentException("Owner struct [" + struct + "] not defined for" + - " transform with cast type from [" + from.name + "] and cast type to [" + to.name + "]."); - } - - if (from.equals(to)) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "] cannot" + - " have cast type from [" + from.name + "] be the same as cast type to [" + to.name + "]."); - } - - final Cast cast = new Cast(from, to, explicit); - - if (transformsMap.containsKey(cast)) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + "] already defined."); - } - - final Cast transform; - - final Method method; - Type upcast = null; - Type downcast = null; - - // transforms are implicitly arity of 0, unless a static method where its 1 (receiver passed) - final MethodKey methodKey = new MethodKey(name, statik ? 1 : 0); - - if (statik) { - method = owner.staticMethods.get(methodKey); - - if (method == null) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + - "] using a function [" + name + "] that is not defined."); - } - - if (method.arguments.size() != 1) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + - "] using function [" + name + "] does not have a single type argument."); - } - - Type argument = method.arguments.get(0); - - if (!argument.clazz.isAssignableFrom(from.clazz)) { - if (from.clazz.isAssignableFrom(argument.clazz)) { - upcast = argument; - } else { - throw new ClassCastException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + "] using" + - " function [" + name + "] cannot cast from type to the function input argument type."); - } - } - - final Type rtn = method.rtn; - - if (!to.clazz.isAssignableFrom(rtn.clazz)) { - if (rtn.clazz.isAssignableFrom(to.clazz)) { - downcast = to; - } else { - throw new ClassCastException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + "] using" + - " function [" + name + "] cannot cast to type to the function return argument type."); - } - } - } else { - method = owner.methods.get(methodKey); - - if (method == null) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + - "] using a method [" + name + "] that is not defined."); - } - - if (!method.arguments.isEmpty()) { - throw new IllegalArgumentException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + - "] using method [" + name + "] does not have a single type argument."); - } - - if (!owner.clazz.isAssignableFrom(from.clazz)) { - if (from.clazz.isAssignableFrom(owner.clazz)) { - upcast = getType(owner.name); - } else { - throw new ClassCastException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + "] using" + - " method [" + name + "] cannot cast from type to the method input argument type."); - } - } - - final Type rtn = method.rtn; - - if (!to.clazz.isAssignableFrom(rtn.clazz)) { - if (rtn.clazz.isAssignableFrom(to.clazz)) { - downcast = to; - } else { - throw new ClassCastException("Transform with owner struct [" + owner.name + "]" + - " and cast type from [" + from.name + "] to cast type to [" + to.name + "]" + - " using method [" + name + "] cannot cast to type to the method return argument type."); - } - } - } - - transform = new Transform(cast, method, upcast, downcast); - transformsMap.put(cast, transform); - } - /** * Precomputes a more efficient structure for dynamic method/field access. */ @@ -2132,7 +898,12 @@ public final class Definition { runtimeMap.put(struct.clazz, new RuntimeClass(methods, getters, setters)); } - public final Type getType(final String name) { + private Type getTypeInternal(final String name) { + // simple types (e.g. 0 array dimensions) are a simple hash lookup for speed + Type simple = simpleTypesMap.get(name); + if (simple != null) { + return simple; + } final int dimensions = getDimensions(name); final String structstr = dimensions == 0 ? name : name.substring(0, name.indexOf('[')); final Struct struct = structsMap.get(structstr); @@ -2141,10 +912,10 @@ public final class Definition { throw new IllegalArgumentException("The struct with name [" + name + "] has not been defined."); } - return getType(struct, dimensions); + return getTypeInternal(struct, dimensions); } - public final Type getType(final Struct struct, final int dimensions) { + private Type getTypeInternal(final Struct struct, final int dimensions) { String name = struct.name; org.objectweb.asm.Type type = struct.type; Class clazz = struct.clazz; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java index fbb1d246a83..90c02b7e801 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java @@ -21,7 +21,6 @@ package org.elasticsearch.painless; import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.Definition.Sort; -import org.elasticsearch.painless.Definition.Transform; import org.elasticsearch.painless.Definition.Type; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Label; @@ -34,10 +33,7 @@ import java.util.ArrayList; import java.util.Deque; import java.util.List; -import static org.elasticsearch.painless.WriterConstants.ADDEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.ADDEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.ADDWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.ADDWOOVERLOW_FLOAT; +import static org.elasticsearch.painless.WriterConstants.CHAR_TO_STRING; import static org.elasticsearch.painless.WriterConstants.DEF_ADD_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_AND_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_DIV_CALL; @@ -47,21 +43,27 @@ import static org.elasticsearch.painless.WriterConstants.DEF_OR_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_REM_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_RSH_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_SUB_CALL; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_BOOLEAN; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_BYTE_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_BYTE_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_CHAR_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_CHAR_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_DOUBLE_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_DOUBLE_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_FLOAT_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_FLOAT_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_INT_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_INT_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_LONG_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_LONG_IMPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_SHORT_EXPLICIT; +import static org.elasticsearch.painless.WriterConstants.DEF_TO_SHORT_IMPLICIT; import static org.elasticsearch.painless.WriterConstants.DEF_USH_CALL; +import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE; import static org.elasticsearch.painless.WriterConstants.DEF_XOR_CALL; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_INT; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_LONG; import static org.elasticsearch.painless.WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE; import static org.elasticsearch.painless.WriterConstants.MAX_INDY_STRING_CONCAT_ARGS; -import static org.elasticsearch.painless.WriterConstants.MULEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.MULEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.MULWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.MULWOOVERLOW_FLOAT; import static org.elasticsearch.painless.WriterConstants.PAINLESS_ERROR_TYPE; -import static org.elasticsearch.painless.WriterConstants.REMWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.REMWOOVERLOW_FLOAT; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_BOOLEAN; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_CHAR; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_DOUBLE; @@ -73,29 +75,9 @@ import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_ST import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_CONSTRUCTOR; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_TOSTRING; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_TYPE; +import static org.elasticsearch.painless.WriterConstants.STRING_TO_CHAR; import static org.elasticsearch.painless.WriterConstants.STRING_TYPE; -import static org.elasticsearch.painless.WriterConstants.SUBEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.SUBEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.SUBWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.SUBWOOVERLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOBYTEEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOBYTEEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOBYTEWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOBYTEWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOCHAREXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOCHAREXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOCHARWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOCHARWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOFLOATWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOINTEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOINTWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOINTWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOLONGWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOLONGWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOSHORTEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOSHORTEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOSHORTWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOSHORTWOOVERFLOW_FLOAT; +import static org.elasticsearch.painless.WriterConstants.UTILITY_TYPE; /** * Extension of {@link GeneratorAdapter} with some utility methods. @@ -132,49 +114,84 @@ public final class MethodWriter extends GeneratorAdapter { visitVarInsn(Opcodes.ILOAD, slot); push(0); ifICmp(GeneratorAdapter.GT, end); - throwException(PAINLESS_ERROR_TYPE, - "The maximum number of statements that can be executed in a loop has been reached."); + throwException(PAINLESS_ERROR_TYPE, "The maximum number of statements that can be executed in a loop has been reached."); mark(end); } } public void writeCast(final Cast cast) { - if (cast instanceof Transform) { - final Transform transform = (Transform)cast; - - if (transform.upcast != null) { - checkCast(transform.upcast.type); - } - - if (java.lang.reflect.Modifier.isStatic(transform.method.reflect.getModifiers())) { - invokeStatic(transform.method.owner.type, transform.method.method); - } else if (java.lang.reflect.Modifier.isInterface(transform.method.owner.clazz.getModifiers())) { - invokeInterface(transform.method.owner.type, transform.method.method); - } else { - invokeVirtual(transform.method.owner.type, transform.method.method); - } - - if (transform.downcast != null) { - checkCast(transform.downcast.type); - } - } else if (cast != null) { + if (cast != null) { final Type from = cast.from; final Type to = cast.to; - if (from.equals(to)) { - return; - } - - if (from.sort.numeric && from.sort.primitive && to.sort.numeric && to.sort.primitive) { - cast(from.type, to.type); - } else { - if (!to.clazz.isAssignableFrom(from.clazz)) { - checkCast(to.type); + if (from.sort == Sort.CHAR && to.sort == Sort.STRING) { + invokeStatic(UTILITY_TYPE, CHAR_TO_STRING); + } else if (from.sort == Sort.STRING && to.sort == Sort.CHAR) { + invokeStatic(UTILITY_TYPE, STRING_TO_CHAR); + } else if (cast.unboxFrom) { + if (from.sort == Sort.DEF) { + if (cast.explicit) { + if (to.sort == Sort.BOOL) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN); + else if (to.sort == Sort.BYTE) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_EXPLICIT); + else if (to.sort == Sort.SHORT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_EXPLICIT); + else if (to.sort == Sort.CHAR) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_EXPLICIT); + else if (to.sort == Sort.INT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_EXPLICIT); + else if (to.sort == Sort.LONG) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_EXPLICIT); + else if (to.sort == Sort.FLOAT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_EXPLICIT); + else if (to.sort == Sort.DOUBLE) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_EXPLICIT); + else throw new IllegalStateException("Illegal tree structure."); + } else { + if (to.sort == Sort.BOOL) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN); + else if (to.sort == Sort.BYTE) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_IMPLICIT); + else if (to.sort == Sort.SHORT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_IMPLICIT); + else if (to.sort == Sort.CHAR) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_IMPLICIT); + else if (to.sort == Sort.INT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_IMPLICIT); + else if (to.sort == Sort.LONG) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_IMPLICIT); + else if (to.sort == Sort.FLOAT) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_IMPLICIT); + else if (to.sort == Sort.DOUBLE) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_IMPLICIT); + else throw new IllegalStateException("Illegal tree structure."); + } + } else { + unbox(from.type); + writeCast(from, to); } + } else if (cast.unboxTo) { + writeCast(from, to); + unbox(to.type); + } else if (cast.boxFrom) { + box(from.type); + writeCast(from, to); + } else if (cast.boxTo) { + writeCast(from, to); + box(to.type); + } else { + writeCast(from, to); } } } + private void writeCast(final Type from, final Type to) { + if (from.equals(to)) { + return; + } + + if (from.sort.numeric && from.sort.primitive && to.sort.numeric && to.sort.primitive) { + cast(from.type, to.type); + } else { + if (!to.clazz.isAssignableFrom(from.clazz)) { + checkCast(to.type); + } + } + } + + /** + * Proxy the box method to use valueOf instead to ensure that the modern boxing methods are used. + */ + @Override + public void box(org.objectweb.asm.Type type) { + valueOf(type); + } + public void writeBranch(final Label tru, final Label fals) { if (tru != null) { visitJumpInsn(Opcodes.IFNE, tru); @@ -182,7 +199,7 @@ public final class MethodWriter extends GeneratorAdapter { visitJumpInsn(Opcodes.IFEQ, fals); } } - + public void writeNewStrings() { if (INDY_STRING_CONCAT_BOOTSTRAP_HANDLE != null) { // Java 9+: we just push our argument collector onto deque @@ -236,231 +253,51 @@ public final class MethodWriter extends GeneratorAdapter { } } - public void writeBinaryInstruction(final CompilerSettings settings, final Definition definition, - final String location, - final Type type, final Operation operation) { + public void writeBinaryInstruction(final String location, final Type type, final Operation operation) { final Sort sort = type.sort; - boolean exact = !settings.getNumericOverflow() && - ((sort == Sort.INT || sort == Sort.LONG) && - (operation == Operation.MUL || operation == Operation.DIV || - operation == Operation.ADD || operation == Operation.SUB) || - (sort == Sort.FLOAT || sort == Sort.DOUBLE) && - (operation == Operation.MUL || operation == Operation.DIV || operation == Operation.REM || - operation == Operation.ADD || operation == Operation.SUB)); - if (exact) { - switch (sort) { - case INT: - switch (operation) { - case MUL: invokeStatic(definition.mathType.type, MULEXACT_INT); break; - case DIV: invokeStatic(definition.utilityType.type, DIVWOOVERLOW_INT); break; - case ADD: invokeStatic(definition.mathType.type, ADDEXACT_INT); break; - case SUB: invokeStatic(definition.mathType.type, SUBEXACT_INT); break; - } + if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) && + (operation == Operation.LSH || operation == Operation.USH || + operation == Operation.RSH || operation == Operation.BWAND || + operation == Operation.XOR || operation == Operation.BWOR)) { + throw new IllegalStateException("Error " + location + ": Illegal tree structure."); + } - break; - case LONG: - switch (operation) { - case MUL: invokeStatic(definition.mathType.type, MULEXACT_LONG); break; - case DIV: invokeStatic(definition.utilityType.type, DIVWOOVERLOW_LONG); break; - case ADD: invokeStatic(definition.mathType.type, ADDEXACT_LONG); break; - case SUB: invokeStatic(definition.mathType.type, SUBEXACT_LONG); break; - } - - break; - case FLOAT: - switch (operation) { - case MUL: invokeStatic(definition.utilityType.type, MULWOOVERLOW_FLOAT); break; - case DIV: invokeStatic(definition.utilityType.type, DIVWOOVERLOW_FLOAT); break; - case REM: invokeStatic(definition.utilityType.type, REMWOOVERLOW_FLOAT); break; - case ADD: invokeStatic(definition.utilityType.type, ADDWOOVERLOW_FLOAT); break; - case SUB: invokeStatic(definition.utilityType.type, SUBWOOVERLOW_FLOAT); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - break; - case DOUBLE: - switch (operation) { - case MUL: invokeStatic(definition.utilityType.type, MULWOOVERLOW_DOUBLE); break; - case DIV: invokeStatic(definition.utilityType.type, DIVWOOVERLOW_DOUBLE); break; - case REM: invokeStatic(definition.utilityType.type, REMWOOVERLOW_DOUBLE); break; - case ADD: invokeStatic(definition.utilityType.type, ADDWOOVERLOW_DOUBLE); break; - case SUB: invokeStatic(definition.utilityType.type, SUBWOOVERLOW_DOUBLE); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - break; + if (sort == Sort.DEF) { + switch (operation) { + case MUL: invokeStatic(DEF_UTIL_TYPE, DEF_MUL_CALL); break; + case DIV: invokeStatic(DEF_UTIL_TYPE, DEF_DIV_CALL); break; + case REM: invokeStatic(DEF_UTIL_TYPE, DEF_REM_CALL); break; + case ADD: invokeStatic(DEF_UTIL_TYPE, DEF_ADD_CALL); break; + case SUB: invokeStatic(DEF_UTIL_TYPE, DEF_SUB_CALL); break; + case LSH: invokeStatic(DEF_UTIL_TYPE, DEF_LSH_CALL); break; + case USH: invokeStatic(DEF_UTIL_TYPE, DEF_RSH_CALL); break; + case RSH: invokeStatic(DEF_UTIL_TYPE, DEF_USH_CALL); break; + case BWAND: invokeStatic(DEF_UTIL_TYPE, DEF_AND_CALL); break; + case XOR: invokeStatic(DEF_UTIL_TYPE, DEF_XOR_CALL); break; + case BWOR: invokeStatic(DEF_UTIL_TYPE, DEF_OR_CALL); break; default: throw new IllegalStateException("Error " + location + ": Illegal tree structure."); } } else { - if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) && - (operation == Operation.LSH || operation == Operation.USH || - operation == Operation.RSH || operation == Operation.BWAND || - operation == Operation.XOR || operation == Operation.BWOR)) { - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - if (sort == Sort.DEF) { - switch (operation) { - case MUL: invokeStatic(definition.defobjType.type, DEF_MUL_CALL); break; - case DIV: invokeStatic(definition.defobjType.type, DEF_DIV_CALL); break; - case REM: invokeStatic(definition.defobjType.type, DEF_REM_CALL); break; - case ADD: invokeStatic(definition.defobjType.type, DEF_ADD_CALL); break; - case SUB: invokeStatic(definition.defobjType.type, DEF_SUB_CALL); break; - case LSH: invokeStatic(definition.defobjType.type, DEF_LSH_CALL); break; - case USH: invokeStatic(definition.defobjType.type, DEF_RSH_CALL); break; - case RSH: invokeStatic(definition.defobjType.type, DEF_USH_CALL); break; - case BWAND: invokeStatic(definition.defobjType.type, DEF_AND_CALL); break; - case XOR: invokeStatic(definition.defobjType.type, DEF_XOR_CALL); break; - case BWOR: invokeStatic(definition.defobjType.type, DEF_OR_CALL); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - } else { - switch (operation) { - case MUL: math(GeneratorAdapter.MUL, type.type); break; - case DIV: math(GeneratorAdapter.DIV, type.type); break; - case REM: math(GeneratorAdapter.REM, type.type); break; - case ADD: math(GeneratorAdapter.ADD, type.type); break; - case SUB: math(GeneratorAdapter.SUB, type.type); break; - case LSH: math(GeneratorAdapter.SHL, type.type); break; - case USH: math(GeneratorAdapter.USHR, type.type); break; - case RSH: math(GeneratorAdapter.SHR, type.type); break; - case BWAND: math(GeneratorAdapter.AND, type.type); break; - case XOR: math(GeneratorAdapter.XOR, type.type); break; - case BWOR: math(GeneratorAdapter.OR, type.type); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } + switch (operation) { + case MUL: math(GeneratorAdapter.MUL, type.type); break; + case DIV: math(GeneratorAdapter.DIV, type.type); break; + case REM: math(GeneratorAdapter.REM, type.type); break; + case ADD: math(GeneratorAdapter.ADD, type.type); break; + case SUB: math(GeneratorAdapter.SUB, type.type); break; + case LSH: math(GeneratorAdapter.SHL, type.type); break; + case USH: math(GeneratorAdapter.USHR, type.type); break; + case RSH: math(GeneratorAdapter.SHR, type.type); break; + case BWAND: math(GeneratorAdapter.AND, type.type); break; + case XOR: math(GeneratorAdapter.XOR, type.type); break; + case BWOR: math(GeneratorAdapter.OR, type.type); break; + default: + throw new IllegalStateException("Error " + location + ": Illegal tree structure."); } } } - /** - * Called for any compound assignment (including increment/decrement instructions). - * We have to be stricter than writeBinary and do overflow checks against the original type's size - * instead of the promoted type's size, since the result will be implicitly cast back. - * - * @return This will be true if an instruction is written, false otherwise. - */ - public boolean writeExactInstruction( - final Definition definition, final Sort fsort, final Sort tsort) { - if (fsort == Sort.DOUBLE) { - if (tsort == Sort.FLOAT) { - invokeStatic(definition.utilityType.type, TOFLOATWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.FLOAT_OBJ) { - invokeStatic(definition.utilityType.type, TOFLOATWOOVERFLOW_DOUBLE); - checkCast(definition.floatobjType.type); - } else if (tsort == Sort.LONG) { - invokeStatic(definition.utilityType.type, TOLONGWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.LONG_OBJ) { - invokeStatic(definition.utilityType.type, TOLONGWOOVERFLOW_DOUBLE); - checkCast(definition.longobjType.type); - } else if (tsort == Sort.INT) { - invokeStatic(definition.utilityType.type, TOINTWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.utilityType.type, TOINTWOOVERFLOW_DOUBLE); - checkCast(definition.intobjType.type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.utilityType.type, TOCHARWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.utilityType.type, TOCHARWOOVERFLOW_DOUBLE); - checkCast(definition.charobjType.type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.utilityType.type, TOSHORTWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.utilityType.type, TOSHORTWOOVERFLOW_DOUBLE); - checkCast(definition.shortobjType.type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.utilityType.type, TOBYTEWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.utilityType.type, TOBYTEWOOVERFLOW_DOUBLE); - checkCast(definition.byteobjType.type); - } else { - return false; - } - } else if (fsort == Sort.FLOAT) { - if (tsort == Sort.LONG) { - invokeStatic(definition.utilityType.type, TOLONGWOOVERFLOW_FLOAT); - } else if (tsort == Sort.LONG_OBJ) { - invokeStatic(definition.utilityType.type, TOLONGWOOVERFLOW_FLOAT); - checkCast(definition.longobjType.type); - } else if (tsort == Sort.INT) { - invokeStatic(definition.utilityType.type, TOINTWOOVERFLOW_FLOAT); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.utilityType.type, TOINTWOOVERFLOW_FLOAT); - checkCast(definition.intobjType.type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.utilityType.type, TOCHARWOOVERFLOW_FLOAT); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.utilityType.type, TOCHARWOOVERFLOW_FLOAT); - checkCast(definition.charobjType.type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.utilityType.type, TOSHORTWOOVERFLOW_FLOAT); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.utilityType.type, TOSHORTWOOVERFLOW_FLOAT); - checkCast(definition.shortobjType.type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.utilityType.type, TOBYTEWOOVERFLOW_FLOAT); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.utilityType.type, TOBYTEWOOVERFLOW_FLOAT); - checkCast(definition.byteobjType.type); - } else { - return false; - } - } else if (fsort == Sort.LONG) { - if (tsort == Sort.INT) { - invokeStatic(definition.mathType.type, TOINTEXACT_LONG); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.mathType.type, TOINTEXACT_LONG); - checkCast(definition.intobjType.type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.utilityType.type, TOCHAREXACT_LONG); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.utilityType.type, TOCHAREXACT_LONG); - checkCast(definition.charobjType.type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.utilityType.type, TOSHORTEXACT_LONG); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.utilityType.type, TOSHORTEXACT_LONG); - checkCast(definition.shortobjType.type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.utilityType.type, TOBYTEEXACT_LONG); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.utilityType.type, TOBYTEEXACT_LONG); - checkCast(definition.byteobjType.type); - } else { - return false; - } - } else if (fsort == Sort.INT) { - if (tsort == Sort.CHAR) { - invokeStatic(definition.utilityType.type, TOCHAREXACT_INT); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.utilityType.type, TOCHAREXACT_INT); - checkCast(definition.charobjType.type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.utilityType.type, TOSHORTEXACT_INT); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.utilityType.type, TOSHORTEXACT_INT); - checkCast(definition.shortobjType.type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.utilityType.type, TOBYTEEXACT_INT); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.utilityType.type, TOBYTEEXACT_INT); - checkCast(definition.byteobjType.type); - } else { - return false; - } - } else { - return false; - } - - return true; - } - public void writeDup(final int size, final int xsize) { if (size == 1) { if (xsize == 2) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java index e5998948d62..8f116c3c6f7 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java @@ -19,6 +19,7 @@ package org.elasticsearch.painless; + import org.elasticsearch.plugins.Plugin; import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptMode; @@ -29,6 +30,11 @@ import org.elasticsearch.script.ScriptModule; */ public final class PainlessPlugin extends Plugin { + // force to pare our definition at startup (not on the user's first script) + static { + Definition.VOID_TYPE.hashCode(); + } + @Override public String name() { return "lang-painless"; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java index dafc6aaba8a..72a657cd7f0 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java @@ -38,9 +38,7 @@ import java.security.AccessController; import java.security.Permissions; import java.security.PrivilegedAction; import java.security.ProtectionDomain; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -117,13 +115,7 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme // Use custom settings specified by params. compilerSettings = new CompilerSettings(); Map copy = new HashMap<>(params); - String value = copy.remove(CompilerSettings.NUMERIC_OVERFLOW); - - if (value != null) { - compilerSettings.setNumericOverflow(Boolean.parseBoolean(value)); - } - - value = copy.remove(CompilerSettings.MAX_LOOP_COUNTER); + String value = copy.remove(CompilerSettings.MAX_LOOP_COUNTER); if (value != null) { compilerSettings.setMaxLoopCounter(Integer.parseInt(value)); @@ -212,7 +204,7 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme * Action taken when the engine is closed. */ @Override - public void close() throws IOException { + public void close() { // Nothing to do. } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java index 32641649827..5ab3450db7e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java @@ -25,442 +25,10 @@ package org.elasticsearch.painless; */ public class Utility { - public static boolean NumberToboolean(final Number value) { - return value.longValue() != 0; - } - - public static char NumberTochar(final Number value) { - return (char)value.intValue(); - } - - public static Boolean NumberToBoolean(final Number value) { - return value.longValue() != 0; - } - - public static Byte NumberToByte(final Number value) { - return value == null ? null : value.byteValue(); - } - - public static Short NumberToShort(final Number value) { - return value == null ? null : value.shortValue(); - } - - public static Character NumberToCharacter(final Number value) { - return value == null ? null : (char)value.intValue(); - } - - public static Integer NumberToInteger(final Number value) { - return value == null ? null : value.intValue(); - } - - public static Long NumberToLong(final Number value) { - return value == null ? null : value.longValue(); - } - - public static Float NumberToFloat(final Number value) { - return value == null ? null : value.floatValue(); - } - - public static Double NumberToDouble(final Number value) { - return value == null ? null : value.doubleValue(); - } - - public static byte booleanTobyte(final boolean value) { - return (byte)(value ? 1 : 0); - } - - public static short booleanToshort(final boolean value) { - return (short)(value ? 1 : 0); - } - - public static char booleanTochar(final boolean value) { - return (char)(value ? 1 : 0); - } - - public static int booleanToint(final boolean value) { - return value ? 1 : 0; - } - - public static long booleanTolong(final boolean value) { - return value ? 1 : 0; - } - - public static float booleanTofloat(final boolean value) { - return value ? 1 : 0; - } - - public static double booleanTodouble(final boolean value) { - return value ? 1 : 0; - } - - public static Integer booleanToInteger(final boolean value) { - return value ? 1 : 0; - } - - public static byte BooleanTobyte(final Boolean value) { - return (byte)(value ? 1 : 0); - } - - public static short BooleanToshort(final Boolean value) { - return (short)(value ? 1 : 0); - } - - public static char BooleanTochar(final Boolean value) { - return (char)(value ? 1 : 0); - } - - public static int BooleanToint(final Boolean value) { - return value ? 1 : 0; - } - - public static long BooleanTolong(final Boolean value) { - return value ? 1 : 0; - } - - public static float BooleanTofloat(final Boolean value) { - return value ? 1 : 0; - } - - public static double BooleanTodouble(final Boolean value) { - return value ? 1 : 0; - } - - public static Byte BooleanToByte(final Boolean value) { - return value == null ? null : (byte)(value ? 1 : 0); - } - - public static Short BooleanToShort(final Boolean value) { - return value == null ? null : (short)(value ? 1 : 0); - } - - public static Character BooleanToCharacter(final Boolean value) { - return value == null ? null : (char)(value ? 1 : 0); - } - - public static Integer BooleanToInteger(final Boolean value) { - return value == null ? null : value ? 1 : 0; - } - - public static Long BooleanToLong(final Boolean value) { - return value == null ? null : value ? 1L : 0L; - } - - public static Float BooleanToFloat(final Boolean value) { - return value == null ? null : value ? 1F : 0F; - } - - public static Double BooleanToDouble(final Boolean value) { - return value == null ? null : value ? 1D : 0D; - } - - public static boolean byteToboolean(final byte value) { - return value != 0; - } - - public static Short byteToShort(final byte value) { - return (short)value; - } - - public static Character byteToCharacter(final byte value) { - return (char)value; - } - - public static Integer byteToInteger(final byte value) { - return (int)value; - } - - public static Long byteToLong(final byte value) { - return (long)value; - } - - public static Float byteToFloat(final byte value) { - return (float)value; - } - - public static Double byteToDouble(final byte value) { - return (double)value; - } - - public static boolean ByteToboolean(final Byte value) { - return value != 0; - } - - public static char ByteTochar(final Byte value) { - return (char)value.byteValue(); - } - - public static boolean shortToboolean(final short value) { - return value != 0; - } - - public static Byte shortToByte(final short value) { - return (byte)value; - } - - public static Character shortToCharacter(final short value) { - return (char)value; - } - - public static Integer shortToInteger(final short value) { - return (int)value; - } - - public static Long shortToLong(final short value) { - return (long)value; - } - - public static Float shortToFloat(final short value) { - return (float)value; - } - - public static Double shortToDouble(final short value) { - return (double)value; - } - - public static boolean ShortToboolean(final Short value) { - return value != 0; - } - - public static char ShortTochar(final Short value) { - return (char)value.shortValue(); - } - - public static boolean charToboolean(final char value) { - return value != 0; - } - - public static Byte charToByte(final char value) { - return (byte)value; - } - - public static Short charToShort(final char value) { - return (short)value; - } - - public static Integer charToInteger(final char value) { - return (int)value; - } - - public static Long charToLong(final char value) { - return (long)value; - } - - public static Float charToFloat(final char value) { - return (float)value; - } - - public static Double charToDouble(final char value) { - return (double)value; - } - public static String charToString(final char value) { return String.valueOf(value); } - public static boolean CharacterToboolean(final Character value) { - return value != 0; - } - - public static byte CharacterTobyte(final Character value) { - return (byte)value.charValue(); - } - - public static short CharacterToshort(final Character value) { - return (short)value.charValue(); - } - - public static int CharacterToint(final Character value) { - return value; - } - - public static long CharacterTolong(final Character value) { - return value; - } - - public static float CharacterTofloat(final Character value) { - return value; - } - - public static double CharacterTodouble(final Character value) { - return value; - } - - public static Boolean CharacterToBoolean(final Character value) { - return value == null ? null : value != 0; - } - - public static Byte CharacterToByte(final Character value) { - return value == null ? null : (byte)value.charValue(); - } - - public static Short CharacterToShort(final Character value) { - return value == null ? null : (short)value.charValue(); - } - - public static Integer CharacterToInteger(final Character value) { - return value == null ? null : (int)value; - } - - public static Long CharacterToLong(final Character value) { - return value == null ? null : (long)value; - } - - public static Float CharacterToFloat(final Character value) { - return value == null ? null : (float)value; - } - - public static Double CharacterToDouble(final Character value) { - return value == null ? null : (double)value; - } - - public static String CharacterToString(final Character value) { - return value == null ? null : value.toString(); - } - - public static boolean intToboolean(final int value) { - return value != 0; - } - - public static Byte intToByte(final int value) { - return (byte)value; - } - - public static Short intToShort(final int value) { - return (short)value; - } - - public static Character intToCharacter(final int value) { - return (char)value; - } - - public static Long intToLong(final int value) { - return (long)value; - } - - public static Float intToFloat(final int value) { - return (float)value; - } - - public static Double intToDouble(final int value) { - return (double)value; - } - - public static boolean IntegerToboolean(final Integer value) { - return value != 0; - } - - public static char IntegerTochar(final Integer value) { - return (char)value.intValue(); - } - - public static boolean longToboolean(final long value) { - return value != 0; - } - - public static Byte longToByte(final long value) { - return (byte)value; - } - - public static Short longToShort(final long value) { - return (short)value; - } - - public static Character longToCharacter(final long value) { - return (char)value; - } - - public static Integer longToInteger(final long value) { - return (int)value; - } - - public static Float longToFloat(final long value) { - return (float)value; - } - - public static Double longToDouble(final long value) { - return (double)value; - } - - public static boolean LongToboolean(final Long value) { - return value != 0; - } - - public static char LongTochar(final Long value) { - return (char)value.longValue(); - } - - public static boolean floatToboolean(final float value) { - return value != 0; - } - - public static Byte floatToByte(final float value) { - return (byte)value; - } - - public static Short floatToShort(final float value) { - return (short)value; - } - - public static Character floatToCharacter(final float value) { - return (char)value; - } - - public static Integer floatToInteger(final float value) { - return (int)value; - } - - public static Long floatToLong(final float value) { - return (long)value; - } - - public static Double floatToDouble(final float value) { - return (double)value; - } - - public static boolean FloatToboolean(final Float value) { - return value != 0; - } - - public static char FloatTochar(final Float value) { - return (char)value.floatValue(); - } - - public static boolean doubleToboolean(final double value) { - return value != 0; - } - - public static Byte doubleToByte(final double value) { - return (byte)value; - } - - public static Short doubleToShort(final double value) { - return (short)value; - } - - public static Character doubleToCharacter(final double value) { - return (char)value; - } - - public static Integer doubleToInteger(final double value) { - return (int)value; - } - - public static Long doubleToLong(final double value) { - return (long)value; - } - - public static Float doubleToFloat(final double value) { - return (float)value; - } - - public static boolean DoubleToboolean(final Double value) { - return value != 0; - } - - public static char DoubleTochar(final Double value) { - return (char)value.doubleValue(); - } - public static char StringTochar(final String value) { if (value.length() != 1) { throw new ClassCastException("Cannot cast [String] with length greater than one to [char]."); @@ -469,359 +37,6 @@ public class Utility { return value.charAt(0); } - public static Character StringToCharacter(final String value) { - if (value == null) { - return null; - } - - if (value.length() != 1) { - throw new ClassCastException("Cannot cast [String] with length greater than one to [Character]."); - } - - return value.charAt(0); - } - - // although divide by zero is guaranteed, the special overflow case is not caught. - // its not needed for remainder because it is not possible there. - // see https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.17.2 - - /** - * Integer divide without overflow - * @throws ArithmeticException on overflow or divide-by-zero - */ - public static int divideWithoutOverflow(int x, int y) { - if (x == Integer.MIN_VALUE && y == -1) { - throw new ArithmeticException("integer overflow"); - } - return x / y; - } - - /** - * Long divide without overflow - * @throws ArithmeticException on overflow or divide-by-zero - */ - public static long divideWithoutOverflow(long x, long y) { - if (x == Long.MIN_VALUE && y == -1L) { - throw new ArithmeticException("long overflow"); - } - return x / y; - } - - // byte, short, and char are promoted to int for normal operations, - // so the JDK exact methods are typically used, and the result has a wider range. - // but compound assignments and increment/decrement operators (e.g. byte b = Byte.MAX_VALUE; b++;) - // implicitly cast back to the original type: so these need to be checked against the original range. - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteExact(int value) { - byte s = (byte) value; - if (s != value) { - throw new ArithmeticException("byte overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteExact(long value) { - byte s = (byte) value; - if (s != value) { - throw new ArithmeticException("byte overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteWithoutOverflow(float value) { - if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { - throw new ArithmeticException("byte overflow"); - } - return (byte)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteWithoutOverflow(double value) { - if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { - throw new ArithmeticException("byte overflow"); - } - return (byte)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(int value) { - short s = (short) value; - if (s != value) { - throw new ArithmeticException("short overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(long value) { - short s = (short) value; - if (s != value) { - throw new ArithmeticException("short overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortWithoutOverflow(float value) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { - throw new ArithmeticException("short overflow"); - } - return (short)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(double value) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { - throw new ArithmeticException("short overflow"); - } - return (short)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharExact(int value) { - char s = (char) value; - if (s != value) { - throw new ArithmeticException("char overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharExact(long value) { - char s = (char) value; - if (s != value) { - throw new ArithmeticException("char overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharWithoutOverflow(float value) { - if (value < Character.MIN_VALUE || value > Character.MAX_VALUE) { - throw new ArithmeticException("char overflow"); - } - return (char)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharWithoutOverflow(double value) { - if (value < Character.MIN_VALUE || value > Character.MAX_VALUE) { - throw new ArithmeticException("char overflow"); - } - return (char)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for int range. - */ - public static int toIntWithoutOverflow(float value) { - if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - throw new ArithmeticException("int overflow"); - } - return (int)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for int range. - */ - public static int toIntWithoutOverflow(double value) { - if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - throw new ArithmeticException("int overflow"); - } - return (int)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for long range. - */ - public static long toLongWithoutOverflow(float value) { - if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) { - throw new ArithmeticException("long overflow"); - } - return (long)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for long range. - */ - public static float toLongWithoutOverflow(double value) { - if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) { - throw new ArithmeticException("long overflow"); - } - return (long)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for float range. - */ - public static float toFloatWithoutOverflow(double value) { - if (value < Float.MIN_VALUE || value > Float.MAX_VALUE) { - throw new ArithmeticException("float overflow"); - } - return (float)value; - } - - /** - * Checks for overflow, result is infinite but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static float checkInfFloat(float x, float y, float z) { - if (Float.isInfinite(z)) { - if (Float.isFinite(x) && Float.isFinite(y)) { - throw new ArithmeticException("float overflow"); - } - } - return z; - } - - /** - * Checks for NaN, result is NaN but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static float checkNaNFloat(float x, float y, float z) { - if (Float.isNaN(z)) { - if (Float.isFinite(x) && Float.isFinite(y)) { - throw new ArithmeticException("NaN"); - } - } - return z; - } - - /** - * Checks for NaN, result is infinite but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static double checkInfDouble(double x, double y, double z) { - if (Double.isInfinite(z)) { - if (Double.isFinite(x) && Double.isFinite(y)) { - throw new ArithmeticException("double overflow"); - } - } - return z; - } - - /** - * Checks for NaN, result is NaN but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static double checkNaNDouble(double x, double y, double z) { - if (Double.isNaN(z)) { - if (Double.isFinite(x) && Double.isFinite(y)) { - throw new ArithmeticException("NaN"); - } - } - return z; - } - - /** - * Adds two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float addWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x + y); - } - - /** - * Adds two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double addWithoutOverflow(double x, double y) { - return checkInfDouble(x, y, x + y); - } - - /** - * Subtracts two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float subtractWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x - y); - } - - /** - * Subtracts two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double subtractWithoutOverflow(double x, double y) { - return checkInfDouble(x, y , x - y); - } - - /** - * Multiplies two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float multiplyWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x * y); - } - - /** - * Multiplies two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double multiplyWithoutOverflow(double x, double y) { - return checkInfDouble(x, y, x * y); - } - - /** - * Divides two floats but throws {@code ArithmeticException} - * if the result overflows, or would create NaN from finite - * inputs ({@code x == 0, y == 0}) - */ - public static float divideWithoutOverflow(float x, float y) { - return checkNaNFloat(x, y, checkInfFloat(x, y, x / y)); - } - - /** - * Divides two doubles but throws {@code ArithmeticException} - * if the result overflows, or would create NaN from finite - * inputs ({@code x == 0, y == 0}) - */ - public static double divideWithoutOverflow(double x, double y) { - return checkNaNDouble(x, y, checkInfDouble(x, y, x / y)); - } - - /** - * Takes remainder two floats but throws {@code ArithmeticException} - * if the result would create NaN from finite inputs ({@code y == 0}) - */ - public static float remainderWithoutOverflow(float x, float y) { - return checkNaNFloat(x, y, x % y); - } - - /** - * Divides two doubles but throws {@code ArithmeticException} - * if the result would create NaN from finite inputs ({@code y == 0}) - */ - public static double remainderWithoutOverflow(double x, double y) { - return checkNaNDouble(x, y, x % y); - } - public static boolean checkEquals(final Object left, final Object right) { if (left != null) { return left.equals(right); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java index adf930b017c..28a7416d800 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java @@ -86,14 +86,12 @@ public final class Variables { } } - private final Definition definition; final Reserved reserved; private final Deque scopes = new ArrayDeque<>(); private final Deque variables = new ArrayDeque<>(); - public Variables(final CompilerSettings settings, final Definition definition, final Reserved reserved) { - this.definition = definition; + public Variables(final CompilerSettings settings, final Reserved reserved) { this.reserved = reserved; incrementScope(); @@ -101,35 +99,35 @@ public final class Variables { // Method variables. // This reference. Internal use only. - addVariable("[" + Reserved.THIS + "]" , definition.execType.name, Reserved.THIS , true, true); + addVariable("[" + Reserved.THIS + "]" , "Executable", Reserved.THIS , true, true); // Input map of variables passed to the script. TODO: Rename to 'params' since that will be its use. - addVariable("[" + Reserved.PARAMS + "]", definition.smapType.name, Reserved.PARAMS, true, true); + addVariable("[" + Reserved.PARAMS + "]", "Map", Reserved.PARAMS, true, true); // Scorer parameter passed to the script. Internal use only. - addVariable("[" + Reserved.SCORER + "]", definition.defType.name , Reserved.SCORER, true, true); + addVariable("[" + Reserved.SCORER + "]", "def", Reserved.SCORER, true, true); - // Doc parameter passed to the script. TODO: Currently working as a Map, we can do better? - addVariable("[" + Reserved.DOC + "]" , definition.smapType.name, Reserved.DOC , true, true); + // Doc parameter passed to the script. TODO: Currently working as a Map, we can do better? + addVariable("[" + Reserved.DOC + "]" , "Map", Reserved.DOC , true, true); // Aggregation _value parameter passed to the script. - addVariable("[" + Reserved.VALUE + "]" , definition.defType.name , Reserved.VALUE , true, true); + addVariable("[" + Reserved.VALUE + "]" , "def", Reserved.VALUE , true, true); // Shortcut variables. // Document's score as a read-only double. if (reserved.score) { - addVariable("[" + Reserved.SCORE + "]", definition.doubleType.name, Reserved.SCORE, true, true); + addVariable("[" + Reserved.SCORE + "]", "double", Reserved.SCORE, true, true); } // The ctx map set by executable scripts as a read-only map. if (reserved.ctx) { - addVariable("[" + Reserved.CTX + "]", definition.smapType.name, Reserved.CTX, true, true); + addVariable("[" + Reserved.CTX + "]", "Map", Reserved.CTX, true, true); } // Loop counter to catch infinite loops. Internal use only. if (reserved.loop && settings.getMaxLoopCounter() > 0) { - addVariable("[" + Reserved.LOOP + "]", definition.intType.name, Reserved.LOOP, true, true); + addVariable("[" + Reserved.LOOP + "]", "int", Reserved.LOOP, true, true); } } @@ -182,7 +180,7 @@ public final class Variables { final Type type; try { - type = definition.getType(typestr); + type = Definition.getType(typestr); } catch (final IllegalArgumentException exception) { throw new IllegalArgumentException("Error " + location + ": Not a type [" + typestr + "]."); } @@ -190,7 +188,7 @@ public final class Variables { boolean legal = !name.contains("<"); try { - definition.getType(name); + Definition.getType(name); legal = false; } catch (final IllegalArgumentException exception) { // Do nothing. diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java index 449361867b9..6e2d0e1431b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java @@ -38,15 +38,14 @@ import static org.elasticsearch.painless.WriterConstants.MAP_TYPE; */ final class Writer { - static byte[] write(final CompilerSettings settings, final Definition definition, + static byte[] write(final CompilerSettings settings, String name, final String source, final Variables variables, final SSource root) { - final Writer writer = new Writer(settings, definition, name, source, variables, root); + final Writer writer = new Writer(settings, name, source, variables, root); return writer.getBytes(); } private final CompilerSettings settings; - private final Definition definition; private final String scriptName; private final String source; private final Variables variables; @@ -55,10 +54,9 @@ final class Writer { private final ClassWriter writer; private final MethodWriter adapter; - private Writer(final CompilerSettings settings, final Definition definition, + private Writer(final CompilerSettings settings, String name, final String source, final Variables variables, final SSource root) { this.settings = settings; - this.definition = definition; this.scriptName = name; this.source = source; this.variables = variables; @@ -117,7 +115,7 @@ final class Writer { // if we truncated, make it obvious if (limit != source.length()) { fileName.append(" ..."); - } + } fileName.append(" @ "); } else { // its a named script, just use the name @@ -177,7 +175,7 @@ final class Writer { adapter.visitVarInsn(Opcodes.ISTORE, loop.slot); } - root.write(settings, definition, adapter); + root.write(adapter); adapter.endMethod(); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java index 6bdb9856114..410c06e6fd7 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java @@ -27,7 +27,6 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Map; @@ -39,7 +38,7 @@ public final class WriterConstants { public final static String BASE_CLASS_NAME = Executable.class.getName(); public final static Type BASE_CLASS_TYPE = Type.getType(Executable.class); - + public final static String CLASS_NAME = BASE_CLASS_NAME + "$Script"; public final static Type CLASS_TYPE = Type.getObjectType(CLASS_NAME.replace('.', '/')); @@ -56,6 +55,10 @@ public final class WriterConstants { public final static Type MAP_TYPE = Type.getType(Map.class); public final static Method MAP_GET = getAsmMethod(Object.class, "get", Object.class); + public final static Type UTILITY_TYPE = Type.getType(Utility.class); + public final static Method STRING_TO_CHAR = getAsmMethod(char.class, "StringTochar", String.class); + public final static Method CHAR_TO_STRING = getAsmMethod(String.class, "charToString", char.class); + /** dynamic callsite bootstrap signature */ public final static MethodType DEF_BOOTSTRAP_TYPE = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class); @@ -63,19 +66,35 @@ public final class WriterConstants { new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(DefBootstrap.class), "bootstrap", DEF_BOOTSTRAP_TYPE.toMethodDescriptorString()); - public final static Method DEF_NOT_CALL = getAsmMethod(Object.class, "not", Object.class); - public final static Method DEF_NEG_CALL = getAsmMethod(Object.class, "neg", Object.class); - public final static Method DEF_MUL_CALL = getAsmMethod(Object.class, "mul", Object.class, Object.class); - public final static Method DEF_DIV_CALL = getAsmMethod(Object.class, "div", Object.class, Object.class); - public final static Method DEF_REM_CALL = getAsmMethod(Object.class, "rem", Object.class, Object.class); - public final static Method DEF_ADD_CALL = getAsmMethod(Object.class, "add", Object.class, Object.class); - public final static Method DEF_SUB_CALL = getAsmMethod(Object.class, "sub", Object.class, Object.class); - public final static Method DEF_LSH_CALL = getAsmMethod(Object.class, "lsh", Object.class, int.class); - public final static Method DEF_RSH_CALL = getAsmMethod(Object.class, "rsh", Object.class, int.class); - public final static Method DEF_USH_CALL = getAsmMethod(Object.class, "ush", Object.class, int.class); - public final static Method DEF_AND_CALL = getAsmMethod(Object.class, "and", Object.class, Object.class); - public final static Method DEF_XOR_CALL = getAsmMethod(Object.class, "xor", Object.class, Object.class); - public final static Method DEF_OR_CALL = getAsmMethod(Object.class, "or" , Object.class, Object.class); + public final static Type DEF_UTIL_TYPE = Type.getType(Def.class); + public final static Method DEF_TO_BOOLEAN = getAsmMethod(boolean.class, "DefToboolean" , Object.class); + public final static Method DEF_TO_BYTE_IMPLICIT = getAsmMethod(byte.class , "DefTobyteImplicit" , Object.class); + public final static Method DEF_TO_SHORT_IMPLICIT = getAsmMethod(short.class , "DefToshortImplicit" , Object.class); + public final static Method DEF_TO_CHAR_IMPLICIT = getAsmMethod(char.class , "DefTocharImplicit" , Object.class); + public final static Method DEF_TO_INT_IMPLICIT = getAsmMethod(int.class , "DefTointImplicit" , Object.class); + public final static Method DEF_TO_LONG_IMPLICIT = getAsmMethod(long.class , "DefTolongImplicit" , Object.class); + public final static Method DEF_TO_FLOAT_IMPLICIT = getAsmMethod(float.class , "DefTofloatImplicit" , Object.class); + public final static Method DEF_TO_DOUBLE_IMPLICIT = getAsmMethod(double.class , "DefTodoubleImplicit", Object.class); + public final static Method DEF_TO_BYTE_EXPLICIT = getAsmMethod(byte.class , "DefTobyteExplicit" , Object.class); + public final static Method DEF_TO_SHORT_EXPLICIT = getAsmMethod(short.class , "DefToshortExplicit" , Object.class); + public final static Method DEF_TO_CHAR_EXPLICIT = getAsmMethod(char.class , "DefTocharExplicit" , Object.class); + public final static Method DEF_TO_INT_EXPLICIT = getAsmMethod(int.class , "DefTointExplicit" , Object.class); + public final static Method DEF_TO_LONG_EXPLICIT = getAsmMethod(long.class , "DefTolongExplicit" , Object.class); + public final static Method DEF_TO_FLOAT_EXPLICIT = getAsmMethod(float.class , "DefTofloatExplicit" , Object.class); + public final static Method DEF_TO_DOUBLE_EXPLICIT = getAsmMethod(double.class , "DefTodoubleExplicit", Object.class); + public final static Method DEF_NOT_CALL = getAsmMethod(Object.class , "not", Object.class); + public final static Method DEF_NEG_CALL = getAsmMethod(Object.class , "neg", Object.class); + public final static Method DEF_MUL_CALL = getAsmMethod(Object.class , "mul", Object.class, Object.class); + public final static Method DEF_DIV_CALL = getAsmMethod(Object.class , "div", Object.class, Object.class); + public final static Method DEF_REM_CALL = getAsmMethod(Object.class , "rem", Object.class, Object.class); + public final static Method DEF_ADD_CALL = getAsmMethod(Object.class , "add", Object.class, Object.class); + public final static Method DEF_SUB_CALL = getAsmMethod(Object.class , "sub", Object.class, Object.class); + public final static Method DEF_LSH_CALL = getAsmMethod(Object.class , "lsh", Object.class, int.class); + public final static Method DEF_RSH_CALL = getAsmMethod(Object.class , "rsh", Object.class, int.class); + public final static Method DEF_USH_CALL = getAsmMethod(Object.class , "ush", Object.class, int.class); + public final static Method DEF_AND_CALL = getAsmMethod(Object.class , "and", Object.class, Object.class); + public final static Method DEF_XOR_CALL = getAsmMethod(Object.class , "xor", Object.class, Object.class); + public final static Method DEF_OR_CALL = getAsmMethod(Object.class , "or" , Object.class, Object.class); public final static Method DEF_EQ_CALL = getAsmMethod(boolean.class, "eq" , Object.class, Object.class); public final static Method DEF_LT_CALL = getAsmMethod(boolean.class, "lt" , Object.class, Object.class); public final static Method DEF_LTE_CALL = getAsmMethod(boolean.class, "lte", Object.class, Object.class); @@ -99,9 +118,9 @@ public final class WriterConstants { } INDY_STRING_CONCAT_BOOTSTRAP_HANDLE = bs; } - + public final static int MAX_INDY_STRING_CONCAT_ARGS = 200; - + public final static Type STRING_TYPE = Type.getType(String.class); public final static Type STRINGBUILDER_TYPE = Type.getType(StringBuilder.class); @@ -116,59 +135,7 @@ public final class WriterConstants { public final static Method STRINGBUILDER_APPEND_OBJECT = getAsmMethod(StringBuilder.class, "append", Object.class); public final static Method STRINGBUILDER_TOSTRING = getAsmMethod(String.class, "toString"); - public final static Method TOINTEXACT_LONG = getAsmMethod(int.class, "toIntExact", long.class); - public final static Method NEGATEEXACT_INT = getAsmMethod(int.class, "negateExact", int.class); - public final static Method NEGATEEXACT_LONG = getAsmMethod(long.class, "negateExact", long.class); - public final static Method MULEXACT_INT = getAsmMethod(int.class, "multiplyExact", int.class, int.class); - public final static Method MULEXACT_LONG = getAsmMethod(long.class, "multiplyExact", long.class, long.class); - public final static Method ADDEXACT_INT = getAsmMethod(int.class, "addExact", int.class, int.class); - public final static Method ADDEXACT_LONG = getAsmMethod(long.class, "addExact", long.class, long.class); - public final static Method SUBEXACT_INT = getAsmMethod(int.class, "subtractExact", int.class, int.class); - public final static Method SUBEXACT_LONG = getAsmMethod(long.class, "subtractExact", long.class, long.class); - - public final static Method CHECKEQUALS = - getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class); - public final static Method TOBYTEEXACT_INT = getAsmMethod(byte.class, "toByteExact", int.class); - public final static Method TOBYTEEXACT_LONG = getAsmMethod(byte.class, "toByteExact", long.class); - public final static Method TOBYTEWOOVERFLOW_FLOAT = getAsmMethod(byte.class, "toByteWithoutOverflow", float.class); - public final static Method TOBYTEWOOVERFLOW_DOUBLE = getAsmMethod(byte.class, "toByteWithoutOverflow", double.class); - public final static Method TOSHORTEXACT_INT = getAsmMethod(short.class, "toShortExact", int.class); - public final static Method TOSHORTEXACT_LONG = getAsmMethod(short.class, "toShortExact", long.class); - public final static Method TOSHORTWOOVERFLOW_FLOAT = getAsmMethod(short.class, "toShortWithoutOverflow", float.class); - public final static Method TOSHORTWOOVERFLOW_DOUBLE = getAsmMethod(short.class, "toShortWihtoutOverflow", double.class); - public final static Method TOCHAREXACT_INT = getAsmMethod(char.class, "toCharExact", int.class); - public final static Method TOCHAREXACT_LONG = getAsmMethod(char.class, "toCharExact", long.class); - public final static Method TOCHARWOOVERFLOW_FLOAT = getAsmMethod(char.class, "toCharWithoutOverflow", float.class); - public final static Method TOCHARWOOVERFLOW_DOUBLE = getAsmMethod(char.class, "toCharWithoutOverflow", double.class); - public final static Method TOINTWOOVERFLOW_FLOAT = getAsmMethod(int.class, "toIntWithoutOverflow", float.class); - public final static Method TOINTWOOVERFLOW_DOUBLE = getAsmMethod(int.class, "toIntWithoutOverflow", double.class); - public final static Method TOLONGWOOVERFLOW_FLOAT = getAsmMethod(long.class, "toLongWithoutOverflow", float.class); - public final static Method TOLONGWOOVERFLOW_DOUBLE = getAsmMethod(long.class, "toLongWithoutOverflow", double.class); - public final static Method TOFLOATWOOVERFLOW_DOUBLE = getAsmMethod(float.class , "toFloatWihtoutOverflow", double.class); - public final static Method MULWOOVERLOW_FLOAT = - getAsmMethod(float.class, "multiplyWithoutOverflow", float.class, float.class); - public final static Method MULWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "multiplyWithoutOverflow", double.class, double.class); - public final static Method DIVWOOVERLOW_INT = - getAsmMethod(int.class, "divideWithoutOverflow", int.class, int.class); - public final static Method DIVWOOVERLOW_LONG = - getAsmMethod(long.class, "divideWithoutOverflow", long.class, long.class); - public final static Method DIVWOOVERLOW_FLOAT = - getAsmMethod(float.class, "divideWithoutOverflow", float.class, float.class); - public final static Method DIVWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "divideWithoutOverflow", double.class, double.class); - public final static Method REMWOOVERLOW_FLOAT = - getAsmMethod(float.class, "remainderWithoutOverflow", float.class, float.class); - public final static Method REMWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "remainderWithoutOverflow", double.class, double.class); - public final static Method ADDWOOVERLOW_FLOAT = - getAsmMethod(float.class, "addWithoutOverflow", float.class, float.class); - public final static Method ADDWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "addWithoutOverflow", double.class, double.class); - public final static Method SUBWOOVERLOW_FLOAT = - getAsmMethod(float.class, "subtractWithoutOverflow", float.class, float.class); - public final static Method SUBWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "subtractWithoutOverflow", double.class, double.class); + public final static Method CHECKEQUALS = getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class); private static Method getAsmMethod(final Class rtype, final String name, final Class... ptypes) { return new Method(name, MethodType.methodType(rtype, ptypes).toMethodDescriptorString()); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java index 4f6e2f5e87c..9ecf6754248 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java @@ -22,6 +22,7 @@ package org.elasticsearch.painless.antlr; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; +import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.Variables.Reserved; import org.elasticsearch.painless.antlr.PainlessParser.AfterthoughtContext; @@ -121,15 +122,17 @@ import java.util.List; */ public final class Walker extends PainlessParserBaseVisitor { - public static SSource buildPainlessTree(final String source, final Reserved reserved) { - return new Walker(source, reserved).source; + public static SSource buildPainlessTree(String source, Reserved reserved, CompilerSettings settings) { + return new Walker(source, reserved, settings).source; } private final Reserved reserved; private final SSource source; + private final CompilerSettings settings; - private Walker(final String source, final Reserved reserved) { + private Walker(String source, Reserved reserved, CompilerSettings settings) { this.reserved = reserved; + this.settings = settings; this.source = (SSource)visit(buildAntlrTree(source)); } @@ -181,7 +184,7 @@ public final class Walker extends PainlessParserBaseVisitor { reserved.usesLoop(); - return new SWhile(line(ctx), location(ctx), condition, block); + return new SWhile(line(ctx), location(ctx), condition, block, settings.getMaxLoopCounter()); } @Override @@ -191,7 +194,7 @@ public final class Walker extends PainlessParserBaseVisitor { reserved.usesLoop(); - return new SDo(line(ctx), location(ctx), block, condition); + return new SDo(line(ctx), location(ctx), block, condition, settings.getMaxLoopCounter()); } @Override @@ -203,7 +206,7 @@ public final class Walker extends PainlessParserBaseVisitor { reserved.usesLoop(); - return new SFor(line(ctx), location(ctx), intializer, condition, afterthought, block); + return new SFor(line(ctx), location(ctx), intializer, condition, afterthought, block, settings.getMaxLoopCounter()); } @Override 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 528da4384c8..54eb8091e8e 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 @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.painless.AnalyzerCaster; @@ -67,6 +65,12 @@ public abstract class AExpression extends ANode { */ protected boolean explicit = false; + /** + * Set to true if a cast is allowed to boxed/unboxed. This is used + * for method arguments because casting may be required. + */ + protected boolean internal = false; + /** * Set to the value of the constant this expression node represents if * and only if the node represents a constant. If this is not null @@ -101,27 +105,27 @@ public abstract class AExpression extends ANode { /** * Checks for errors and collects data for the writing phase. */ - abstract void analyze(final CompilerSettings settings, final Definition definition, final Variables variables); + abstract void analyze(Variables variables); /** * Writes ASM based on the data collected during the analysis phase. */ - abstract void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter); + abstract void write(MethodWriter adapter); /** * Inserts {@link ECast} nodes into the tree for implicit casts. Also replaces * nodes with the constant variable set to a non-null value with {@link EConstant}. * @return The new child node for the parent node calling this method. */ - AExpression cast(final CompilerSettings settings, final Definition definition, final Variables variables) { - final Cast cast = AnalyzerCaster.getLegalCast(definition, location, actual, expected, explicit); + AExpression cast(Variables variables) { + final Cast cast = AnalyzerCaster.getLegalCast(location, actual, expected, explicit, internal); if (cast == null) { if (constant == null || this instanceof EConstant) { return this; } else { final EConstant econstant = new EConstant(line, location, constant); - econstant.analyze(settings, definition, variables); + econstant.analyze(variables); if (!expected.equals(econstant.actual)) { throw new IllegalStateException(error("Illegal tree structure.")); @@ -142,7 +146,7 @@ public abstract class AExpression extends ANode { constant = AnalyzerCaster.constCast(location, constant, cast); final EConstant econstant = new EConstant(line, location, constant); - econstant.analyze(settings, definition, variables); + econstant.analyze(variables); if (!expected.equals(econstant.actual)) { throw new IllegalStateException(error("Illegal tree structure.")); @@ -156,7 +160,7 @@ public abstract class AExpression extends ANode { return ecast; } else { final EConstant econstant = new EConstant(line, location, constant); - econstant.analyze(settings, definition, variables); + econstant.analyze(variables); if (!actual.equals(econstant.actual)) { throw new IllegalStateException(error("Illegal tree structure.")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ALink.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ALink.java index ffbfff112b3..e134e7fbcb9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ALink.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ALink.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -75,7 +73,7 @@ public abstract class ALink extends ANode { */ String string = null; - ALink(final int line, final String location, final int size) { + ALink(int line, String location, int size) { super(line, location); this.size = size; @@ -87,27 +85,27 @@ public abstract class ALink extends ANode { * def or a shortcut is used. Otherwise, returns itself. This will be * updated into the {@link EChain} node's list of links. */ - abstract ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables); + abstract ALink analyze(Variables variables); /** * Write values before a load/store occurs such as an array index. */ - abstract void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter); + abstract void write(MethodWriter adapter); /** * Write a load for the specific link type. */ - abstract void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter); + abstract void load(MethodWriter adapter); /** * Write a store for the specific link type. */ - abstract void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter); + abstract void store(MethodWriter adapter); /** * Used to copy link data from one to another during analysis in the case of replacement. */ - final ALink copy(final ALink link) { + final ALink copy(ALink link) { load = link.load; store = link.store; statik = link.statik; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AStatement.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AStatement.java index 569e8cfb03b..ebc4a166268 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AStatement.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AStatement.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; import org.elasticsearch.painless.MethodWriter; @@ -109,17 +107,17 @@ public abstract class AStatement extends ANode { */ Label brake = null; - AStatement(final int line, final String location) { + AStatement(int line, String location) { super(line, location); } /** * Checks for errors and collects data for the writing phase. */ - abstract void analyze(final CompilerSettings settings, final Definition definition, final Variables variables); + abstract void analyze(Variables variables); /** * Writes ASM based on the data collected during the analysis phase. */ - abstract void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter); + abstract void write(MethodWriter adapter); } 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 07fe1ff3447..ee990f60b61 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 @@ -20,7 +20,6 @@ package org.elasticsearch.painless.node; import org.elasticsearch.painless.AnalyzerCaster; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Definition.Type; @@ -39,7 +38,7 @@ public final class EBinary extends AExpression { boolean cat = false; - public EBinary(final int line, final String location, final Operation operation, final AExpression left, final AExpression right) { + public EBinary(int line, String location, Operation operation, AExpression left, AExpression right) { super(line, location); this.operation = operation; @@ -48,39 +47,39 @@ public final class EBinary extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (operation == Operation.MUL) { - analyzeMul(settings, definition, variables); + analyzeMul(variables); } else if (operation == Operation.DIV) { - analyzeDiv(settings, definition, variables); + analyzeDiv(variables); } else if (operation == Operation.REM) { - analyzeRem(settings, definition, variables); + analyzeRem(variables); } else if (operation == Operation.ADD) { - analyzeAdd(settings, definition, variables); + analyzeAdd(variables); } else if (operation == Operation.SUB) { - analyzeSub(settings, definition, variables); + analyzeSub(variables); } else if (operation == Operation.LSH) { - analyzeLSH(settings, definition, variables); + analyzeLSH(variables); } else if (operation == Operation.RSH) { - analyzeRSH(settings, definition, variables); + analyzeRSH(variables); } else if (operation == Operation.USH) { - analyzeUSH(settings, definition, variables); + analyzeUSH(variables); } else if (operation == Operation.BWAND) { - analyzeBWAnd(settings, definition, variables); + analyzeBWAnd(variables); } else if (operation == Operation.XOR) { - analyzeXor(settings, definition, variables); + analyzeXor(variables); } else if (operation == Operation.BWOR) { - analyzeBWOr(settings, definition, variables); + analyzeBWOr(variables); } else { throw new IllegalStateException(error("Illegal tree structure.")); } } - private void analyzeMul(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeMul(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply multiply [*] to types " + @@ -90,25 +89,20 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant * (int)right.constant : - Math.multiplyExact((int)left.constant, (int)right.constant); + constant = (int)left.constant * (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant * (long)right.constant : - Math.multiplyExact((long)left.constant, (long)right.constant); + constant = (long)left.constant * (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant * (float)right.constant : - org.elasticsearch.painless.Utility.multiplyWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant * (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant * (double)right.constant : - org.elasticsearch.painless.Utility.multiplyWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant * (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -117,11 +111,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeDiv(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeDiv(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply divide [/] to types " + @@ -131,25 +125,20 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant / (int)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((int)left.constant, (int)right.constant); + constant = (int)left.constant / (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant / (long)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((long)left.constant, (long)right.constant); + constant = (long)left.constant / (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant / (float)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant / (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant / (double)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant / (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -158,11 +147,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeRem(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeRem(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply remainder [%] to types " + @@ -172,11 +161,10 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { @@ -184,11 +172,9 @@ public final class EBinary extends AExpression { } else if (sort == Sort.LONG) { constant = (long)left.constant % (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant % (float)right.constant : - org.elasticsearch.painless.Utility.remainderWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant % (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant % (double)right.constant : - org.elasticsearch.painless.Utility.remainderWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant % (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -197,11 +183,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeAdd(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeAdd(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteAdd(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteAdd(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply add [+] to types " + @@ -227,24 +213,18 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); - if (sort == Sort.INT) { - constant = overflow ? (int)left.constant + (int)right.constant : - Math.addExact((int)left.constant, (int)right.constant); + constant = (int)left.constant + (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant + (long)right.constant : - Math.addExact((long)left.constant, (long)right.constant); + constant = (long)left.constant + (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant + (float)right.constant : - org.elasticsearch.painless.Utility.addWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant + (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant + (double)right.constant : - org.elasticsearch.painless.Utility.addWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant + (double)right.constant; } else if (sort == Sort.STRING) { constant = "" + left.constant + right.constant; } else { @@ -255,11 +235,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeSub(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeSub(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply subtract [-] to types " + @@ -269,25 +249,20 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant - (int)right.constant : - Math.subtractExact((int)left.constant, (int)right.constant); + constant = (int)left.constant - (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant - (long)right.constant : - Math.subtractExact((long)left.constant, (long)right.constant); + constant = (long)left.constant - (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant - (float)right.constant : - org.elasticsearch.painless.Utility.subtractWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant - (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant - (double)right.constant : - org.elasticsearch.painless.Utility.subtractWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant - (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -296,11 +271,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeLSH(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeLSH(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply left shift [<<] to types " + @@ -308,11 +283,11 @@ public final class EBinary extends AExpression { } left.expected = promote; - right.expected = definition.intType; + right.expected = Definition.INT_TYPE; right.explicit = true; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -329,11 +304,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeRSH(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeRSH(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply right shift [>>] to types " + @@ -341,11 +316,11 @@ public final class EBinary extends AExpression { } left.expected = promote; - right.expected = definition.intType; + right.expected = Definition.INT_TYPE; right.explicit = true; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -362,11 +337,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeUSH(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeUSH(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply unsigned shift [>>>] to types " + @@ -374,11 +349,11 @@ public final class EBinary extends AExpression { } left.expected = promote; - right.expected = definition.intType; + right.expected = Definition.INT_TYPE; right.explicit = true; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -395,11 +370,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeBWAnd(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeBWAnd(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply and [&] to types " + @@ -409,8 +384,8 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -427,11 +402,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeXor(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeXor(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteXor(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteXor(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply xor [^] to types " + @@ -441,8 +416,8 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -461,11 +436,11 @@ public final class EBinary extends AExpression { actual = promote; } - private void analyzeBWOr(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeBWOr(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply or [|] to types " + @@ -475,8 +450,8 @@ public final class EBinary extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -494,19 +469,19 @@ public final class EBinary extends AExpression { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { if (actual.sort == Sort.STRING && operation == Operation.ADD) { if (!cat) { adapter.writeNewStrings(); } - left.write(settings, definition, adapter); + left.write(adapter); if (!(left instanceof EBinary) || ((EBinary)left).operation != Operation.ADD || left.actual.sort != Sort.STRING) { adapter.writeAppendStrings(left.actual); } - right.write(settings, definition, adapter); + right.write(adapter); if (!(right instanceof EBinary) || ((EBinary)right).operation != Operation.ADD || right.actual.sort != Sort.STRING) { adapter.writeAppendStrings(right.actual); @@ -516,10 +491,10 @@ public final class EBinary extends AExpression { adapter.writeToStrings(); } } else { - left.write(settings, definition, adapter); - right.write(settings, definition, adapter); + left.write(adapter); + right.write(adapter); - adapter.writeBinaryInstruction(settings, definition, location, actual, operation); + adapter.writeBinaryInstruction(location, actual, operation); } adapter.writeBranch(tru, fals); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java index 7f9f7dee000..27cd3018ded 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.Variables; @@ -35,7 +34,7 @@ public final class EBool extends AExpression { AExpression left; AExpression right; - public EBool(final int line, final String location, final Operation operation, final AExpression left, final AExpression right) { + public EBool(int line, String location, Operation operation, AExpression left, AExpression right) { super(line, location); this.operation = operation; @@ -44,14 +43,14 @@ public final class EBool extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.expected = definition.booleanType; - left.analyze(settings, definition, variables); - left = left.cast(settings, definition, variables); + void analyze(Variables variables) { + left.expected = Definition.BOOLEAN_TYPE; + left.analyze(variables); + left = left.cast(variables); - right.expected = definition.booleanType; - right.analyze(settings, definition, variables); - right = right.cast(settings, definition, variables); + right.expected = Definition.BOOLEAN_TYPE; + right.analyze(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { if (operation == Operation.AND) { @@ -63,11 +62,11 @@ public final class EBool extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { if (tru != null || fals != null) { if (operation == Operation.AND) { final Label localfals = fals == null ? new Label() : fals; @@ -76,8 +75,8 @@ public final class EBool extends AExpression { right.tru = tru; right.fals = fals; - left.write(settings, definition, adapter); - right.write(settings, definition, adapter); + left.write(adapter); + right.write(adapter); if (fals == null) { adapter.mark(localfals); @@ -89,8 +88,8 @@ public final class EBool extends AExpression { right.tru = tru; right.fals = fals; - left.write(settings, definition, adapter); - right.write(settings, definition, adapter); + left.write(adapter); + right.write(adapter); if (tru == null) { adapter.mark(localtru); @@ -106,8 +105,8 @@ public final class EBool extends AExpression { left.fals = localfals; right.fals = localfals; - left.write(settings, definition, adapter); - right.write(settings, definition, adapter); + left.write(adapter); + right.write(adapter); adapter.push(true); adapter.goTo(end); @@ -122,8 +121,8 @@ public final class EBool extends AExpression { left.tru = localtru; right.fals = localfals; - left.write(settings, definition, adapter); - right.write(settings, definition, adapter); + left.write(adapter); + right.write(adapter); adapter.mark(localtru); adapter.push(true); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java index 9b9f0917546..27d7bb9a626 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -29,19 +28,19 @@ import org.elasticsearch.painless.MethodWriter; */ public final class EBoolean extends AExpression { - public EBoolean(final int line, final String location, final boolean constant) { + public EBoolean(int line, String location, boolean constant) { super(line, location); this.constant = constant; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - actual = definition.booleanType; + void analyze(Variables variables) { + actual = Definition.BOOLEAN_TYPE; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { throw new IllegalArgumentException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java index d68c95c910a..7a8c4a29b60 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -36,7 +34,7 @@ final class ECast extends AExpression { Cast cast = null; - ECast(final int line, final String location, final AExpression child, final Cast cast) { + ECast(int line, String location, AExpression child, Cast cast) { super(line, location); this.type = null; @@ -46,13 +44,13 @@ final class ECast extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { throw new IllegalStateException(error("Illegal tree structure.")); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - child.write(settings, definition, adapter); + void write(MethodWriter adapter) { + child.write(adapter); adapter.writeCast(cast); adapter.writeBranch(tru, fals); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java index 39afcd935ad..31bff2dd66d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.Definition.Sort; @@ -44,12 +43,11 @@ public final class EChain extends AExpression { boolean cat = false; Type promote = null; - boolean exact = false; Cast there = null; Cast back = null; - public EChain(final int line, final String location, final List links, - final boolean pre, final boolean post, final Operation operation, final AExpression expression) { + public EChain(int line, String location, List links, + boolean pre, boolean post, Operation operation, AExpression expression) { super(line, location); this.links = links; @@ -60,20 +58,20 @@ public final class EChain extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - analyzeLinks(settings, definition, variables); + void analyze(Variables variables) { + analyzeLinks(variables); analyzeIncrDecr(); if (operation != null) { - analyzeCompound(settings, definition, variables); + analyzeCompound(variables); } else if (expression != null) { - analyzeWrite(settings, definition, variables); + analyzeWrite(variables); } else { analyzeRead(); } } - private void analyzeLinks(final CompilerSettings settings, final Definition definition, final Variables variables) { + private void analyzeLinks(Variables variables) { ALink previous = null; int index = 0; @@ -93,7 +91,7 @@ public final class EChain extends AExpression { current.store = expression != null || pre || post; } - final ALink analyzed = current.analyze(settings, definition, variables); + final ALink analyzed = current.analyze(variables); if (analyzed == null) { links.remove(index); @@ -154,33 +152,33 @@ public final class EChain extends AExpression { } } - private void analyzeCompound(final CompilerSettings settings, final Definition definition, final Variables variables) { + private void analyzeCompound(Variables variables) { final ALink last = links.get(links.size() - 1); - expression.analyze(settings, definition, variables); + expression.analyze(variables); if (operation == Operation.MUL) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, expression.actual, true, true); + promote = AnalyzerCaster.promoteNumeric(last.after, expression.actual, true); } else if (operation == Operation.DIV) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, expression.actual, true, true); + promote = AnalyzerCaster.promoteNumeric(last.after, expression.actual, true); } else if (operation == Operation.REM) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, expression.actual, true, true); + promote = AnalyzerCaster.promoteNumeric(last.after, expression.actual, true); } else if (operation == Operation.ADD) { - promote = AnalyzerCaster.promoteAdd(definition, last.after, expression.actual); + promote = AnalyzerCaster.promoteAdd(last.after, expression.actual); } else if (operation == Operation.SUB) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, expression.actual, true, true); + promote = AnalyzerCaster.promoteNumeric(last.after, expression.actual, true); } else if (operation == Operation.LSH) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, false, true); + promote = AnalyzerCaster.promoteNumeric(last.after, false); } else if (operation == Operation.RSH) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, false, true); + promote = AnalyzerCaster.promoteNumeric(last.after, false); } else if (operation == Operation.USH) { - promote = AnalyzerCaster.promoteNumeric(definition, last.after, false, true); + promote = AnalyzerCaster.promoteNumeric(last.after, false); } else if (operation == Operation.BWAND) { - promote = AnalyzerCaster.promoteXor(definition, last.after, expression.actual); + promote = AnalyzerCaster.promoteXor(last.after, expression.actual); } else if (operation == Operation.XOR) { - promote = AnalyzerCaster.promoteXor(definition, last.after, expression.actual); + promote = AnalyzerCaster.promoteXor(last.after, expression.actual); } else if (operation == Operation.BWOR) { - promote = AnalyzerCaster.promoteXor(definition, last.after, expression.actual); + promote = AnalyzerCaster.promoteXor(last.after, expression.actual); } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -200,42 +198,39 @@ public final class EChain extends AExpression { expression.expected = expression.actual; } else if (operation == Operation.LSH || operation == Operation.RSH || operation == Operation.USH) { - expression.expected = definition.intType; + expression.expected = Definition.INT_TYPE; expression.explicit = true; } else { expression.expected = promote; } - expression = expression.cast(settings, definition, variables); + expression = expression.cast(variables); - exact = !settings.getNumericOverflow() && - (operation == Operation.MUL || operation == Operation.DIV || operation == Operation.REM || - operation == Operation.ADD || operation == Operation.SUB); - there = AnalyzerCaster.getLegalCast(definition, location, last.after, promote, false); - back = AnalyzerCaster.getLegalCast(definition, location, promote, last.after, true); + there = AnalyzerCaster.getLegalCast(location, last.after, promote, false, false); + back = AnalyzerCaster.getLegalCast(location, promote, last.after, true, false); this.statement = true; - this.actual = read ? last.after : definition.voidType; + this.actual = read ? last.after : Definition.VOID_TYPE; } - private void analyzeWrite(final CompilerSettings settings, final Definition definition, final Variables variables) { + private void analyzeWrite(Variables variables) { final ALink last = links.get(links.size() - 1); // If the store node is a DEF node, we remove the cast to DEF from the expression // and promote the real type to it: if (last instanceof IDefLink) { - expression.analyze(settings, definition, variables); + expression.analyze(variables); last.after = expression.expected = expression.actual; } else { // otherwise we adapt the type of the expression to the store type expression.expected = last.after; - expression.analyze(settings, definition, variables); + expression.analyze(variables); } - expression = expression.cast(settings, definition, variables); + expression = expression.cast(variables); this.statement = true; - this.actual = read ? last.after : definition.voidType; + this.actual = read ? last.after : Definition.VOID_TYPE; } private void analyzeRead() { @@ -252,7 +247,7 @@ public final class EChain extends AExpression { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { if (cat) { adapter.writeNewStrings(); } @@ -260,15 +255,15 @@ public final class EChain extends AExpression { final ALink last = links.get(links.size() - 1); for (final ALink link : links) { - link.write(settings, definition, adapter); + link.write(adapter); if (link == last && link.store) { if (cat) { adapter.writeDup(link.size, 1); - link.load(settings, definition, adapter); + link.load(adapter); adapter.writeAppendStrings(link.after); - expression.write(settings, definition, adapter); + expression.write(adapter); if (!(expression instanceof EBinary) || ((EBinary)expression).operation != Operation.ADD || expression.actual.sort != Sort.STRING) { @@ -282,39 +277,37 @@ public final class EChain extends AExpression { adapter.writeDup(link.after.sort.size, link.size); } - link.store(settings, definition, adapter); + link.store(adapter); } else if (operation != null) { adapter.writeDup(link.size, 0); - link.load(settings, definition, adapter); + link.load(adapter); if (link.load && post) { adapter.writeDup(link.after.sort.size, link.size); } adapter.writeCast(there); - expression.write(settings, definition, adapter); - adapter.writeBinaryInstruction(settings, definition, location, promote, operation); + expression.write(adapter); + adapter.writeBinaryInstruction(location, promote, operation); - if (!exact || !adapter.writeExactInstruction(definition, promote.sort, link.after.sort)) { - adapter.writeCast(back); - } + adapter.writeCast(back); if (link.load && !post) { adapter.writeDup(link.after.sort.size, link.size); } - link.store(settings, definition, adapter); + link.store(adapter); } else { - expression.write(settings, definition, adapter); + expression.write(adapter); if (link.load) { adapter.writeDup(link.after.sort.size, link.size); } - link.store(settings, definition, adapter); + link.store(adapter); } } else { - link.load(settings, definition, adapter); + link.load(adapter); } } 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 d9337ae562b..08fed075335 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 @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Definition.Type; @@ -35,6 +34,8 @@ import static org.elasticsearch.painless.WriterConstants.DEF_GTE_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_GT_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_LTE_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_LT_CALL; +import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE; +import static org.elasticsearch.painless.WriterConstants.UTILITY_TYPE; /** * Represents a comparison expression. @@ -45,7 +46,7 @@ public final class EComp extends AExpression { AExpression left; AExpression right; - public EComp(final int line, final String location, final Operation operation, final AExpression left, final AExpression right) { + public EComp(int line, String location, Operation operation, AExpression left, AExpression right) { super(line, location); this.operation = operation; @@ -54,33 +55,33 @@ public final class EComp extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (operation == Operation.EQ) { - analyzeEq(settings, definition, variables); + analyzeEq(variables); } else if (operation == Operation.EQR) { - analyzeEqR(settings, definition, variables); + analyzeEqR(variables); } else if (operation == Operation.NE) { - analyzeNE(settings, definition, variables); + analyzeNE(variables); } else if (operation == Operation.NER) { - analyzeNER(settings, definition, variables); + analyzeNER(variables); } else if (operation == Operation.GTE) { - analyzeGTE(settings, definition, variables); + analyzeGTE(variables); } else if (operation == Operation.GT) { - analyzeGT(settings, definition, variables); + analyzeGT(variables); } else if (operation == Operation.LTE) { - analyzeLTE(settings, definition, variables); + analyzeLTE(variables); } else if (operation == Operation.LT) { - analyzeLT(settings, definition, variables); + analyzeLT(variables); } else { throw new IllegalStateException(error("Illegal tree structure.")); } } - private void analyzeEq(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeEq(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteEquality(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply equals [==] to types " + @@ -90,8 +91,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.isNull && right.isNull) { throw new IllegalArgumentException(error("Extraneous comparison of null constants.")); @@ -119,14 +120,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeEqR(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeEqR(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteReference(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply reference equals [===] to types " + @@ -136,8 +137,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.isNull && right.isNull) { throw new IllegalArgumentException(error("Extraneous comparison of null constants.")); @@ -161,14 +162,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeNE(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeNE(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteEquality(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply not equals [!=] to types " + @@ -178,8 +179,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.isNull && right.isNull) { throw new IllegalArgumentException(error("Extraneous comparison of null constants.")); @@ -207,14 +208,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeNER(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeNER(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteReference(definition, left.actual, right.actual); + final Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual); if (promote == null) { throw new ClassCastException(error("Cannot apply reference not equals [!==] to types " + @@ -224,8 +225,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.isNull && right.isNull) { throw new IllegalArgumentException(error("Extraneous comparison of null constants.")); @@ -249,14 +250,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeGTE(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeGTE(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply greater than or equals [>=] to types " + @@ -266,8 +267,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -285,14 +286,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeGT(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeGT(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply greater than [>] to types " + @@ -302,8 +303,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -321,14 +322,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeLTE(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeLTE(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply less than or equals [<=] to types " + @@ -338,8 +339,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -357,14 +358,14 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - private void analyzeLT(final CompilerSettings settings, final Definition definition, final Variables variables) { - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + private void analyzeLT(Variables variables) { + left.analyze(variables); + right.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, left.actual, right.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply less than [>=] to types " + @@ -374,8 +375,8 @@ public final class EComp extends AExpression { left.expected = promote; right.expected = promote; - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); if (left.constant != null && right.constant != null) { final Sort sort = promote.sort; @@ -393,19 +394,19 @@ public final class EComp extends AExpression { } } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { final boolean branch = tru != null || fals != null; final org.objectweb.asm.Type rtype = right.actual.type; final Sort rsort = right.actual.sort; - left.write(settings, definition, adapter); + left.write(adapter); if (!right.isNull) { - right.write(settings, definition, adapter); + right.write(adapter); } final Label jump = tru != null ? tru : fals != null ? fals : new Label(); @@ -455,34 +456,37 @@ public final class EComp extends AExpression { if (eq) { if (right.isNull) { adapter.ifNull(jump); - } else if (!left.isNull && operation == Operation.EQ) { - adapter.invokeStatic(definition.defobjType.type, DEF_EQ_CALL); + } else if (!left.isNull && (operation == Operation.EQ || operation == Operation.NE)) { + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_EQ_CALL); + writejump = false; } else { adapter.ifCmp(rtype, MethodWriter.EQ, jump); } } else if (ne) { if (right.isNull) { adapter.ifNonNull(jump); - } else if (!left.isNull && operation == Operation.NE) { - adapter.invokeStatic(definition.defobjType.type, DEF_EQ_CALL); + } else if (!left.isNull && (operation == Operation.EQ || operation == Operation.NE)) { + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_EQ_CALL); adapter.ifZCmp(MethodWriter.EQ, jump); } else { adapter.ifCmp(rtype, MethodWriter.NE, jump); } } else if (lt) { - adapter.invokeStatic(definition.defobjType.type, DEF_LT_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_LT_CALL); + writejump = false; } else if (lte) { - adapter.invokeStatic(definition.defobjType.type, DEF_LTE_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_LTE_CALL); + writejump = false; } else if (gt) { - adapter.invokeStatic(definition.defobjType.type, DEF_GT_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_GT_CALL); + writejump = false; } else if (gte) { - adapter.invokeStatic(definition.defobjType.type, DEF_GTE_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_GTE_CALL); + writejump = false; } else { throw new IllegalStateException(error("Illegal tree structure.")); } - writejump = left.isNull || ne || operation == Operation.EQR; - if (branch && !writejump) { adapter.ifZCmp(MethodWriter.NE, jump); } @@ -492,8 +496,8 @@ public final class EComp extends AExpression { if (eq) { if (right.isNull) { adapter.ifNull(jump); - } else if (operation == Operation.EQ) { - adapter.invokeStatic(definition.utilityType.type, CHECKEQUALS); + } else if (operation == Operation.EQ || operation == Operation.NE) { + adapter.invokeStatic(UTILITY_TYPE, CHECKEQUALS); if (branch) { adapter.ifZCmp(MethodWriter.NE, jump); @@ -506,8 +510,8 @@ public final class EComp extends AExpression { } else if (ne) { if (right.isNull) { adapter.ifNonNull(jump); - } else if (operation == Operation.NE) { - adapter.invokeStatic(definition.utilityType.type, CHECKEQUALS); + } else if (operation == Operation.EQ || operation == Operation.NE) { + adapter.invokeStatic(UTILITY_TYPE, CHECKEQUALS); adapter.ifZCmp(MethodWriter.EQ, jump); } else { adapter.ifCmp(rtype, MethodWriter.NE, jump); 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 5853fa3242e..8f9d0038586 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 @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.painless.AnalyzerCaster; @@ -36,8 +35,7 @@ public final class EConditional extends AExpression { AExpression left; AExpression right; - public EConditional(final int line, final String location, - final AExpression condition, final AExpression left, final AExpression right) { + public EConditional(int line, String location, AExpression condition, AExpression left, AExpression right) { super(line, location); this.condition = condition; @@ -46,10 +44,10 @@ public final class EConditional extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - condition.expected = definition.booleanType; - condition.analyze(settings, definition, variables); - condition = condition.cast(settings, definition, variables); + void analyze(Variables variables) { + condition.expected = Definition.BOOLEAN_TYPE; + condition.analyze(variables); + condition = condition.cast(variables); if (condition.constant != null) { throw new IllegalArgumentException(error("Extraneous conditional statement.")); @@ -57,27 +55,29 @@ public final class EConditional extends AExpression { left.expected = expected; left.explicit = explicit; + left.internal = internal; right.expected = expected; right.explicit = explicit; + right.internal = internal; actual = expected; - left.analyze(settings, definition, variables); - right.analyze(settings, definition, variables); + left.analyze(variables); + right.analyze(variables); if (expected == null) { - final Type promote = AnalyzerCaster.promoteConditional(definition, left.actual, right.actual, left.constant, right.constant); + final Type promote = AnalyzerCaster.promoteConditional(left.actual, right.actual, left.constant, right.constant); left.expected = promote; right.expected = promote; actual = promote; } - left = left.cast(settings, definition, variables); - right = right.cast(settings, definition, variables); + left = left.cast(variables); + right = right.cast(variables); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { final Label localfals = new Label(); final Label end = new Label(); @@ -85,11 +85,11 @@ public final class EConditional extends AExpression { left.tru = right.tru = tru; left.fals = right.fals = fals; - condition.write(settings, definition, adapter); - left.write(settings, definition, adapter); + condition.write(adapter); + left.write(adapter); adapter.goTo(end); adapter.mark(localfals); - right.write(settings, definition, adapter); + right.write(adapter); adapter.mark(end); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java index 7afa88ffc9a..ac18b849162 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Variables; @@ -31,39 +30,39 @@ import org.elasticsearch.painless.MethodWriter; */ final class EConstant extends AExpression { - EConstant(final int line, final String location, final Object constant) { + EConstant(int line, String location, Object constant) { super(line, location); this.constant = constant; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (constant instanceof String) { - actual = definition.stringType; + actual = Definition.STRING_TYPE; } else if (constant instanceof Double) { - actual = definition.doubleType; + actual = Definition.DOUBLE_TYPE; } else if (constant instanceof Float) { - actual = definition.floatType; + actual = Definition.FLOAT_TYPE; } else if (constant instanceof Long) { - actual = definition.longType; + actual = Definition.LONG_TYPE; } else if (constant instanceof Integer) { - actual = definition.intType; + actual = Definition.INT_TYPE; } else if (constant instanceof Character) { - actual = definition.charType; + actual = Definition.CHAR_TYPE; } else if (constant instanceof Short) { - actual = definition.shortType; + actual = Definition.SHORT_TYPE; } else if (constant instanceof Byte) { - actual = definition.byteType; + actual = Definition.BYTE_TYPE; } else if (constant instanceof Boolean) { - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } else { throw new IllegalStateException(error("Illegal tree structure.")); } } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { final Sort sort = actual.sort; switch (sort) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java index 7583d3eb158..85e857da3c4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -31,25 +30,25 @@ public final class EDecimal extends AExpression { final String value; - public EDecimal(final int line, final String location, final String value) { + public EDecimal(int line, String location, String value) { super(line, location); this.value = value; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (value.endsWith("f") || value.endsWith("F")) { try { constant = Float.parseFloat(value.substring(0, value.length() - 1)); - actual = definition.floatType; + actual = Definition.FLOAT_TYPE; } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid float constant [" + value + "].")); } } else { try { constant = Double.parseDouble(value); - actual = definition.doubleType; + actual = Definition.DOUBLE_TYPE; } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid double constant [" + value + "].")); } @@ -57,7 +56,7 @@ public final class EDecimal extends AExpression { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { throw new IllegalArgumentException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java index ac0b06c0a79..7a8c9dadeca 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -32,7 +31,7 @@ public final class EExplicit extends AExpression { final String type; AExpression child; - public EExplicit(final int line, final String location, final String type, final AExpression child) { + public EExplicit(int line, String location, String type, AExpression child) { super(line, location); this.type = type; @@ -40,28 +39,29 @@ public final class EExplicit extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { try { - actual = definition.getType(this.type); + actual = Definition.getType(this.type); } catch (final IllegalArgumentException exception) { throw new IllegalArgumentException(error("Not a type [" + this.type + "].")); } child.expected = actual; child.explicit = true; - child.analyze(settings, definition, variables); - child = child.cast(settings, definition, variables); + child.analyze(variables); + child = child.cast(variables); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { throw new IllegalArgumentException(error("Illegal tree structure.")); } - AExpression cast(final CompilerSettings settings, final Definition definition, final Variables variables) { + AExpression cast(Variables variables) { child.expected = expected; child.explicit = explicit; + child.internal = internal; - return child.cast(settings, definition, variables); + return child.cast(variables); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java index 0c8500c528b..3a8005b20d6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Opcodes; @@ -30,12 +29,12 @@ import org.elasticsearch.painless.MethodWriter; */ public final class ENull extends AExpression { - public ENull(final int line, final String location) { + public ENull(int line, String location) { super(line, location); } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { isNull = true; if (expected != null) { @@ -45,12 +44,12 @@ public final class ENull extends AExpression { actual = expected; } else { - actual = definition.objectType; + actual = Definition.OBJECT_TYPE; } } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { adapter.visitInsn(Opcodes.ACONST_NULL); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java index ed7314b3571..ee70bb77d44 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Variables; @@ -33,7 +32,7 @@ public final class ENumeric extends AExpression { final String value; int radix; - public ENumeric(final int line, final String location, final String value, final int radix) { + public ENumeric(int line, String location, String value, int radix) { super(line, location); this.value = value; @@ -41,7 +40,7 @@ public final class ENumeric extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (value.endsWith("d") || value.endsWith("D")) { if (radix != 10) { throw new IllegalStateException(error("Invalid tree structure.")); @@ -49,7 +48,7 @@ public final class ENumeric extends AExpression { try { constant = Double.parseDouble(value.substring(0, value.length() - 1)); - actual = definition.doubleType; + actual = Definition.DOUBLE_TYPE; } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid double constant [" + value + "].")); } @@ -60,14 +59,14 @@ public final class ENumeric extends AExpression { try { constant = Float.parseFloat(value.substring(0, value.length() - 1)); - actual = definition.floatType; + actual = Definition.FLOAT_TYPE; } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid float constant [" + value + "].")); } } else if (value.endsWith("l") || value.endsWith("L")) { try { constant = Long.parseLong(value.substring(0, value.length() - 1), radix); - actual = definition.longType; + actual = Definition.LONG_TYPE; } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid long constant [" + value + "].")); } @@ -78,16 +77,16 @@ public final class ENumeric extends AExpression { if (sort == Sort.BYTE && integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) { constant = (byte)integer; - actual = definition.byteType; + actual = Definition.BYTE_TYPE; } else if (sort == Sort.CHAR && integer >= Character.MIN_VALUE && integer <= Character.MAX_VALUE) { constant = (char)integer; - actual = definition.charType; + actual = Definition.CHAR_TYPE; } else if (sort == Sort.SHORT && integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) { constant = (short)integer; - actual = definition.shortType; + actual = Definition.SHORT_TYPE; } else { constant = integer; - actual = definition.intType; + actual = Definition.INT_TYPE; } } catch (final NumberFormatException exception) { throw new IllegalArgumentException(error("Invalid int constant [" + value + "].")); @@ -96,7 +95,7 @@ public final class ENumeric extends AExpression { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { throw new IllegalArgumentException(error("Illegal tree structure.")); } } 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 f4205223a65..d62fa2c8ebf 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 @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Definition.Type; @@ -31,8 +30,7 @@ import org.elasticsearch.painless.MethodWriter; import static org.elasticsearch.painless.WriterConstants.DEF_NEG_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_NOT_CALL; -import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_LONG; +import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE; /** * Represents a unary math expression. @@ -42,7 +40,7 @@ public final class EUnary extends AExpression { Operation operation; AExpression child; - public EUnary(final int line, final String location, final Operation operation, final AExpression child) { + public EUnary(int line, String location, Operation operation, AExpression child) { super(line, location); this.operation = operation; @@ -50,43 +48,43 @@ public final class EUnary extends AExpression { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (operation == Operation.NOT) { - analyzeNot(settings, definition, variables); + analyzeNot(variables); } else if (operation == Operation.BWNOT) { - analyzeBWNot(settings, definition, variables); + analyzeBWNot(variables); } else if (operation == Operation.ADD) { - analyzerAdd(settings, definition, variables); + analyzerAdd(variables); } else if (operation == Operation.SUB) { - analyzerSub(settings, definition, variables); + analyzerSub(variables); } else { throw new IllegalStateException(error("Illegal tree structure.")); } } - void analyzeNot(final CompilerSettings settings, final Definition definition, final Variables variables) { - child.expected = definition.booleanType; - child.analyze(settings, definition, variables); - child = child.cast(settings, definition, variables); + void analyzeNot(Variables variables) { + child.expected = Definition.BOOLEAN_TYPE; + child.analyze(variables); + child = child.cast(variables); if (child.constant != null) { constant = !(boolean)child.constant; } - actual = definition.booleanType; + actual = Definition.BOOLEAN_TYPE; } - void analyzeBWNot(final CompilerSettings settings, final Definition definition, final Variables variables) { - child.analyze(settings, definition, variables); + void analyzeBWNot(Variables variables) { + child.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, child.actual, false, true); + final Type promote = AnalyzerCaster.promoteNumeric(child.actual, false); if (promote == null) { throw new ClassCastException(error("Cannot apply not [~] to type [" + child.actual.name + "].")); } child.expected = promote; - child = child.cast(settings, definition, variables); + child = child.cast(variables); if (child.constant != null) { final Sort sort = promote.sort; @@ -103,17 +101,17 @@ public final class EUnary extends AExpression { actual = promote; } - void analyzerAdd(final CompilerSettings settings, final Definition definition, final Variables variables) { - child.analyze(settings, definition, variables); + void analyzerAdd(Variables variables) { + child.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, child.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(child.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply positive [+] to type [" + child.actual.name + "].")); } child.expected = promote; - child = child.cast(settings, definition, variables); + child = child.cast(variables); if (child.constant != null) { final Sort sort = promote.sort; @@ -134,27 +132,25 @@ public final class EUnary extends AExpression { actual = promote; } - void analyzerSub(final CompilerSettings settings, final Definition definition, final Variables variables) { - child.analyze(settings, definition, variables); + void analyzerSub(Variables variables) { + child.analyze(variables); - final Type promote = AnalyzerCaster.promoteNumeric(definition, child.actual, true, true); + final Type promote = AnalyzerCaster.promoteNumeric(child.actual, true); if (promote == null) { throw new ClassCastException(error("Cannot apply negative [-] to type [" + child.actual.name + "].")); } child.expected = promote; - child = child.cast(settings, definition, variables); + child = child.cast(variables); if (child.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; - if (sort == Sort.INT) { - constant = overflow ? -(int)child.constant : Math.negateExact((int)child.constant); + constant = -(int)child.constant; } else if (sort == Sort.LONG) { - constant = overflow ? -(long)child.constant : Math.negateExact((long)child.constant); + constant = -(long)child.constant; } else if (sort == Sort.FLOAT) { constant = -(float)child.constant; } else if (sort == Sort.DOUBLE) { @@ -168,14 +164,14 @@ public final class EUnary extends AExpression { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { if (operation == Operation.NOT) { if (tru == null && fals == null) { final Label localfals = new Label(); final Label end = new Label(); child.fals = localfals; - child.write(settings, definition, adapter); + child.write(adapter); adapter.push(false); adapter.goTo(end); @@ -185,17 +181,17 @@ public final class EUnary extends AExpression { } else { child.tru = fals; child.fals = tru; - child.write(settings, definition, adapter); + child.write(adapter); } } else { final org.objectweb.asm.Type type = actual.type; final Sort sort = actual.sort; - child.write(settings, definition, adapter); + child.write(adapter); if (operation == Operation.BWNOT) { if (sort == Sort.DEF) { - adapter.invokeStatic(definition.defobjType.type, DEF_NOT_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_NOT_CALL); } else { if (sort == Sort.INT) { adapter.push(-1); @@ -209,19 +205,9 @@ public final class EUnary extends AExpression { } } else if (operation == Operation.SUB) { if (sort == Sort.DEF) { - adapter.invokeStatic(definition.defobjType.type, DEF_NEG_CALL); + adapter.invokeStatic(DEF_UTIL_TYPE, DEF_NEG_CALL); } else { - if (settings.getNumericOverflow()) { - adapter.math(MethodWriter.NEG, type); - } else { - if (sort == Sort.INT) { - adapter.invokeStatic(definition.mathType.type, NEGATEEXACT_INT); - } else if (sort == Sort.LONG) { - adapter.invokeStatic(definition.mathType.type, NEGATEEXACT_LONG); - } else { - throw new IllegalStateException(error("Illegal tree structure.")); - } - } + adapter.math(MethodWriter.NEG, type); } } else if (operation != Operation.ADD) { throw new IllegalStateException(error("Illegal tree structure.")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LArrayLength.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LArrayLength.java index 5803fcfa273..4a6df96073e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LArrayLength.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LArrayLength.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -31,14 +30,14 @@ public final class LArrayLength extends ALink { final String value; - LArrayLength(final int line, final String location, final String value) { + LArrayLength(int line, String location, String value) { super(line, location, -1); this.value = value; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if ("length".equals(value)) { if (!load) { throw new IllegalArgumentException(error("Must read array field [length].")); @@ -46,7 +45,7 @@ public final class LArrayLength extends ALink { throw new IllegalArgumentException(error("Cannot write to read-only array field [length].")); } - after = definition.intType; + after = Definition.INT_TYPE; } else { throw new IllegalArgumentException(error("Illegal field access [" + value + "].")); } @@ -55,17 +54,17 @@ public final class LArrayLength extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { adapter.arrayLength(); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LBrace.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LBrace.java index b38826f9e7e..95cc02602f6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LBrace.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LBrace.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Variables; @@ -35,14 +34,14 @@ public final class LBrace extends ALink { AExpression index; - public LBrace(final int line, final String location, final AExpression index) { + public LBrace(int line, String location, AExpression index) { super(line, location, 2); this.index = index; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before == null) { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -50,36 +49,36 @@ public final class LBrace extends ALink { final Sort sort = before.sort; if (sort == Sort.ARRAY) { - index.expected = definition.intType; - index.analyze(settings, definition, variables); - index = index.cast(settings, definition, variables); + index.expected = Definition.INT_TYPE; + index.analyze(variables); + index = index.cast(variables); - after = definition.getType(before.struct, before.dimensions - 1); + after = Definition.getType(before.struct, before.dimensions - 1); return this; } else if (sort == Sort.DEF) { - return new LDefArray(line, location, index).copy(this).analyze(settings, definition, variables); + return new LDefArray(line, location, index).copy(this).analyze(variables); } else if (Map.class.isAssignableFrom(before.clazz)) { - return new LMapShortcut(line, location, index).copy(this).analyze(settings, definition, variables); + return new LMapShortcut(line, location, index).copy(this).analyze(variables); } else if (List.class.isAssignableFrom(before.clazz)) { - return new LListShortcut(line, location, index).copy(this).analyze(settings, definition, variables); + return new LListShortcut(line, location, index).copy(this).analyze(variables); } throw new IllegalArgumentException(error("Illegal array access on type [" + before.name + "].")); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - index.write(settings, definition, adapter); + void write(MethodWriter adapter) { + index.write(adapter); } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { adapter.arrayLoad(after.type); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { adapter.arrayStore(after.type); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCall.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCall.java index bd76aa293cc..fdb6612e1f4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCall.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCall.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Struct; @@ -38,7 +37,7 @@ public final class LCall extends ALink { Method method = null; - public LCall(final int line, final String location, final String name, final List arguments) { + public LCall(int line, String location, String name, List arguments) { super(line, location, -1); this.name = name; @@ -46,7 +45,7 @@ public final class LCall extends ALink { } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before == null) { throw new IllegalStateException(error("Illegal tree structure.")); } else if (before.sort == Definition.Sort.ARRAY) { @@ -64,8 +63,9 @@ public final class LCall extends ALink { final AExpression expression = arguments.get(argument); expression.expected = method.arguments.get(argument); - expression.analyze(settings, definition, variables); - arguments.set(argument, expression.cast(settings, definition, variables)); + expression.internal = true; + expression.analyze(variables); + arguments.set(argument, expression.cast(variables)); } statement = true; @@ -76,22 +76,22 @@ public final class LCall extends ALink { final ALink link = new LDefCall(line, location, name, arguments); link.copy(this); - return link.analyze(settings, definition, variables); + return link.analyze(variables); } - throw new IllegalArgumentException(error("Unknown call [" + name + "] with [" + arguments.size() + + throw new IllegalArgumentException(error("Unknown call [" + name + "] with [" + arguments.size() + "] arguments on type [" + struct.name + "].")); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { for (final AExpression argument : arguments) { - argument.write(settings, definition, adapter); + argument.write(adapter); } if (java.lang.reflect.Modifier.isStatic(method.reflect.getModifiers())) { @@ -108,7 +108,7 @@ public final class LCall extends ALink { } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCast.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCast.java index eb7fb3a6b10..8e917c5b99e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCast.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCast.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.AnalyzerCaster; @@ -35,14 +34,14 @@ public final class LCast extends ALink { Cast cast = null; - public LCast(final int line, final String location, final String type) { + public LCast(int line, String location, String type) { super(line, location, -1); this.type = type; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before == null) { throw new IllegalStateException(error("Illegal tree structure.")); } else if (store) { @@ -50,28 +49,28 @@ public final class LCast extends ALink { } try { - after = definition.getType(type); + after = Definition.getType(type); } catch (final IllegalArgumentException exception) { throw new IllegalArgumentException(error("Not a type [" + type + "].")); } - cast = AnalyzerCaster.getLegalCast(definition, location, before, after, true); + cast = AnalyzerCaster.getLegalCast(location, before, after, true, false); return cast != null ? this : null; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { adapter.writeCast(cast); } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { // Do nothing. } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefArray.java index 98b2fbe7bf9..1ef12026e65 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefArray.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.DefBootstrap; import org.elasticsearch.painless.Variables; @@ -35,37 +34,37 @@ final class LDefArray extends ALink implements IDefLink { AExpression index; - LDefArray(final int line, final String location, final AExpression index) { + LDefArray(int line, String location, AExpression index) { super(line, location, 2); this.index = index; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - index.analyze(settings, definition, variables); + ALink analyze(Variables variables) { + index.analyze(variables); index.expected = index.actual; - index = index.cast(settings, definition, variables); + index = index.cast(variables); - after = definition.defType; + after = Definition.DEF_TYPE; return this; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - index.write(settings, definition, adapter); + void write(MethodWriter adapter) { + index.write(adapter); } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - final String desc = Type.getMethodDescriptor(after.type, definition.defType.type, index.actual.type); + void load(MethodWriter adapter) { + final String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type, index.actual.type); adapter.invokeDynamic("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_LOAD); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type, + void store(MethodWriter adapter) { + final String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, index.actual.type, after.type); adapter.invokeDynamic("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_STORE); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefCall.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefCall.java index 9dbe65110ee..a9d1cb2b892 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefCall.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefCall.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.DefBootstrap; import org.elasticsearch.painless.Variables; @@ -37,7 +36,7 @@ final class LDefCall extends ALink implements IDefLink { final String name; final List arguments; - LDefCall(final int line, final String location, final String name, final List arguments) { + LDefCall(int line, String location, String name, List arguments) { super(line, location, -1); this.name = name; @@ -45,39 +44,40 @@ final class LDefCall extends ALink implements IDefLink { } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { for (int argument = 0; argument < arguments.size(); ++argument) { final AExpression expression = arguments.get(argument); - expression.analyze(settings, definition, variables); + expression.internal = true; + expression.analyze(variables); expression.expected = expression.actual; - arguments.set(argument, expression.cast(settings, definition, variables)); + arguments.set(argument, expression.cast(variables)); } statement = true; - after = definition.defType; + after = Definition.DEF_TYPE; return this; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { final StringBuilder signature = new StringBuilder(); signature.append('('); // first parameter is the receiver, we never know its type: always Object - signature.append(definition.defType.type.getDescriptor()); + signature.append(Definition.DEF_TYPE.type.getDescriptor()); // TODO: remove our explicit conversions and feed more type information for return value, // it can avoid some unnecessary boxing etc. for (final AExpression argument : arguments) { signature.append(argument.actual.type.getDescriptor()); - argument.write(settings, definition, adapter); + argument.write(adapter); } signature.append(')'); @@ -88,7 +88,7 @@ final class LDefCall extends ALink implements IDefLink { } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java index 759b407cb5a..ee0cf990c5b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.DefBootstrap; import org.elasticsearch.painless.Variables; @@ -35,7 +34,7 @@ final class LDefField extends ALink implements IDefLink { final String value; - LDefField(final int line, final String location, final String value) { + LDefField(int line, String location, String value) { super(line, location, 1); this.value = value; @@ -43,26 +42,26 @@ final class LDefField extends ALink implements IDefLink { @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - after = definition.defType; + ALink analyze(Variables variables) { + after = Definition.DEF_TYPE; return this; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - final String desc = Type.getMethodDescriptor(after.type, definition.defType.type); + void load(MethodWriter adapter) { + final String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type); adapter.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.LOAD); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type, after.type); + void store(MethodWriter adapter) { + final String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, after.type); adapter.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.STORE); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LField.java index 06f820eba26..44ba33acdda 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LField.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Field; import org.elasticsearch.painless.Definition.Sort; @@ -39,14 +38,14 @@ public final class LField extends ALink { Field field; - public LField(final int line, final String location, final String value) { + public LField(int line, String location, String value) { super(line, location, 1); this.value = value; } @Override - ALink analyze(CompilerSettings settings, Definition definition, Variables variables) { + ALink analyze(Variables variables) { if (before == null) { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -54,9 +53,9 @@ public final class LField extends ALink { final Sort sort = before.sort; if (sort == Sort.ARRAY) { - return new LArrayLength(line, location, value).copy(this).analyze(settings, definition, variables); + return new LArrayLength(line, location, value).copy(this).analyze(variables); } else if (sort == Sort.DEF) { - return new LDefField(line, location, value).copy(this).analyze(settings, definition, variables); + return new LDefField(line, location, value).copy(this).analyze(variables); } final Struct struct = before.struct; @@ -80,17 +79,17 @@ public final class LField extends ALink { Character.toUpperCase(value.charAt(0)) + value.substring(1), 1)); if (shortcut) { - return new LShortcut(line, location, value).copy(this).analyze(settings, definition, variables); + return new LShortcut(line, location, value).copy(this).analyze(variables); } else { final EConstant index = new EConstant(line, location, value); - index.analyze(settings, definition, variables); + index.analyze(variables); if (Map.class.isAssignableFrom(before.clazz)) { - return new LMapShortcut(line, location, index).copy(this).analyze(settings, definition, variables); + return new LMapShortcut(line, location, index).copy(this).analyze(variables); } if (List.class.isAssignableFrom(before.clazz)) { - return new LListShortcut(line, location, index).copy(this).analyze(settings, definition, variables); + return new LListShortcut(line, location, index).copy(this).analyze(variables); } } } @@ -99,29 +98,21 @@ public final class LField extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { if (java.lang.reflect.Modifier.isStatic(field.reflect.getModifiers())) { adapter.getStatic(field.owner.type, field.reflect.getName(), field.type.type); - - if (!field.generic.clazz.equals(field.type.clazz)) { - adapter.checkCast(field.generic.type); - } } else { adapter.getField(field.owner.type, field.reflect.getName(), field.type.type); - - if (!field.generic.clazz.equals(field.type.clazz)) { - adapter.checkCast(field.generic.type); - } } } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { if (java.lang.reflect.Modifier.isStatic(field.reflect.getModifiers())) { adapter.putStatic(field.owner.type, field.reflect.getName(), field.type.type); } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LListShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LListShortcut.java index 8526ef1297e..52f82c9d1ca 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LListShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LListShortcut.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Sort; @@ -35,14 +34,14 @@ final class LListShortcut extends ALink { Method getter; Method setter; - LListShortcut(final int line, final String location, final AExpression index) { + LListShortcut(int line, String location, AExpression index) { super(line, location, 2); this.index = index; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { getter = before.struct.methods.get(new Definition.MethodKey("get", 1)); setter = before.struct.methods.get(new Definition.MethodKey("set", 2)); @@ -61,9 +60,9 @@ final class LListShortcut extends ALink { } if ((load || store) && (!load || getter != null) && (!store || setter != null)) { - index.expected = definition.intType; - index.analyze(settings, definition, variables); - index = index.cast(settings, definition, variables); + index.expected = Definition.INT_TYPE; + index.analyze(variables); + index = index.cast(variables); after = setter != null ? setter.arguments.get(1) : getter.rtn; } else { @@ -74,12 +73,12 @@ final class LListShortcut extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - index.write(settings, definition, adapter); + void write(MethodWriter adapter) { + index.write(adapter); } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) { adapter.invokeInterface(getter.owner.type, getter.method); } else { @@ -92,7 +91,7 @@ final class LListShortcut extends ALink { } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) { adapter.invokeInterface(setter.owner.type, setter.method); } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LMapShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LMapShortcut.java index 4efbd4bdf0f..9fbc39d72b3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LMapShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LMapShortcut.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Sort; @@ -35,14 +34,14 @@ final class LMapShortcut extends ALink { Method getter; Method setter; - LMapShortcut(final int line, final String location, final AExpression index) { + LMapShortcut(int line, String location, AExpression index) { super(line, location, 2); this.index = index; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { getter = before.struct.methods.get(new Definition.MethodKey("get", 1)); setter = before.struct.methods.get(new Definition.MethodKey("put", 2)); @@ -61,8 +60,8 @@ final class LMapShortcut extends ALink { if ((load || store) && (!load || getter != null) && (!store || setter != null)) { index.expected = setter != null ? setter.arguments.get(0) : getter.arguments.get(0); - index.analyze(settings, definition, variables); - index = index.cast(settings, definition, variables); + index.analyze(variables); + index = index.cast(variables); after = setter != null ? setter.arguments.get(1) : getter.rtn; } else { @@ -73,12 +72,12 @@ final class LMapShortcut extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - index.write(settings, definition, adapter); + void write(MethodWriter adapter) { + index.write(adapter); } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) { adapter.invokeInterface(getter.owner.type, getter.method); } else { @@ -91,7 +90,7 @@ final class LMapShortcut extends ALink { } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) { adapter.invokeInterface(setter.owner.type, setter.method); } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewArray.java index 67f9769bd6a..da88b45e72d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewArray.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.painless.Variables; @@ -35,7 +34,7 @@ public final class LNewArray extends ALink { final String type; final List arguments; - public LNewArray(final int line, final String location, final String type, final List arguments) { + public LNewArray(int line, String location, String type, List arguments) { super(line, location, -1); this.type = type; @@ -43,7 +42,7 @@ public final class LNewArray extends ALink { } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before != null) { throw new IllegalStateException(error("Illegal tree structure.")); } else if (store) { @@ -55,7 +54,7 @@ public final class LNewArray extends ALink { final Type type; try { - type = definition.getType(this.type); + type = Definition.getType(this.type); } catch (final IllegalArgumentException exception) { throw new IllegalArgumentException(error("Not a type [" + this.type + "].")); } @@ -63,36 +62,36 @@ public final class LNewArray extends ALink { for (int argument = 0; argument < arguments.size(); ++argument) { final AExpression expression = arguments.get(argument); - expression.expected = definition.intType; - expression.analyze(settings, definition, variables); - arguments.set(argument, expression.cast(settings, definition, variables)); + expression.expected = Definition.INT_TYPE; + expression.analyze(variables); + arguments.set(argument, expression.cast(variables)); } - after = definition.getType(type.struct, arguments.size()); + after = Definition.getType(type.struct, arguments.size()); return this; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { for (final AExpression argument : arguments) { - argument.write(settings, definition, adapter); + argument.write(adapter); } if (arguments.size() > 1) { adapter.visitMultiANewArrayInsn(after.type.getDescriptor(), after.type.getDimensions()); } else { - adapter.newArray(definition.getType(after.struct, 0).type); + adapter.newArray(Definition.getType(after.struct, 0).type); } } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewObj.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewObj.java index 227b63cf31f..28209e96f2b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewObj.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewObj.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Constructor; import org.elasticsearch.painless.Definition.Struct; @@ -39,7 +38,7 @@ public final class LNewObj extends ALink { Constructor constructor; - public LNewObj(final int line, final String location, final String type, final List arguments) { + public LNewObj(int line, String location, String type, List arguments) { super(line, location, -1); this.type = type; @@ -47,7 +46,7 @@ public final class LNewObj extends ALink { } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before != null) { throw new IllegalStateException(error("Illegal tree structure")); } else if (store) { @@ -57,7 +56,7 @@ public final class LNewObj extends ALink { final Type type; try { - type = definition.getType(this.type); + type = Definition.getType(this.type); } catch (final IllegalArgumentException exception) { throw new IllegalArgumentException(error("Not a type [" + this.type + "].")); } @@ -78,8 +77,9 @@ public final class LNewObj extends ALink { final AExpression expression = arguments.get(argument); expression.expected = types[argument]; - expression.analyze(settings, definition, variables); - arguments.set(argument, expression.cast(settings, definition, variables)); + expression.internal = true; + expression.analyze(variables); + arguments.set(argument, expression.cast(variables)); } statement = true; @@ -92,27 +92,27 @@ public final class LNewObj extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { adapter.newInstance(after.type); if (load) { adapter.dup(); } - for (final AExpression argument : arguments) { - argument.write(settings, definition, adapter); + for (AExpression argument : arguments) { + argument.write(adapter); } adapter.invokeConstructor(constructor.owner.type, constructor.method); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LShortcut.java index c65077e6e28..85a7d70c46e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LShortcut.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Sort; @@ -37,14 +36,14 @@ final class LShortcut extends ALink { Method getter = null; Method setter = null; - LShortcut(final int line, final String location, final String value) { + LShortcut(int line, String location, String value) { super(line, location, 1); this.value = value; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { final Struct struct = before.struct; getter = struct.methods.get(new Definition.MethodKey("get" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 0)); @@ -74,12 +73,12 @@ final class LShortcut extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) { adapter.invokeInterface(getter.owner.type, getter.method); } else { @@ -92,7 +91,7 @@ final class LShortcut extends ALink { } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) { adapter.invokeInterface(setter.owner.type, setter.method); } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LString.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LString.java index 1d11652f483..07d76d42676 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LString.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LString.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -29,14 +28,14 @@ import org.elasticsearch.painless.MethodWriter; */ public final class LString extends ALink { - public LString(final int line, final String location, final String string) { + public LString(int line, String location, String string) { super(line, location, -1); this.string = string; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before != null) { throw new IllegalStateException("Illegal tree structure."); } else if (store) { @@ -45,23 +44,23 @@ public final class LString extends ALink { throw new IllegalArgumentException(error("Must read String constant [" + string + "].")); } - after = definition.stringType; + after = Definition.STRING_TYPE; return this; } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { adapter.push(string); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { throw new IllegalStateException(error("Illegal tree structure.")); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LVariable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LVariable.java index 35a652f5b84..85a2048bdc6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LVariable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LVariable.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.painless.Variables; @@ -36,14 +35,14 @@ public final class LVariable extends ALink { int slot; - public LVariable(final int line, final String location, final String name) { + public LVariable(int line, String location, String name) { super(line, location, 0); this.name = name; } @Override - ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + ALink analyze(Variables variables) { if (before != null) { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -51,7 +50,7 @@ public final class LVariable extends ALink { Type type = null; try { - type = definition.getType(name); + type = Definition.getType(name); } catch (final IllegalArgumentException exception) { // Do nothing. } @@ -74,17 +73,17 @@ public final class LVariable extends ALink { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { // Do nothing. } @Override - void load(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void load(MethodWriter adapter) { adapter.visitVarInsn(after.type.getOpcode(Opcodes.ILOAD), slot); } @Override - void store(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void store(MethodWriter adapter) { adapter.visitVarInsn(after.type.getOpcode(Opcodes.ISTORE), slot); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java index 802d5b6c415..a925c411a2a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -34,17 +32,17 @@ public final class SBlock extends AStatement { final List statements; - public SBlock(final int line, final String location, final List statements) { + public SBlock(int line, String location, List statements) { super(line, location); this.statements = Collections.unmodifiableList(statements); } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { final AStatement last = statements.get(statements.size() - 1); - for (final AStatement statement : statements) { + for (AStatement statement : statements) { if (allEscape) { throw new IllegalArgumentException(error("Unreachable statement.")); } @@ -53,7 +51,7 @@ public final class SBlock extends AStatement { statement.lastSource = lastSource && statement == last; statement.lastLoop = (beginLoop || lastLoop) && statement == last; - statement.analyze(settings, definition, variables); + statement.analyze(variables); methodEscape = statement.methodEscape; loopEscape = statement.loopEscape; @@ -65,11 +63,11 @@ public final class SBlock extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { - for (final AStatement statement : statements) { + void write(MethodWriter adapter) { + for (AStatement statement : statements) { statement.continu = continu; statement.brake = brake; - statement.write(settings, definition, adapter); + statement.write(adapter); } } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java index 3998b1a9ff2..fb12a2b452e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -29,12 +27,12 @@ import org.elasticsearch.painless.MethodWriter; */ public final class SBreak extends AStatement { - public SBreak(final int line, final String location) { + public SBreak(int line, String location) { super(line, location); } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (!inLoop) { throw new IllegalArgumentException(error("Break statement outside of a loop.")); } @@ -46,7 +44,7 @@ public final class SBreak extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); adapter.goTo(brake); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java index 2c4e33b6326..01ca3f5697d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -29,12 +27,12 @@ import org.elasticsearch.painless.MethodWriter; */ public final class SContinue extends AStatement { - public SContinue(final int line, final String location) { + public SContinue(int line, String location) { super(line, location); } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { if (!inLoop) { throw new IllegalArgumentException(error("Continue statement outside of a loop.")); } @@ -49,7 +47,7 @@ public final class SContinue extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); adapter.goTo(continu); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java index 5494ef9c32a..917dd9b8e5a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -34,25 +32,25 @@ public final class SDeclBlock extends AStatement { final List declarations; - public SDeclBlock(final int line, final String location, final List declarations) { + public SDeclBlock(int line, String location, List declarations) { super(line, location); this.declarations = Collections.unmodifiableList(declarations); } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { for (final SDeclaration declaration : declarations) { - declaration.analyze(settings, definition, variables); + declaration.analyze(variables); } statementCount = declarations.size(); } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { for (final SDeclaration declaration : declarations) { - declaration.write(settings, definition, adapter); + declaration.write(adapter); } } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java index 189ddc95936..0e366dfc19b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.Variables.Variable; @@ -38,7 +36,7 @@ public final class SDeclaration extends AStatement { Variable variable; - public SDeclaration(final int line, final String location, final String type, final String name, final AExpression expression) { + public SDeclaration(int line, String location, String type, String name, AExpression expression) { super(line, location); this.type = type; @@ -47,18 +45,18 @@ public final class SDeclaration extends AStatement { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { variable = variables.addVariable(location, type, name, false, false); if (expression != null) { expression.expected = variable.type; - expression.analyze(settings, definition, variables); - expression = expression.cast(settings, definition, variables); + expression.analyze(variables); + expression = expression.cast(variables); } } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final org.objectweb.asm.Type type = variable.type.type; final Sort sort = variable.type.sort; @@ -66,7 +64,7 @@ public final class SDeclaration extends AStatement { final boolean initialize = expression == null; if (!initialize) { - expression.write(settings, definition, adapter); + expression.write(adapter); } switch (sort) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java index 63d3df4bcee..6c8785a923a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; @@ -32,30 +31,32 @@ public final class SDo extends AStatement { final AStatement block; AExpression condition; + final int maxLoopCounter; - public SDo(final int line, final String location, final AStatement block, final AExpression condition) { + public SDo(int line, String location, AStatement block, AExpression condition, int maxLoopCounter) { super(line, location); this.condition = condition; this.block = block; + this.maxLoopCounter = maxLoopCounter; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { variables.incrementScope(); block.beginLoop = true; block.inLoop = true; - block.analyze(settings, definition, variables); + block.analyze(variables); if (block.loopEscape && !block.anyContinue) { throw new IllegalArgumentException(error("Extraneous do while loop.")); } - condition.expected = definition.booleanType; - condition.analyze(settings, definition, variables); - condition = condition.cast(settings, definition, variables); + condition.expected = Definition.BOOLEAN_TYPE; + condition.analyze(variables); + condition = condition.cast(variables); if (condition.constant != null) { final boolean continuous = (boolean)condition.constant; @@ -72,7 +73,7 @@ public final class SDo extends AStatement { statementCount = 1; - if (settings.getMaxLoopCounter() > 0) { + if (maxLoopCounter > 0) { loopCounterSlot = variables.getVariable(location, "#loop").slot; } @@ -80,7 +81,7 @@ public final class SDo extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label start = new Label(); final Label begin = new Label(); @@ -90,12 +91,12 @@ public final class SDo extends AStatement { block.continu = begin; block.brake = end; - block.write(settings, definition, adapter); + block.write(adapter); adapter.mark(begin); condition.fals = end; - condition.write(settings, definition, adapter); + condition.write(adapter); adapter.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount)); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java index dd7cffaa970..9d2bc6385a5 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Definition.Sort; import org.elasticsearch.painless.Variables; @@ -32,16 +31,16 @@ public final class SExpression extends AStatement { AExpression expression; - public SExpression(final int line, final String location, final AExpression expression) { + public SExpression(int line, String location, AExpression expression) { super(line, location); this.expression = expression; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { expression.read = lastSource; - expression.analyze(settings, definition, variables); + expression.analyze(variables); if (!lastSource && !expression.statement) { throw new IllegalArgumentException(error("Not a statement.")); @@ -49,8 +48,9 @@ public final class SExpression extends AStatement { final boolean rtn = lastSource && expression.actual.sort != Sort.VOID; - expression.expected = rtn ? definition.objectType : expression.actual; - expression = expression.cast(settings, definition, variables); + expression.expected = rtn ? Definition.OBJECT_TYPE : expression.actual; + expression.internal = rtn; + expression = expression.cast(variables); methodEscape = rtn; loopEscape = rtn; @@ -59,9 +59,9 @@ public final class SExpression extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); - expression.write(settings, definition, adapter); + expression.write(adapter); if (methodEscape) { adapter.returnValue(); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java index 43c978b47fa..56073e6e8db 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; @@ -34,31 +33,33 @@ public final class SFor extends AStatement { AExpression condition; AExpression afterthought; final AStatement block; + final int maxLoopCounter; - public SFor(final int line, final String location, - final ANode initializer, final AExpression condition, final AExpression afterthought, final AStatement block) { + public SFor(int line, String location, + ANode initializer, AExpression condition, AExpression afterthought, AStatement block, int maxLoopCounter) { super(line, location); this.initializer = initializer; this.condition = condition; this.afterthought = afterthought; this.block = block; + this.maxLoopCounter = maxLoopCounter; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { variables.incrementScope(); boolean continuous = false; if (initializer != null) { if (initializer instanceof SDeclBlock) { - ((SDeclBlock)initializer).analyze(settings, definition, variables); + ((SDeclBlock)initializer).analyze(variables); } else if (initializer instanceof AExpression) { final AExpression initializer = (AExpression)this.initializer; initializer.read = false; - initializer.analyze(settings, definition, variables); + initializer.analyze(variables); if (!initializer.statement) { throw new IllegalArgumentException(initializer.error("Not a statement.")); @@ -70,9 +71,9 @@ public final class SFor extends AStatement { if (condition != null) { - condition.expected = definition.booleanType; - condition.analyze(settings, definition, variables); - condition = condition.cast(settings, definition, variables); + condition.expected = Definition.BOOLEAN_TYPE; + condition.analyze(variables); + condition = condition.cast(variables); if (condition.constant != null) { continuous = (boolean)condition.constant; @@ -91,7 +92,7 @@ public final class SFor extends AStatement { if (afterthought != null) { afterthought.read = false; - afterthought.analyze(settings, definition, variables); + afterthought.analyze(variables); if (!afterthought.statement) { throw new IllegalArgumentException(afterthought.error("Not a statement.")); @@ -104,7 +105,7 @@ public final class SFor extends AStatement { block.beginLoop = true; block.inLoop = true; - block.analyze(settings, definition, variables); + block.analyze(variables); if (block.loopEscape && !block.anyContinue) { throw new IllegalArgumentException(error("Extraneous for loop.")); @@ -120,7 +121,7 @@ public final class SFor extends AStatement { statementCount = 1; - if (settings.getMaxLoopCounter() > 0) { + if (maxLoopCounter > 0) { loopCounterSlot = variables.getVariable(location, "#loop").slot; } @@ -128,18 +129,18 @@ public final class SFor extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label start = new Label(); final Label begin = afterthought == null ? start : new Label(); final Label end = new Label(); if (initializer instanceof SDeclBlock) { - ((SDeclBlock)initializer).write(settings, definition, adapter); + ((SDeclBlock)initializer).write(adapter); } else if (initializer instanceof AExpression) { AExpression initializer = (AExpression)this.initializer; - initializer.write(settings, definition, adapter); + initializer.write(adapter); adapter.writePop(initializer.expected.sort.size); } @@ -147,7 +148,7 @@ public final class SFor extends AStatement { if (condition != null) { condition.fals = end; - condition.write(settings, definition, adapter); + condition.write(adapter); } boolean allEscape = false; @@ -162,14 +163,14 @@ public final class SFor extends AStatement { } adapter.writeLoopCounter(loopCounterSlot, statementCount); - block.write(settings, definition, adapter); + block.write(adapter); } else { adapter.writeLoopCounter(loopCounterSlot, 1); } if (afterthought != null) { adapter.mark(begin); - afterthought.write(settings, definition, adapter); + afterthought.write(adapter); } if (afterthought != null || !allEscape) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java index 698d8c8126c..560ce44e415 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; @@ -34,8 +33,7 @@ public final class SIfElse extends AStatement { final AStatement ifblock; final AStatement elseblock; - public SIfElse(final int line, final String location, - final AExpression condition, final AStatement ifblock, final AStatement elseblock) { + public SIfElse(int line, String location, AExpression condition, AStatement ifblock, AStatement elseblock) { super(line, location); this.condition = condition; @@ -44,10 +42,10 @@ public final class SIfElse extends AStatement { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - condition.expected = definition.booleanType; - condition.analyze(settings, definition, variables); - condition = condition.cast(settings, definition, variables); + void analyze(Variables variables) { + condition.expected = Definition.BOOLEAN_TYPE; + condition.analyze(variables); + condition = condition.cast(variables); if (condition.constant != null) { throw new IllegalArgumentException(error("Extraneous if statement.")); @@ -58,7 +56,7 @@ public final class SIfElse extends AStatement { ifblock.lastLoop = lastLoop; variables.incrementScope(); - ifblock.analyze(settings, definition, variables); + ifblock.analyze(variables); variables.decrementScope(); anyContinue = ifblock.anyContinue; @@ -71,7 +69,7 @@ public final class SIfElse extends AStatement { elseblock.lastLoop = lastLoop; variables.incrementScope(); - elseblock.analyze(settings, definition, variables); + elseblock.analyze(variables); variables.decrementScope(); methodEscape = ifblock.methodEscape && elseblock.methodEscape; @@ -84,17 +82,17 @@ public final class SIfElse extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label end = new Label(); final Label fals = elseblock != null ? new Label() : end; condition.fals = fals; - condition.write(settings, definition, adapter); + condition.write(adapter); ifblock.continu = continu; ifblock.brake = brake; - ifblock.write(settings, definition, adapter); + ifblock.write(adapter); if (elseblock != null) { if (!ifblock.allEscape) { @@ -105,7 +103,7 @@ public final class SIfElse extends AStatement { elseblock.continu = continu; elseblock.brake = brake; - elseblock.write(settings, definition, adapter); + elseblock.write(adapter); } adapter.mark(end); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java index b959b47a96b..ecdf5c7b69a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -31,17 +30,18 @@ public final class SReturn extends AStatement { AExpression expression; - public SReturn(final int line, final String location, final AExpression expression) { + public SReturn(int line, String location, AExpression expression) { super(line, location); this.expression = expression; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - expression.expected = definition.objectType; - expression.analyze(settings, definition, variables); - expression = expression.cast(settings, definition, variables); + void analyze(Variables variables) { + expression.expected = Definition.OBJECT_TYPE; + expression.internal = true; + expression.analyze(variables); + expression = expression.cast(variables); methodEscape = true; loopEscape = true; @@ -51,9 +51,9 @@ public final class SReturn extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); - expression.write(settings, definition, adapter); + expression.write(adapter); adapter.returnValue(); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java index e5a80802ce8..0932ae6e2f0 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Opcodes; import org.elasticsearch.painless.MethodWriter; @@ -35,14 +33,14 @@ public final class SSource extends AStatement { final List statements; - public SSource(final int line, final String location, final List statements) { + public SSource(int line, String location, List statements) { super(line, location); this.statements = Collections.unmodifiableList(statements); } @Override - public void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + public void analyze(Variables variables) { variables.incrementScope(); final AStatement last = statements.get(statements.size() - 1); @@ -53,7 +51,7 @@ public final class SSource extends AStatement { } statement.lastSource = statement == last; - statement.analyze(settings, definition, variables); + statement.analyze(variables); methodEscape = statement.methodEscape; allEscape = statement.allEscape; @@ -63,9 +61,9 @@ public final class SSource extends AStatement { } @Override - public void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + public void write(MethodWriter adapter) { for (final AStatement statement : statements) { - statement.write(settings, definition, adapter); + statement.write(adapter); } if (!methodEscape) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java index eac039b998e..a0bfa12e267 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.MethodWriter; @@ -31,17 +30,17 @@ public final class SThrow extends AStatement { AExpression expression; - public SThrow(final int line, final String location, final AExpression expression) { + public SThrow(int line, String location, AExpression expression) { super(line, location); this.expression = expression; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { - expression.expected = definition.exceptionType; - expression.analyze(settings, definition, variables); - expression = expression.cast(settings, definition, variables); + void analyze(Variables variables) { + expression.expected = Definition.EXCEPTION_TYPE; + expression.analyze(variables); + expression = expression.cast(variables); methodEscape = true; loopEscape = true; @@ -50,9 +49,9 @@ public final class SThrow extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); - expression.write(settings, definition, adapter); + expression.write(adapter); adapter.throwException(); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STrap.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STrap.java index acb50a2b962..9a791b1615d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STrap.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STrap.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.elasticsearch.painless.Variables.Variable; import org.objectweb.asm.Label; @@ -42,7 +40,7 @@ public final class STrap extends AStatement { Label end; Label exception; - public STrap(final int line, final String location, final String type, final String name, final AStatement block) { + public STrap(int line, String location, String type, String name, AStatement block) { super(line, location); this.type = type; @@ -51,7 +49,7 @@ public final class STrap extends AStatement { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { variable = variables.addVariable(location, type, name, true, false); if (!Exception.class.isAssignableFrom(variable.type.clazz)) { @@ -63,7 +61,7 @@ public final class STrap extends AStatement { block.inLoop = inLoop; block.lastLoop = lastLoop; - block.analyze(settings, definition, variables); + block.analyze(variables); methodEscape = block.methodEscape; loopEscape = block.loopEscape; @@ -75,7 +73,7 @@ public final class STrap extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label jump = new Label(); @@ -85,7 +83,7 @@ public final class STrap extends AStatement { if (block != null) { block.continu = continu; block.brake = brake; - block.write(settings, definition, adapter); + block.write(adapter); } adapter.visitTryCatchBlock(begin, end, jump, variable.type.type.getInternalName()); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java index 0329826b02a..4f97d5835cc 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java @@ -19,8 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; import org.elasticsearch.painless.MethodWriter; @@ -36,7 +34,7 @@ public final class STry extends AStatement { final AStatement block; final List traps; - public STry(final int line, final String location, final AStatement block, final List traps) { + public STry(int line, String location, AStatement block, List traps) { super(line, location); this.block = block; @@ -44,13 +42,13 @@ public final class STry extends AStatement { } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { block.lastSource = lastSource; block.inLoop = inLoop; block.lastLoop = lastLoop; variables.incrementScope(); - block.analyze(settings, definition, variables); + block.analyze(variables); variables.decrementScope(); methodEscape = block.methodEscape; @@ -67,7 +65,7 @@ public final class STry extends AStatement { trap.lastLoop = lastLoop; variables.incrementScope(); - trap.analyze(settings, definition, variables); + trap.analyze(variables); variables.decrementScope(); methodEscape &= trap.methodEscape; @@ -83,7 +81,7 @@ public final class STry extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label begin = new Label(); final Label end = new Label(); @@ -93,7 +91,7 @@ public final class STry extends AStatement { block.continu = continu; block.brake = brake; - block.write(settings, definition, adapter); + block.write(adapter); if (!block.allEscape) { adapter.goTo(exception); @@ -105,7 +103,7 @@ public final class STry extends AStatement { trap.begin = begin; trap.end = end; trap.exception = traps.size() > 1 ? exception : null; - trap.write(settings, definition, adapter); + trap.write(adapter); } if (!block.allEscape || traps.size() > 1) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java index f6f8ddc678f..48f59c55189 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java @@ -19,7 +19,6 @@ package org.elasticsearch.painless.node; -import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.Definition; import org.elasticsearch.painless.Variables; import org.objectweb.asm.Label; @@ -32,21 +31,23 @@ public final class SWhile extends AStatement { AExpression condition; final AStatement block; + final int maxLoopCounter; - public SWhile(final int line, final String location, final AExpression condition, final AStatement block) { + public SWhile(int line, String location, AExpression condition, AStatement block, int maxLoopCounter) { super(line, location); this.condition = condition; this.block = block; + this.maxLoopCounter = maxLoopCounter; } @Override - void analyze(final CompilerSettings settings, final Definition definition, final Variables variables) { + void analyze(Variables variables) { variables.incrementScope(); - condition.expected = definition.booleanType; - condition.analyze(settings, definition, variables); - condition = condition.cast(settings, definition, variables); + condition.expected = Definition.BOOLEAN_TYPE; + condition.analyze(variables); + condition = condition.cast(variables); boolean continuous = false; @@ -68,7 +69,7 @@ public final class SWhile extends AStatement { block.beginLoop = true; block.inLoop = true; - block.analyze(settings, definition, variables); + block.analyze(variables); if (block.loopEscape && !block.anyContinue) { throw new IllegalArgumentException(error("Extranous while loop.")); @@ -84,7 +85,7 @@ public final class SWhile extends AStatement { statementCount = 1; - if (settings.getMaxLoopCounter() > 0) { + if (maxLoopCounter > 0) { loopCounterSlot = variables.getVariable(location, "#loop").slot; } @@ -92,7 +93,7 @@ public final class SWhile extends AStatement { } @Override - void write(final CompilerSettings settings, final Definition definition, final MethodWriter adapter) { + void write(MethodWriter adapter) { writeDebugInfo(adapter); final Label begin = new Label(); final Label end = new Label(); @@ -100,14 +101,14 @@ public final class SWhile extends AStatement { adapter.mark(begin); condition.fals = end; - condition.write(settings, definition, adapter); + condition.write(adapter); if (block != null) { adapter.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount)); block.continu = begin; block.brake = end; - block.write(settings, definition, adapter); + block.write(adapter); } else { adapter.writeLoopCounter(loopCounterSlot, 1); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java index ab6944619ca..0d4e993b39b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java @@ -22,6 +22,7 @@ *

* The following are the types of nodes: * A* (abstract) - These are the abstract nodes that are the superclasses for the other types. + * I* (interface) -- Thse are marker interfaces to denote a property of the node. * S* (statement) - These are nodes that represent a statement in Painless. These are the highest level nodes. * E* (expression) - These are nodess that represent an expression in Painless. These are the middle level nodes. * L* (link) - These are nodes that respresent a piece of a variable/method chain. The are the lowest level nodes. diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/definition.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/definition.txt new file mode 100644 index 00000000000..379fadb9865 --- /dev/null +++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/definition.txt @@ -0,0 +1,375 @@ +# +# Licensed to Elasticsearch under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# Painless definition file. This defines the hierarchy of classes, +# what methods and fields they have, etc. +# + +# primitive types + +class void -> void { +} + +class boolean -> boolean { +} + +class byte -> byte { +} + +class short -> short { +} + +class char -> char { +} + +class int -> int { +} + +class long -> long { +} + +class float -> float { +} + +class double -> double { +} + +# basic JDK classes + +class Object -> java.lang.Object { + boolean equals(Object) + int hashCode() + String toString() +} + +class def -> java.lang.Object { + boolean equals(Object) + int hashCode() + String toString() +} + +class Void -> java.lang.Void extends Object { +} + +class Boolean -> java.lang.Boolean extends Object { + Boolean TRUE + Boolean FALSE + int compare(boolean,boolean) + boolean parseBoolean(String) + Boolean valueOf(boolean) + boolean booleanValue() + int compareTo(Boolean) +} + +class Byte -> java.lang.Byte extends Number,Object { + byte MIN_VALUE + byte MAX_VALUE + int compare(byte,byte) + int compareTo(Byte) + byte parseByte(String) + Byte valueOf(byte) +} + +class Short -> java.lang.Short extends Number,Object { + short MIN_VALUE + short MAX_VALUE + int compare(short,short) + int compareTo(Short) + short parseShort(String) + Short valueOf(short) +} + +class Character -> java.lang.Character extends Object { + char MIN_VALUE + char MAX_VALUE + int charCount(int) + char charValue() + int compare(char,char) + int compareTo(Character) + int digit(int,int) + char forDigit(int,int) + String getName(int) + int getNumericValue(int) + boolean isAlphabetic(int) + boolean isDefined(int) + boolean isDigit(int) + boolean isIdeographic(int) + boolean isLetter(int) + boolean isLetterOrDigit(int) + boolean isLowerCase(int) + boolean isMirrored(int) + boolean isSpaceChar(int) + boolean isTitleCase(int) + boolean isUpperCase(int) + boolean isWhitespace(int) + Character valueOf(char) +} + +class Integer -> java.lang.Integer extends Number,Object { + int MIN_VALUE + int MAX_VALUE + int compare(int,int) + int compareTo(Integer) + int min(int,int) + int max(int,int) + int parseInt(String) + int signum(int) + String toHexString(int) + Integer valueOf(int) +} + +class Long -> java.lang.Long extends Number,Object { + long MIN_VALUE + long MAX_VALUE + int compare(long,long) + int compareTo(Long) + long min(long,long) + long max(long,long) + long parseLong(String) + int signum(long) + String toHexString(long) + Long valueOf(long) +} + +class Float -> java.lang.Float extends Number,Object { + float MIN_VALUE + float MAX_VALUE + int compare(float,float) + int compareTo(Float) + float min(float,float) + float max(float,float) + float parseFloat(String) + String toHexString(float) + Float valueOf(float) +} + +class Double -> java.lang.Double extends Number,Object { + double MIN_VALUE + double MAX_VALUE + int compare(double,double) + int compareTo(Double) + double min(double,double) + double max(double,double) + double parseDouble(String) + String toHexString(double) + Double valueOf(double) +} + +class Number -> java.lang.Number extends Object { + byte byteValue() + short shortValue() + int intValue() + long longValue() + float floatValue() + double doubleValue() +} + +class CharSequence -> java.lang.CharSequence extends Object { + char charAt(int) + int length() +} + +class String -> java.lang.String extends CharSequence,Object { + String () + int codePointAt(int) + int compareTo(String) + String concat(String) + boolean endsWith(String) + int indexOf(String) + int indexOf(String,int) + boolean isEmpty() + String replace(CharSequence,CharSequence) + boolean startsWith(String) + String substring(int,int) + char[] toCharArray() + String trim() +} + +class Math -> java.lang.Math { + double E + double PI + double abs(double) + double acos(double) + double asin(double) + double atan(double) + double atan2(double,double) + double cbrt(double) + double ceil(double) + double cos(double) + double cosh(double) + double exp(double) + double expm1(double) + double floor(double) + double hypot(double,double) + double log(double) + double log10(double) + double log1p(double) + double max(double,double) + double min(double,double) + double pow(double,double) + double random() + double rint(double) + long round(double) + double sin(double) + double sinh(double) + double sqrt(double) + double tan(double) + double tanh(double) + double toDegrees(double) + double toRadians(double) +} + +class Iterator -> java.util.Iterator extends Object { + boolean hasNext() + def next() + void remove() +} + +class Collection -> java.util.Collection extends Object { + boolean add(def) + void clear() + boolean contains(def) + boolean isEmpty() + Iterator iterator() + boolean remove(def) + int size() +} + +class List -> java.util.List extends Collection,Object { + def set(int,def) + def get(int) + def remove(int) + int getLength/size() +} + +class ArrayList -> java.util.ArrayList extends List,Collection,Object { + ArrayList () +} + +class Set -> java.util.Set extends Collection,Object { +} + +class HashSet -> java.util.HashSet extends Set,Collection,Object { + HashSet () +} + +class Map -> java.util.Map extends Object { + def put(def,def) + def get(def) + def remove(def) + boolean isEmpty() + int size() + boolean containsKey(def) + Set keySet() + Collection values() +} + +class HashMap -> java.util.HashMap extends Map,Object { + HashMap () +} + +class Exception -> java.lang.Exception extends Object { + String getMessage() +} + +class ArithmeticException -> java.lang.ArithmeticException extends Exception,Object { + ArithmeticException () +} + +class IllegalArgumentException -> java.lang.IllegalArgumentException extends Exception,Object { + IllegalArgumentException () +} + +class IllegalStateException -> java.lang.IllegalStateException extends Exception,Object { + IllegalStateException () +} + +class NumberFormatException -> java.lang.NumberFormatException extends Exception,Object { + NumberFormatException () +} + +# ES Scripting API + +class GeoPoint -> org.elasticsearch.common.geo.GeoPoint extends Object { + double getLat() + double getLon() +} + +class Strings -> org.elasticsearch.index.fielddata.ScriptDocValues$Strings extends List,Collection,Object { + String getValue() + List getValues() +} + +class Longs -> org.elasticsearch.index.fielddata.ScriptDocValues$Longs extends List,Collection,Object { + long getValue() + List getValues() +} + +class Doubles -> org.elasticsearch.index.fielddata.ScriptDocValues$Doubles extends List,Collection,Object { + double getValue() + List getValues() +} + +class GeoPoints -> org.elasticsearch.index.fielddata.ScriptDocValues$GeoPoints extends List,Collection,Object { + GeoPoint getValue() + List getValues() + double getLat() + double getLon() + double[] getLats() + double[] getLons() + + # geo distance functions... so many... + double factorDistance(double,double) + double factorDistanceWithDefault(double,double,double) + double factorDistance02(double,double) + double factorDistance13(double,double) + double arcDistance(double,double) + double arcDistanceWithDefault(double,double,double) + double arcDistanceInKm(double,double) + double arcDistanceInKmWithDefault(double,double,double) + double arcDistanceInMiles(double,double) + double arcDistanceInMilesWithDefault(double,double,double) + double distance(double,double) + double distanceWithDefault(double,double,double) + double distanceInKm(double,double) + double distanceInKmWithDefault(double,double,double) + double distanceInMiles(double,double) + double distanceInMilesWithDefault(double,double,double) + double geohashDistance(String) + double geohashDistanceInKm(String) + double geohashDistanceInMiles(String) +} + +# for testing. +# currently FeatureTest exposes overloaded constructor, field load store, and overloaded static methods +class FeatureTest -> org.elasticsearch.painless.FeatureTest extends Object { + FeatureTest () + FeatureTest (int,int) + int getX() + int getY() + void setX(int) + void setY(int) + boolean overloadedStatic() + boolean overloadedStatic(boolean) +} + +# currently needed internally +class Executable -> org.elasticsearch.painless.Executable { +} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ArrayTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ArrayTests.java index 2036c4fd04c..8dabacdd5f9 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ArrayTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ArrayTests.java @@ -34,7 +34,7 @@ public class ArrayTests extends ScriptTestCase { assertArrayLength(10, new Integer[10]); assertArrayLength(11, new String[11][2]); } - + private void assertArrayLength(int length, Object array) throws Throwable { assertEquals(length, (int) Def.arrayLengthGetter(array.getClass()).invoke(array)); } @@ -43,36 +43,36 @@ public class ArrayTests extends ScriptTestCase { assertEquals(5, exec("def x = new int[5]; return x.length")); assertEquals(5, exec("def x = new int[4]; x[0] = 5; return x[0];")); } - + public void testArrayLoadStoreString() { assertEquals(5, exec("def x = new String[5]; return x.length")); assertEquals("foobar", exec("def x = new String[4]; x[0] = 'foobar'; return x[0];")); } - + public void testArrayLoadStoreDef() { assertEquals(5, exec("def x = new def[5]; return x.length")); assertEquals(5, exec("def x = new def[4]; x[0] = 5; return x[0];")); } - + public void testArrayCompoundInt() { assertEquals(6, exec("int[] x = new int[5]; x[0] = 5; x[0]++; return x[0];")); } - + public void testArrayCompoundDef() { assertEquals(6, exec("def x = new int[5]; x[0] = 5; x[0]++; return x[0];")); } - + public void testJacksCrazyExpression1() { assertEquals(1, exec("int x; def[] y = new def[1]; x = y[0] = 1; return x;")); } - + public void testJacksCrazyExpression2() { assertEquals(1, exec("int x; def y = new def[1]; x = y[0] = 1; return x;")); } - + public void testForLoop() { assertEquals(999*1000/2, exec("def a = new int[1000]; for (int x = 0; x < a.length; x++) { a[x] = x; } "+ "int total = 0; for (int x = 0; x < a.length; x++) { total += a[x]; } return total;")); } - + } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicAPITests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicAPITests.java index af067d15252..338e3f00113 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicAPITests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicAPITests.java @@ -24,10 +24,8 @@ public class BasicAPITests extends ScriptTestCase { public void testListIterator() { assertEquals(3, exec("List x = new ArrayList(); x.add(2); x.add(3); x.add(-2); Iterator y = x.iterator(); " + "int total = 0; while (y.hasNext()) total += y.next(); return total;")); - assertEquals(3, exec("List x = new ArrayList(); x.add(2); x.add(3); x.add(-2); Iterator y = x.iterator(); " + - "int total = 0; while (y.hasNext()) total += (int)y.next(); return total;")); - assertEquals("abc", exec("List x = new ArrayList(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " + - "Iterator y = x.iterator(); String total = \"\"; while (y.hasNext()) total += y.next(); return total;")); + assertEquals("abc", exec("List x = new ArrayList(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " + + "Iterator y = x.iterator(); String total = \"\"; while (y.hasNext()) total += y.next(); return total;")); assertEquals(3, exec("def x = new ArrayList(); x.add(2); x.add(3); x.add(-2); def y = x.iterator(); " + "def total = 0; while (y.hasNext()) total += y.next(); return total;")); } @@ -35,10 +33,8 @@ public class BasicAPITests extends ScriptTestCase { public void testSetIterator() { assertEquals(3, exec("Set x = new HashSet(); x.add(2); x.add(3); x.add(-2); Iterator y = x.iterator(); " + "int total = 0; while (y.hasNext()) total += y.next(); return total;")); - assertEquals(3, exec("Set x = new HashSet(); x.add(2); x.add(3); x.add(-2); Iterator y = x.iterator(); " + - "int total = 0; while (y.hasNext()) total += (int)y.next(); return total;")); - assertEquals("abc", exec("Set x = new HashSet(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " + - "Iterator y = x.iterator(); String total = \"\"; while (y.hasNext()) total += y.next(); return total;")); + assertEquals("abc", exec("Set x = new HashSet(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " + + "Iterator y = x.iterator(); String total = \"\"; while (y.hasNext()) total += y.next(); return total;")); assertEquals(3, exec("def x = new HashSet(); x.add(2); x.add(3); x.add(-2); def y = x.iterator(); " + "def total = 0; while (y.hasNext()) total += (int)y.next(); return total;")); } @@ -49,41 +45,49 @@ public class BasicAPITests extends ScriptTestCase { assertEquals(3, exec("Map x = new HashMap(); x.put(2, 2); x.put(3, 3); x.put(-2, -2); Iterator y = x.values().iterator(); " + "int total = 0; while (y.hasNext()) total += (int)y.next(); return total;")); } - + /** Test loads and stores with a map */ public void testMapLoadStore() { assertEquals(5, exec("def x = new HashMap(); x.abc = 5; return x.abc;")); assertEquals(5, exec("def x = new HashMap(); x['abc'] = 5; return x['abc'];")); } - + /** Test loads and stores with a list */ public void testListLoadStore() { assertEquals(5, exec("def x = new ArrayList(); x.add(3); x.0 = 5; return x.0;")); assertEquals(5, exec("def x = new ArrayList(); x.add(3); x[0] = 5; return x[0];")); } - + /** Test shortcut for getters with isXXXX */ public void testListEmpty() { assertEquals(true, exec("def x = new ArrayList(); return x.empty;")); assertEquals(true, exec("def x = new HashMap(); return x.empty;")); } - + /** Test list method invocation */ public void testListGet() { assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x.get(0);")); assertEquals(5, exec("def x = new ArrayList(); x.add(5); def index = 0; return x.get(index);")); } - + public void testListAsArray() { assertEquals(1, exec("def x = new ArrayList(); x.add(5); return x.length")); assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x[0]")); assertEquals(1, exec("List x = new ArrayList(); x.add('Hallo'); return x.length")); - assertEquals(1, exec("List x = new ArrayList(); x.add('Hallo'); return x.length")); - assertEquals(1, exec("List x = new ArrayList(); x.add('Hallo'); return x.length")); } - + public void testDefAssignments() { assertEquals(2, exec("int x; def y = 2.0; x = (int)y;")); } - + + public void testInternalBoxing() { + assertBytecodeExists("def x = true", "INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;"); + assertBytecodeExists("def x = (byte)1", "INVOKESTATIC java/lang/Byte.valueOf (B)Ljava/lang/Byte;"); + assertBytecodeExists("def x = (short)1", "INVOKESTATIC java/lang/Short.valueOf (S)Ljava/lang/Short;"); + assertBytecodeExists("def x = (char)1", "INVOKESTATIC java/lang/Character.valueOf (C)Ljava/lang/Character;"); + assertBytecodeExists("def x = 1", "INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;"); + assertBytecodeExists("def x = 1L", "INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;"); + assertBytecodeExists("def x = 1F", "INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;"); + assertBytecodeExists("def x = 1D", "INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;"); + } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java index 2fb676bf299..2a8f3674ac1 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java @@ -96,15 +96,15 @@ public class BasicExpressionTests extends ScriptTestCase { } /** - * Test boxed objects in various places + * Test boxed def objects in various places */ public void testBoxing() { // return assertEquals(4, exec("return params.get(\"x\");", Collections.singletonMap("x", 4))); // assignment - assertEquals(4, exec("int y = (Integer)params.get(\"x\"); return y;", Collections.singletonMap("x", 4))); + assertEquals(4, exec("int y = params.get(\"x\"); return y;", Collections.singletonMap("x", 4))); // comparison - assertEquals(true, exec("return 5 > (Integer)params.get(\"x\");", Collections.singletonMap("x", 4))); + assertEquals(true, exec("return 5 > params.get(\"x\");", Collections.singletonMap("x", 4))); } public void testBool() { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java index f0022e6bcf1..0d6a54b515b 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java @@ -135,7 +135,7 @@ public class BasicStatementTests extends ScriptTestCase { assertEquals(2.0, exec("double a = 2; return a;")); assertEquals(false, exec("boolean a = false; return a;")); assertEquals("string", exec("String a = \"string\"; return a;")); - assertEquals(HashMap.class, exec("Map a = new HashMap(); return a;").getClass()); + assertEquals(HashMap.class, exec("Map a = new HashMap(); return a;").getClass()); assertEquals(byte[].class, exec("byte[] a = new byte[1]; return a;").getClass()); assertEquals(short[].class, exec("short[] a = new short[1]; return a;").getClass()); @@ -146,7 +146,7 @@ public class BasicStatementTests extends ScriptTestCase { assertEquals(double[].class, exec("double[] a = new double[1]; return a;").getClass()); assertEquals(boolean[].class, exec("boolean[] a = new boolean[1]; return a;").getClass()); assertEquals(String[].class, exec("String[] a = new String[1]; return a;").getClass()); - assertEquals(Map[].class, exec("Map[] a = new Map[1]; return a;").getClass()); + assertEquals(Map[].class, exec("Map[] a = new Map[1]; return a;").getClass()); assertEquals(byte[][].class, exec("byte[][] a = new byte[1][2]; return a;").getClass()); assertEquals(short[][][].class, exec("short[][][] a = new short[1][2][3]; return a;").getClass()); @@ -157,7 +157,7 @@ public class BasicStatementTests extends ScriptTestCase { assertEquals(double[][][][].class, exec("double[][][][] a = new double[1][2][3][4]; return a;").getClass()); assertEquals(boolean[][][][][].class, exec("boolean[][][][][] a = new boolean[1][2][3][4][5]; return a;").getClass()); assertEquals(String[][].class, exec("String[][] a = new String[1][2]; return a;").getClass()); - assertEquals(Map[][][].class, exec("Map[][][] a = new Map[1][2][3]; return a;").getClass()); + assertEquals(Map[][][].class, exec("Map[][][] a = new Map[1][2][3]; return a;").getClass()); } public void testContinueStatement() { @@ -174,6 +174,6 @@ public class BasicStatementTests extends ScriptTestCase { assertEquals(5, exec("int x = 5; return x;")); assertEquals(4, exec("int[] x = new int[2]; x[1] = 4; return x[1];")); assertEquals(5, ((short[])exec("short[] s = new short[3]; s[1] = 5; return s;"))[1]); - assertEquals(10, ((Map)exec("Map s = new HashMap< String , Object >(); s.put(\"x\", 10); return s;")).get("x")); + assertEquals(10, ((Map)exec("Map s = new HashMap(); s.put(\"x\", 10); return s;")).get("x")); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/CompoundAssignmentTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/CompoundAssignmentTests.java index d54b976d65d..03593116538 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/CompoundAssignmentTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/CompoundAssignmentTests.java @@ -230,18 +230,18 @@ public class CompoundAssignmentTests extends ScriptTestCase { assertEquals(false, exec("boolean x = true; x &= false; return x;")); assertEquals(false, exec("boolean x = false; x &= true; return x;")); assertEquals(false, exec("boolean x = false; x &= false; return x;")); - assertEquals(true, exec("Boolean x = true; x &= true; return x;")); - assertEquals(false, exec("Boolean x = true; x &= false; return x;")); - assertEquals(false, exec("Boolean x = false; x &= true; return x;")); - assertEquals(false, exec("Boolean x = false; x &= false; return x;")); + assertEquals(true, exec("def x = true; x &= true; return x;")); + assertEquals(false, exec("def x = true; x &= false; return x;")); + assertEquals(false, exec("def x = false; x &= true; return x;")); + assertEquals(false, exec("def x = false; x &= false; return x;")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] &= true; return x[0];")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] &= false; return x[0];")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] &= true; return x[0];")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] &= false; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] &= true; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] &= false; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] &= true; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] &= false; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = true; x[0] &= true; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = true; x[0] &= false; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = false; x[0] &= true; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = false; x[0] &= false; return x[0];")); // byte assertEquals((byte) (13 & 14), exec("byte x = 13; x &= 14; return x;")); @@ -261,18 +261,18 @@ public class CompoundAssignmentTests extends ScriptTestCase { assertEquals(true, exec("boolean x = true; x |= false; return x;")); assertEquals(true, exec("boolean x = false; x |= true; return x;")); assertEquals(false, exec("boolean x = false; x |= false; return x;")); - assertEquals(true, exec("Boolean x = true; x |= true; return x;")); - assertEquals(true, exec("Boolean x = true; x |= false; return x;")); - assertEquals(true, exec("Boolean x = false; x |= true; return x;")); - assertEquals(false, exec("Boolean x = false; x |= false; return x;")); + assertEquals(true, exec("def x = true; x |= true; return x;")); + assertEquals(true, exec("def x = true; x |= false; return x;")); + assertEquals(true, exec("def x = false; x |= true; return x;")); + assertEquals(false, exec("def x = false; x |= false; return x;")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] |= true; return x[0];")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] |= false; return x[0];")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] |= true; return x[0];")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] |= false; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] |= true; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] |= false; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] |= true; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] |= false; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = true; x[0] |= true; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = true; x[0] |= false; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = false; x[0] |= true; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = false; x[0] |= false; return x[0];")); // byte assertEquals((byte) (13 | 14), exec("byte x = 13; x |= 14; return x;")); @@ -292,18 +292,18 @@ public class CompoundAssignmentTests extends ScriptTestCase { assertEquals(true, exec("boolean x = true; x ^= false; return x;")); assertEquals(true, exec("boolean x = false; x ^= true; return x;")); assertEquals(false, exec("boolean x = false; x ^= false; return x;")); - assertEquals(false, exec("Boolean x = true; x ^= true; return x;")); - assertEquals(true, exec("Boolean x = true; x ^= false; return x;")); - assertEquals(true, exec("Boolean x = false; x ^= true; return x;")); - assertEquals(false, exec("Boolean x = false; x ^= false; return x;")); + assertEquals(false, exec("def x = true; x ^= true; return x;")); + assertEquals(true, exec("def x = true; x ^= false; return x;")); + assertEquals(true, exec("def x = false; x ^= true; return x;")); + assertEquals(false, exec("def x = false; x ^= false; return x;")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] ^= true; return x[0];")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = true; x[0] ^= false; return x[0];")); assertEquals(true, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] ^= true; return x[0];")); assertEquals(false, exec("boolean[] x = new boolean[1]; x[0] = false; x[0] ^= false; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] ^= true; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = true; x[0] ^= false; return x[0];")); - assertEquals(true, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] ^= true; return x[0];")); - assertEquals(false, exec("Boolean[] x = new Boolean[1]; x[0] = false; x[0] ^= false; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = true; x[0] ^= true; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = true; x[0] ^= false; return x[0];")); + assertEquals(true, exec("def[] x = new def[1]; x[0] = false; x[0] ^= true; return x[0];")); + assertEquals(false, exec("def[] x = new def[1]; x[0] = false; x[0] ^= false; return x[0];")); // byte assertEquals((byte) (13 ^ 14), exec("byte x = 13; x ^= 14; return x;")); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ConditionalTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ConditionalTests.java index 859825f129a..a3a09fee425 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ConditionalTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ConditionalTests.java @@ -65,10 +65,8 @@ public class ConditionalTests extends ScriptTestCase { public void testPromotion() { assertEquals(false, exec("boolean x = false; boolean y = true; return (x ? 2 : 4.0F) == (y ? 2 : 4.0F);")); - assertEquals(false, exec("boolean x = false; boolean y = true; return (x ? 2 : 4.0F) == (y ? new Long(2) : new Float(4.0F));")); assertEquals(false, exec("boolean x = false; boolean y = true; " + - "return (x ? new HashMap() : new ArrayList()) == (y ? new Long(2) : new Float(4.0F));")); - assertEquals(false, exec("boolean x = false; boolean y = true; return (x ? 2 : 4.0F) == (y ? new HashMap() : new ArrayList());")); + "return (x ? new HashMap() : new ArrayList()) == (y ? new HashMap() : new ArrayList());")); } public void testIncompatibleAssignment() { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOperationTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOperationTests.java index bfc0d142045..9f171a96889 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOperationTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOperationTests.java @@ -22,10 +22,10 @@ package org.elasticsearch.painless; public class DefOperationTests extends ScriptTestCase { public void testIllegalCast() { Exception exception = expectThrows(ClassCastException.class, () -> exec("def x = 1.0; int y = x; return y;")); - assertTrue(exception.getMessage().contains("java.lang.Double cannot be cast to java.lang.Integer")); + assertTrue(exception.getMessage().contains("cannot be cast")); exception = expectThrows(ClassCastException.class, () -> exec("def x = (short)1; byte y = x; return y;")); - assertTrue(exception.getMessage().contains("java.lang.Short cannot be cast to java.lang.Byte")); + assertTrue(exception.getMessage().contains("cannot be cast")); } public void testNot() { @@ -103,13 +103,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(4D, exec("def x = (float)2; def y = (double)2; return x * y")); assertEquals(4D, exec("def x = (double)2; def y = (double)2; return x * y")); - assertEquals(4, exec("def x = (Byte)2; def y = (byte)2; return x * y")); - assertEquals(4, exec("def x = (Short)2; def y = (short)2; return x * y")); - assertEquals(4, exec("def x = (Character)2; def y = (char)2; return x * y")); - assertEquals(4, exec("def x = (Integer)2; def y = (int)2; return x * y")); - assertEquals(4L, exec("def x = (Long)2; def y = (long)2; return x * y")); - assertEquals(4F, exec("def x = (Float)2; def y = (float)2; return x * y")); - assertEquals(4D, exec("def x = (Double)2; def y = (double)2; return x * y")); + assertEquals(4, exec("def x = (byte)2; def y = (byte)2; return x * y")); + assertEquals(4, exec("def x = (short)2; def y = (short)2; return x * y")); + assertEquals(4, exec("def x = (char)2; def y = (char)2; return x * y")); + assertEquals(4, exec("def x = (int)2; def y = (int)2; return x * y")); + assertEquals(4L, exec("def x = (long)2; def y = (long)2; return x * y")); + assertEquals(4F, exec("def x = (float)2; def y = (float)2; return x * y")); + assertEquals(4D, exec("def x = (double)2; def y = (double)2; return x * y")); } public void testDiv() { @@ -169,13 +169,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(1D, exec("def x = (float)2; def y = (double)2; return x / y")); assertEquals(1D, exec("def x = (double)2; def y = (double)2; return x / y")); - assertEquals(1, exec("def x = (Byte)2; def y = (byte)2; return x / y")); - assertEquals(1, exec("def x = (Short)2; def y = (short)2; return x / y")); - assertEquals(1, exec("def x = (Character)2; def y = (char)2; return x / y")); - assertEquals(1, exec("def x = (Integer)2; def y = (int)2; return x / y")); - assertEquals(1L, exec("def x = (Long)2; def y = (long)2; return x / y")); - assertEquals(1F, exec("def x = (Float)2; def y = (float)2; return x / y")); - assertEquals(1D, exec("def x = (Double)2; def y = (double)2; return x / y")); + assertEquals(1, exec("def x = (byte)2; def y = (byte)2; return x / y")); + assertEquals(1, exec("def x = (short)2; def y = (short)2; return x / y")); + assertEquals(1, exec("def x = (char)2; def y = (char)2; return x / y")); + assertEquals(1, exec("def x = (int)2; def y = (int)2; return x / y")); + assertEquals(1L, exec("def x = (long)2; def y = (long)2; return x / y")); + assertEquals(1F, exec("def x = (float)2; def y = (float)2; return x / y")); + assertEquals(1D, exec("def x = (double)2; def y = (double)2; return x / y")); } public void testRem() { @@ -235,13 +235,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(0D, exec("def x = (float)2; def y = (double)2; return x % y")); assertEquals(0D, exec("def x = (double)2; def y = (double)2; return x % y")); - assertEquals(0, exec("def x = (Byte)2; def y = (byte)2; return x % y")); - assertEquals(0, exec("def x = (Short)2; def y = (short)2; return x % y")); - assertEquals(0, exec("def x = (Character)2; def y = (char)2; return x % y")); - assertEquals(0, exec("def x = (Integer)2; def y = (int)2; return x % y")); - assertEquals(0L, exec("def x = (Long)2; def y = (long)2; return x % y")); - assertEquals(0F, exec("def x = (Float)2; def y = (float)2; return x % y")); - assertEquals(0D, exec("def x = (Double)2; def y = (double)2; return x % y")); + assertEquals(0, exec("def x = (byte)2; def y = (byte)2; return x % y")); + assertEquals(0, exec("def x = (short)2; def y = (short)2; return x % y")); + assertEquals(0, exec("def x = (char)2; def y = (char)2; return x % y")); + assertEquals(0, exec("def x = (int)2; def y = (int)2; return x % y")); + assertEquals(0L, exec("def x = (long)2; def y = (long)2; return x % y")); + assertEquals(0F, exec("def x = (float)2; def y = (float)2; return x % y")); + assertEquals(0D, exec("def x = (double)2; def y = (double)2; return x % y")); } public void testAdd() { @@ -301,13 +301,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(2D, exec("def x = (float)1; def y = (double)1; return x + y")); assertEquals(2D, exec("def x = (double)1; def y = (double)1; return x + y")); - assertEquals(2, exec("def x = (Byte)1; def y = (byte)1; return x + y")); - assertEquals(2, exec("def x = (Short)1; def y = (short)1; return x + y")); - assertEquals(2, exec("def x = (Character)1; def y = (char)1; return x + y")); - assertEquals(2, exec("def x = (Integer)1; def y = (int)1; return x + y")); - assertEquals(2L, exec("def x = (Long)1; def y = (long)1; return x + y")); - assertEquals(2F, exec("def x = (Float)1; def y = (float)1; return x + y")); - assertEquals(2D, exec("def x = (Double)1; def y = (double)1; return x + y")); + assertEquals(2, exec("def x = (byte)1; def y = (byte)1; return x + y")); + assertEquals(2, exec("def x = (short)1; def y = (short)1; return x + y")); + assertEquals(2, exec("def x = (char)1; def y = (char)1; return x + y")); + assertEquals(2, exec("def x = (int)1; def y = (int)1; return x + y")); + assertEquals(2L, exec("def x = (long)1; def y = (long)1; return x + y")); + assertEquals(2F, exec("def x = (float)1; def y = (float)1; return x + y")); + assertEquals(2D, exec("def x = (double)1; def y = (double)1; return x + y")); } public void testSub() { @@ -367,13 +367,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(0D, exec("def x = (float)1; def y = (double)1; return x - y")); assertEquals(0D, exec("def x = (double)1; def y = (double)1; return x - y")); - assertEquals(0, exec("def x = (Byte)1; def y = (byte)1; return x - y")); - assertEquals(0, exec("def x = (Short)1; def y = (short)1; return x - y")); - assertEquals(0, exec("def x = (Character)1; def y = (char)1; return x - y")); - assertEquals(0, exec("def x = (Integer)1; def y = (int)1; return x - y")); - assertEquals(0L, exec("def x = (Long)1; def y = (long)1; return x - y")); - assertEquals(0F, exec("def x = (Float)1; def y = (float)1; return x - y")); - assertEquals(0D, exec("def x = (Double)1; def y = (double)1; return x - y")); + assertEquals(0, exec("def x = (byte)1; def y = (byte)1; return x - y")); + assertEquals(0, exec("def x = (short)1; def y = (short)1; return x - y")); + assertEquals(0, exec("def x = (char)1; def y = (char)1; return x - y")); + assertEquals(0, exec("def x = (int)1; def y = (int)1; return x - y")); + assertEquals(0L, exec("def x = (long)1; def y = (long)1; return x - y")); + assertEquals(0F, exec("def x = (float)1; def y = (float)1; return x - y")); + assertEquals(0D, exec("def x = (double)1; def y = (double)1; return x - y")); } public void testLsh() { @@ -433,13 +433,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(2L, exec("def x = (float)1; def y = (double)1; return x << y")); assertEquals(2L, exec("def x = (double)1; def y = (double)1; return x << y")); - assertEquals(2, exec("def x = (Byte)1; def y = (byte)1; return x << y")); - assertEquals(2, exec("def x = (Short)1; def y = (short)1; return x << y")); - assertEquals(2, exec("def x = (Character)1; def y = (char)1; return x << y")); - assertEquals(2, exec("def x = (Integer)1; def y = (int)1; return x << y")); - assertEquals(2L, exec("def x = (Long)1; def y = (long)1; return x << y")); - assertEquals(2L, exec("def x = (Float)1; def y = (float)1; return x << y")); - assertEquals(2L, exec("def x = (Double)1; def y = (double)1; return x << y")); + assertEquals(2, exec("def x = (byte)1; def y = (byte)1; return x << y")); + assertEquals(2, exec("def x = (short)1; def y = (short)1; return x << y")); + assertEquals(2, exec("def x = (char)1; def y = (char)1; return x << y")); + assertEquals(2, exec("def x = (int)1; def y = (int)1; return x << y")); + assertEquals(2L, exec("def x = (long)1; def y = (long)1; return x << y")); + assertEquals(2L, exec("def x = (float)1; def y = (float)1; return x << y")); + assertEquals(2L, exec("def x = (double)1; def y = (double)1; return x << y")); } public void testRsh() { @@ -499,13 +499,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(2L, exec("def x = (float)4; def y = (double)1; return x >> y")); assertEquals(2L, exec("def x = (double)4; def y = (double)1; return x >> y")); - assertEquals(2, exec("def x = (Byte)4; def y = (byte)1; return x >> y")); - assertEquals(2, exec("def x = (Short)4; def y = (short)1; return x >> y")); - assertEquals(2, exec("def x = (Character)4; def y = (char)1; return x >> y")); - assertEquals(2, exec("def x = (Integer)4; def y = (int)1; return x >> y")); - assertEquals(2L, exec("def x = (Long)4; def y = (long)1; return x >> y")); - assertEquals(2L, exec("def x = (Float)4; def y = (float)1; return x >> y")); - assertEquals(2L, exec("def x = (Double)4; def y = (double)1; return x >> y")); + assertEquals(2, exec("def x = (byte)4; def y = (byte)1; return x >> y")); + assertEquals(2, exec("def x = (short)4; def y = (short)1; return x >> y")); + assertEquals(2, exec("def x = (char)4; def y = (char)1; return x >> y")); + assertEquals(2, exec("def x = (int)4; def y = (int)1; return x >> y")); + assertEquals(2L, exec("def x = (long)4; def y = (long)1; return x >> y")); + assertEquals(2L, exec("def x = (float)4; def y = (float)1; return x >> y")); + assertEquals(2L, exec("def x = (double)4; def y = (double)1; return x >> y")); } public void testUsh() { @@ -565,13 +565,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(2L, exec("def x = (float)4; def y = (double)1; return x >>> y")); assertEquals(2L, exec("def x = (double)4; def y = (double)1; return x >>> y")); - assertEquals(2, exec("def x = (Byte)4; def y = (byte)1; return x >>> y")); - assertEquals(2, exec("def x = (Short)4; def y = (short)1; return x >>> y")); - assertEquals(2, exec("def x = (Character)4; def y = (char)1; return x >>> y")); - assertEquals(2, exec("def x = (Integer)4; def y = (int)1; return x >>> y")); - assertEquals(2L, exec("def x = (Long)4; def y = (long)1; return x >>> y")); - assertEquals(2L, exec("def x = (Float)4; def y = (float)1; return x >>> y")); - assertEquals(2L, exec("def x = (Double)4; def y = (double)1; return x >>> y")); + assertEquals(2, exec("def x = (byte)4; def y = (byte)1; return x >>> y")); + assertEquals(2, exec("def x = (short)4; def y = (short)1; return x >>> y")); + assertEquals(2, exec("def x = (char)4; def y = (char)1; return x >>> y")); + assertEquals(2, exec("def x = (int)4; def y = (int)1; return x >>> y")); + assertEquals(2L, exec("def x = (long)4; def y = (long)1; return x >>> y")); + assertEquals(2L, exec("def x = (float)4; def y = (float)1; return x >>> y")); + assertEquals(2L, exec("def x = (double)4; def y = (double)1; return x >>> y")); } public void testAnd() { @@ -631,13 +631,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(0L, exec("def x = (float)4; def y = (double)1; return x & y")); assertEquals(0L, exec("def x = (double)4; def y = (double)1; return x & y")); - assertEquals(0, exec("def x = (Byte)4; def y = (byte)1; return x & y")); - assertEquals(0, exec("def x = (Short)4; def y = (short)1; return x & y")); - assertEquals(0, exec("def x = (Character)4; def y = (char)1; return x & y")); - assertEquals(0, exec("def x = (Integer)4; def y = (int)1; return x & y")); - assertEquals(0L, exec("def x = (Long)4; def y = (long)1; return x & y")); - assertEquals(0L, exec("def x = (Float)4; def y = (float)1; return x & y")); - assertEquals(0L, exec("def x = (Double)4; def y = (double)1; return x & y")); + assertEquals(0, exec("def x = (byte)4; def y = (byte)1; return x & y")); + assertEquals(0, exec("def x = (short)4; def y = (short)1; return x & y")); + assertEquals(0, exec("def x = (char)4; def y = (char)1; return x & y")); + assertEquals(0, exec("def x = (int)4; def y = (int)1; return x & y")); + assertEquals(0L, exec("def x = (long)4; def y = (long)1; return x & y")); + assertEquals(0L, exec("def x = (float)4; def y = (float)1; return x & y")); + assertEquals(0L, exec("def x = (double)4; def y = (double)1; return x & y")); } public void testXor() { @@ -697,13 +697,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(5L, exec("def x = (float)4; def y = (double)1; return x ^ y")); assertEquals(5L, exec("def x = (double)4; def y = (double)1; return x ^ y")); - assertEquals(5, exec("def x = (Byte)4; def y = (byte)1; return x ^ y")); - assertEquals(5, exec("def x = (Short)4; def y = (short)1; return x ^ y")); - assertEquals(5, exec("def x = (Character)4; def y = (char)1; return x ^ y")); - assertEquals(5, exec("def x = (Integer)4; def y = (int)1; return x ^ y")); - assertEquals(5L, exec("def x = (Long)4; def y = (long)1; return x ^ y")); - assertEquals(5L, exec("def x = (Float)4; def y = (float)1; return x ^ y")); - assertEquals(5L, exec("def x = (Double)4; def y = (double)1; return x ^ y")); + assertEquals(5, exec("def x = (byte)4; def y = (byte)1; return x ^ y")); + assertEquals(5, exec("def x = (short)4; def y = (short)1; return x ^ y")); + assertEquals(5, exec("def x = (char)4; def y = (char)1; return x ^ y")); + assertEquals(5, exec("def x = (int)4; def y = (int)1; return x ^ y")); + assertEquals(5L, exec("def x = (long)4; def y = (long)1; return x ^ y")); + assertEquals(5L, exec("def x = (float)4; def y = (float)1; return x ^ y")); + assertEquals(5L, exec("def x = (double)4; def y = (double)1; return x ^ y")); } public void testOr() { @@ -763,13 +763,13 @@ public class DefOperationTests extends ScriptTestCase { assertEquals(5L, exec("def x = (float)4; def y = (double)1; return x | y")); assertEquals(5L, exec("def x = (double)4; def y = (double)1; return x | y")); - assertEquals(5, exec("def x = (Byte)4; def y = (byte)1; return x | y")); - assertEquals(5, exec("def x = (Short)4; def y = (short)1; return x | y")); - assertEquals(5, exec("def x = (Character)4; def y = (char)1; return x | y")); - assertEquals(5, exec("def x = (Integer)4; def y = (int)1; return x | y")); - assertEquals(5L, exec("def x = (Long)4; def y = (long)1; return x | y")); - assertEquals(5L, exec("def x = (Float)4; def y = (float)1; return x | y")); - assertEquals(5L, exec("def x = (Double)4; def y = (double)1; return x | y")); + assertEquals(5, exec("def x = (byte)4; def y = (byte)1; return x | y")); + assertEquals(5, exec("def x = (short)4; def y = (short)1; return x | y")); + assertEquals(5, exec("def x = (char)4; def y = (char)1; return x | y")); + assertEquals(5, exec("def x = (int)4; def y = (int)1; return x | y")); + assertEquals(5L, exec("def x = (long)4; def y = (long)1; return x | y")); + assertEquals(5L, exec("def x = (float)4; def y = (float)1; return x | y")); + assertEquals(5L, exec("def x = (double)4; def y = (double)1; return x | y")); } public void testEq() { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/EqualsTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/EqualsTests.java index 8043d9da915..7e4448495a9 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/EqualsTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/EqualsTests.java @@ -94,17 +94,8 @@ public class EqualsTests extends ScriptTestCase { } public void testEquals() { - assertEquals(true, exec("return new Long(3) == new Long(3);")); - assertEquals(false, exec("return new Long(3) === new Long(3);")); - assertEquals(true, exec("Integer x = new Integer(3); Object y = x; return x == y;")); - assertEquals(true, exec("Integer x = new Integer(3); Object y = x; return x === y;")); - assertEquals(true, exec("Integer x = new Integer(3); Object y = new Integer(3); return x == y;")); - assertEquals(false, exec("Integer x = new Integer(3); Object y = new Integer(3); return x === y;")); - assertEquals(true, exec("Integer x = new Integer(3); int y = 3; return x == y;")); - assertEquals(true, exec("Integer x = new Integer(3); short y = 3; return x == y;")); - assertEquals(true, exec("Integer x = new Integer(3); Short y = (short)3; return x == y;")); - assertEquals(false, exec("Integer x = new Integer(3); int y = 3; return x === y;")); - assertEquals(false, exec("Integer x = new Integer(3); double y = 3; return x === y;")); + assertEquals(true, exec("return 3 == 3;")); + assertEquals(false, exec("int x = 4; int y = 5; x == y")); assertEquals(true, exec("int[] x = new int[1]; Object y = x; return x == y;")); assertEquals(true, exec("int[] x = new int[1]; Object y = x; return x === y;")); assertEquals(false, exec("int[] x = new int[1]; Object y = new int[1]; return x == y;")); @@ -114,14 +105,8 @@ public class EqualsTests extends ScriptTestCase { } public void testNotEquals() { - assertEquals(false, exec("return new Long(3) != new Long(3);")); - assertEquals(true, exec("return new Long(3) !== new Long(3);")); - assertEquals(false, exec("Integer x = new Integer(3); Object y = x; return x != y;")); - assertEquals(false, exec("Integer x = new Integer(3); Object y = x; return x !== y;")); - assertEquals(false, exec("Integer x = new Integer(3); Object y = new Integer(3); return x != y;")); - assertEquals(true, exec("Integer x = new Integer(3); Object y = new Integer(3); return x !== y;")); - assertEquals(true, exec("Integer x = new Integer(3); int y = 3; return x !== y;")); - assertEquals(true, exec("Integer x = new Integer(3); double y = 3; return x !== y;")); + assertEquals(false, exec("return 3 != 3;")); + assertEquals(true, exec("int x = 4; int y = 5; x != y")); assertEquals(false, exec("int[] x = new int[1]; Object y = x; return x != y;")); assertEquals(false, exec("int[] x = new int[1]; Object y = x; return x !== y;")); assertEquals(true, exec("int[] x = new int[1]; Object y = new int[1]; return x != y;")); @@ -131,54 +116,36 @@ public class EqualsTests extends ScriptTestCase { } public void testBranchEquals() { - assertEquals(0, exec("Character a = (char)'a'; Character b = (char)'b'; if (a == b) return 1; else return 0;")); - assertEquals(1, exec("Character a = (char)'a'; Character b = (char)'a'; if (a == b) return 1; else return 0;")); - assertEquals(0, exec("Integer a = new Integer(1); Integer b = 1; if (a === b) return 1; else return 0;")); - assertEquals(0, exec("Character a = (char)'a'; Character b = new Character((char)'a'); if (a === b) return 1; else return 0;")); - assertEquals(1, exec("Character a = (char)'a'; Object b = a; if (a === b) return 1; else return 0;")); - assertEquals(1, exec("Integer a = 1; Number b = a; Number c = a; if (c === b) return 1; else return 0;")); - assertEquals(0, exec("Integer a = 1; Character b = (char)'a'; if (a === (Object)b) return 1; else return 0;")); + assertEquals(0, exec("def a = (char)'a'; def b = (char)'b'; if (a == b) return 1; else return 0;")); + assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a == b) return 1; else return 0;")); + assertEquals(1, exec("def a = 1; def b = 1; if (a === b) return 1; else return 0;")); + assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a === b) return 1; else return 0;")); + assertEquals(1, exec("def a = (char)'a'; Object b = a; if (a === b) return 1; else return 0;")); + assertEquals(1, exec("def a = 1; Number b = a; Number c = a; if (c === b) return 1; else return 0;")); + assertEquals(0, exec("def a = 1; Object b = new HashMap(); if (a === (Object)b) return 1; else return 0;")); } public void testBranchNotEquals() { - assertEquals(1, exec("Character a = (char)'a'; Character b = (char)'b'; if (a != b) return 1; else return 0;")); - assertEquals(0, exec("Character a = (char)'a'; Character b = (char)'a'; if (a != b) return 1; else return 0;")); - assertEquals(1, exec("Integer a = new Integer(1); Integer b = 1; if (a !== b) return 1; else return 0;")); - assertEquals(1, exec("Character a = (char)'a'; Character b = new Character((char)'a'); if (a !== b) return 1; else return 0;")); - assertEquals(0, exec("Character a = (char)'a'; Object b = a; if (a !== b) return 1; else return 0;")); - assertEquals(0, exec("Integer a = 1; Number b = a; Number c = a; if (c !== b) return 1; else return 0;")); - assertEquals(1, exec("Integer a = 1; Character b = (char)'a'; if (a !== (Object)b) return 1; else return 0;")); + assertEquals(1, exec("def a = (char)'a'; def b = (char)'b'; if (a != b) return 1; else return 0;")); + assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a != b) return 1; else return 0;")); + assertEquals(0, exec("def a = 1; def b = 1; if (a !== b) return 1; else return 0;")); + assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a !== b) return 1; else return 0;")); + assertEquals(0, exec("def a = (char)'a'; Object b = a; if (a !== b) return 1; else return 0;")); + assertEquals(0, exec("def a = 1; Number b = a; Number c = a; if (c !== b) return 1; else return 0;")); + assertEquals(1, exec("def a = 1; Object b = new HashMap(); if (a !== (Object)b) return 1; else return 0;")); } public void testRightHandNull() { - assertEquals(false, exec("Character a = (char)'a'; return a == null;")); - assertEquals(false, exec("Character a = (char)'a'; return a === null;")); - assertEquals(true, exec("Character a = (char)'a'; return a != null;")); - assertEquals(true, exec("Character a = (char)'a'; return a !== null;")); - assertEquals(true, exec("Character a = null; return a == null;")); - assertEquals(false, exec("Character a = null; return a != null;")); - assertEquals(false, exec("Character a = (char)'a'; Character b = null; return a == b;")); - assertEquals(true, exec("Character a = null; Character b = null; return a === b;")); - assertEquals(true, exec("Character a = (char)'a'; Character b = null; return a != b;")); - assertEquals(false, exec("Character a = null; Character b = null; return a !== b;")); - assertEquals(false, exec("Integer x = null; double y = 2.0; return x == y;")); - assertEquals(true, exec("Integer x = null; Short y = null; return x == y;")); + assertEquals(false, exec("HashMap a = new HashMap(); return a == null;")); + assertEquals(false, exec("HashMap a = new HashMap(); return a === null;")); + assertEquals(true, exec("HashMap a = new HashMap(); return a != null;")); + assertEquals(true, exec("HashMap a = new HashMap(); return a !== null;")); } public void testLeftHandNull() { - assertEquals(false, exec("Character a = (char)'a'; return null == a;")); - assertEquals(false, exec("Character a = (char)'a'; return null === a;")); - assertEquals(true, exec("Character a = (char)'a'; return null != a;")); - assertEquals(true, exec("Character a = (char)'a'; return null !== a;")); - assertEquals(true, exec("Character a = null; return null == a;")); - assertEquals(false, exec("Character a = null; return null != a;")); - assertEquals(false, exec("Character a = null; Character b = (char)'a'; return a == b;")); - assertEquals(true, exec("Character a = null; Character b = null; return a == b;")); - assertEquals(true, exec("Character a = null; Character b = null; return b === a;")); - assertEquals(true, exec("Character a = null; Character b = (char)'a'; return a != b;")); - assertEquals(false, exec("Character a = null; Character b = null; return b != a;")); - assertEquals(false, exec("Character a = null; Character b = null; return b !== a;")); - assertEquals(false, exec("Integer x = null; double y = 2.0; return y == x;")); - assertEquals(true, exec("Integer x = null; Short y = null; return y == x;")); + assertEquals(false, exec("HashMap a = new HashMap(); return null == a;")); + assertEquals(false, exec("HashMap a = new HashMap(); return null === a;")); + assertEquals(true, exec("HashMap a = new HashMap(); return null != a;")); + assertEquals(true, exec("HashMap a = new HashMap(); return null !== a;")); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java deleted file mode 100644 index 7bec0b110df..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import java.util.Collections; -import java.util.Map; - -/** Tests floating point overflow with numeric overflow disabled */ -public class FloatOverflowDisabledTests extends ScriptTestCase { - - /** wire overflow to false for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "false")); - } - - public void testAssignmentAdditionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x += 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = -3.4028234663852886E38f; x += -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x += 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; x += -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentSubtractionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x -= -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = -3.4028234663852886E38f; x -= 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x -= -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; x -= 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentMultiplicationOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x *= 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 3.4028234663852886E38f; x *= -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x *= 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; x *= -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentDivisionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x /= 1.401298464324817E-45f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 3.4028234663852886E38f; x /= -1.401298464324817E-45f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1.0f; x /= 0.0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x /= 4.9E-324; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; x /= -4.9E-324; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0f; x /= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddition() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x + y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 1.7976931348623157E308; return x + y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAdditionConst() throws Exception { - try { - exec("return 3.4028234663852886E38f + 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 + 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtraction() throws Exception { - try { - exec("float x = -3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x - y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; double y = 1.7976931348623157E308; return x - y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractionConst() throws Exception { - try { - exec("return -3.4028234663852886E38f - 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return -1.7976931348623157E308 - 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplication() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x * y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 1.7976931348623157E308; return x * y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplicationConst() throws Exception { - try { - exec("return 3.4028234663852886E38f * 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 * 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivision() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 1.401298464324817E-45f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1.0f; float y = 0.0f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 4.9E-324; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0; double y = 0.0; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionConst() throws Exception { - try { - exec("return 3.4028234663852886E38f / 1.401298464324817E-45f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0f / 0.0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 / 4.9E-324;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0 / 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionNaN() throws Exception { - // float division, constant division, and assignment - try { - exec("float x = 0f; float y = 0f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 0f / 0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 0f; x /= 0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double division, constant division, and assignment - try { - exec("double x = 0.0; double y = 0.0; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 0.0 / 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 0.0; x /= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderNaN() throws Exception { - // float division, constant division, and assignment - try { - exec("float x = 1f; float y = 0f; return x % y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1f % 0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1f; x %= 0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double division, constant division, and assignment - try { - exec("double x = 1.0; double y = 0.0; return x % y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0 % 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0; x %= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } -} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java similarity index 94% rename from modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java rename to modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java index ccfd2232e88..4b3eb8f0e7f 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java @@ -19,17 +19,8 @@ package org.elasticsearch.painless; -import java.util.Collections; -import java.util.Map; - -/** Tests floating point overflow with numeric overflow enabled */ -public class FloatOverflowEnabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "true")); - } +/** Tests floating point overflow cases */ +public class FloatOverflowTests extends ScriptTestCase { public void testAssignmentAdditionOverflow() { // float diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java deleted file mode 100644 index f4adcfce878..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import java.util.Collections; -import java.util.Map; - -/** Tests integer overflow with numeric overflow disabled */ -public class IntegerOverflowDisabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "false")); - } - - public void testAssignmentAdditionOverflow() { - // byte - try { - exec("byte x = 0; x += 128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x += -129; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 0; x += 32768; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x += -32769; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 0; x += 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 0; x += -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 1; x += 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = -2; x += -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 1; x += 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -2; x += -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentSubtractionOverflow() { - // byte - try { - exec("byte x = 0; x -= -128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x -= 129; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 0; x -= -32768; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x -= 32769; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 0; x -= -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 0; x -= 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 1; x -= -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = -2; x -= 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 1; x -= -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -2; x -= 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentMultiplicationOverflow() { - // byte - try { - exec("byte x = 2; x *= 128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 2; x *= -128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 2; x *= 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 2; x *= -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 2; x *= 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = 2; x *= -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 2; x *= 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 2; x *= -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentDivisionOverflow() { - // byte - try { - exec("byte x = (byte) -128; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = (short) -32768; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // cannot happen for char: unsigned - - // int - try { - exec("int x = -2147483647 - 1; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = -9223372036854775807L - 1L; x /=-1L; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testIncrementOverFlow() throws Exception { - // byte - try { - exec("byte x = 127; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 127; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = (byte) -128; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = (byte) -128; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 32767; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = 32767; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = (short) -32768; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = (short) -32768; x--; return x;"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 65535; ++x; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 65535; x++; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = (char) 0; --x; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = (char) 0; x--; return x;"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 2147483647; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = 2147483647; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = (int) -2147483648L; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = (int) -2147483648L; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 9223372036854775807L; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775807L - 1L; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775807L - 1L; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddition() throws Exception { - try { - exec("int x = 2147483647; int y = 2147483647; return x + y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; long y = 9223372036854775807L; return x + y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testAdditionConst() throws Exception { - try { - exec("return 2147483647 + 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return 9223372036854775807L + 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - - public void testSubtraction() throws Exception { - try { - exec("int x = -10; int y = 2147483647; return x - y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -10L; long y = 9223372036854775807L; return x - y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractionConst() throws Exception { - try { - exec("return -10 - 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return -10L - 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplication() throws Exception { - try { - exec("int x = 2147483647; int y = 2147483647; return x * y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; long y = 9223372036854775807L; return x * y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplicationConst() throws Exception { - try { - exec("return 2147483647 * 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return 9223372036854775807L * 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivision() throws Exception { - try { - exec("int x = -2147483647 - 1; int y = -1; return x / y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775808L; long y = -1L; return x / y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionConst() throws Exception { - try { - exec("return (-2147483648) / -1;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return (-9223372036854775808L) / -1L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testNegationOverflow() throws Exception { - try { - exec("int x = -2147483648; x = -x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775808L; x = -x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testNegationOverflowConst() throws Exception { - try { - exec("int x = -(-2147483648); return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -(-9223372036854775808L); return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } -} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java similarity index 95% rename from modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java rename to modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java index 41b3f857c0a..1165547bf5a 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java @@ -19,17 +19,8 @@ package org.elasticsearch.painless; -import java.util.Collections; -import java.util.Map; - -/** Tests integer overflow with numeric overflow enabled */ -public class IntegerOverflowEnabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "true")); - } +/** Tests integer overflow cases */ +public class IntegerOverflowTests extends ScriptTestCase { public void testAssignmentAdditionOverflow() { // byte diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java index 4b56d9751b6..3fe071c5221 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java @@ -60,6 +60,7 @@ public class NeedsScoreTests extends ESSingleNodeTestCase { ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), lookup, Collections.emptyMap()); assertTrue(ss.needsScores()); + service.close(); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NoSemiColonTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NoSemiColonTests.java index f2e65fc680c..e4af7a2d166 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NoSemiColonTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NoSemiColonTests.java @@ -35,7 +35,7 @@ public class NoSemiColonTests extends ScriptTestCase { assertEquals(2.0, exec("double a = 2; return a")); assertEquals(false, exec("boolean a = false; return a")); assertEquals("string", exec("String a = \"string\"; return a")); - assertEquals(HashMap.class, exec("Map a = new HashMap(); return a").getClass()); + assertEquals(HashMap.class, exec("Map a = new HashMap(); return a").getClass()); assertEquals(byte[].class, exec("byte[] a = new byte[1]; return a").getClass()); assertEquals(short[].class, exec("short[] a = new short[1]; return a").getClass()); @@ -46,7 +46,7 @@ public class NoSemiColonTests extends ScriptTestCase { assertEquals(double[].class, exec("double[] a = new double[1]; return a").getClass()); assertEquals(boolean[].class, exec("boolean[] a = new boolean[1]; return a").getClass()); assertEquals(String[].class, exec("String[] a = new String[1]; return a").getClass()); - assertEquals(Map[].class, exec("Map[] a = new Map[1]; return a").getClass()); + assertEquals(Map[].class, exec("Map[] a = new Map[1]; return a").getClass()); assertEquals(byte[][].class, exec("byte[][] a = new byte[1][2]; return a").getClass()); assertEquals(short[][][].class, exec("short[][][] a = new short[1][2][3]; return a").getClass()); @@ -57,7 +57,7 @@ public class NoSemiColonTests extends ScriptTestCase { assertEquals(double[][][][].class, exec("double[][][][] a = new double[1][2][3][4]; return a").getClass()); assertEquals(boolean[][][][][].class, exec("boolean[][][][][] a = new boolean[1][2][3][4][5]; return a").getClass()); assertEquals(String[][].class, exec("String[][] a = new String[1][2]; return a").getClass()); - assertEquals(Map[][][].class, exec("Map[][][] a = new Map[1][2][3]; return a").getClass()); + assertEquals(Map[][][].class, exec("Map[][][] a = new Map[1][2][3]; return a").getClass()); } public void testExpression() { @@ -73,6 +73,6 @@ public class NoSemiColonTests extends ScriptTestCase { assertEquals(5, exec("int x = 5; return x")); assertEquals(4, exec("int[] x = new int[2]; x[1] = 4; return x[1]")); assertEquals(5, ((short[])exec("short[] s = new short[3]; s[1] = 5; return s"))[1]); - assertEquals(10, ((Map)exec("Map s = new HashMap< String,Object>(); s.put(\"x\", 10); return s")).get("x")); + assertEquals(10, ((Map)exec("Map s = new HashMap(); s.put(\"x\", 10); return s")).get("x")); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 2ccd2f1460a..c3ce127034e 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -48,7 +48,7 @@ public abstract class ScriptTestCase extends ESTestCase { /** Compiles and returns the result of {@code script} with access to {@code vars} */ public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, Boolean.toString(random().nextBoolean()))); + return exec(script, vars, Collections.emptyMap()); } /** Compiles and returns the result of {@code script} with access to {@code vars} and compile-time parameters */ diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/StringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/StringTests.java index e61541bf371..b06199cf903 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/StringTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/StringTests.java @@ -70,13 +70,13 @@ public class StringTests extends ScriptTestCase { public void testAppendMultiple() { assertEquals("cat" + true + "abc" + null, exec("String s = \"cat\"; return s + true + 'abc' + null;")); } - + public void testAppendMany() { for (int i = MAX_INDY_STRING_CONCAT_ARGS - 5; i < MAX_INDY_STRING_CONCAT_ARGS + 5; i++) { doTestAppendMany(i); } } - + private void doTestAppendMany(int count) { StringBuilder script = new StringBuilder("String s = \"cat\"; return s"); StringBuilder result = new StringBuilder("cat"); @@ -90,11 +90,11 @@ public class StringTests extends ScriptTestCase { Debugger.toString(s).contains(String.format(Locale.ROOT, "LDC \"%03d\"", count/2))); assertEquals(result.toString(), exec(s)); } - + public void testNestedConcats() { assertEquals("foo1010foo", exec("String s = 'foo'; String x = '10'; return s + Integer.parseInt(x + x) + s;")); } - + public void testStringAPI() { assertEquals("", exec("return new String();")); assertEquals('x', exec("String s = \"x\"; return s.charAt(0);")); @@ -166,14 +166,14 @@ public class StringTests extends ScriptTestCase { assertEquals("cc", exec("return (String)(char)\"cc\"")); fail(); } catch (final ClassCastException cce) { - assertTrue(cce.getMessage().contains("Cannot cast from [String] to [char].")); + assertTrue(cce.getMessage().contains("Cannot cast [String] with length greater than one to [char].")); } try { assertEquals("cc", exec("return (String)(char)'cc'")); fail(); } catch (final ClassCastException cce) { - assertTrue(cce.getMessage().contains("Cannot cast from [String] to [char].")); + assertTrue(cce.getMessage().contains("Cannot cast [String] with length greater than one to [char].")); } try { @@ -189,41 +189,5 @@ public class StringTests extends ScriptTestCase { } catch (final ClassCastException cce) { assertTrue(cce.getMessage().contains("Cannot cast [String] with length greater than one to [char].")); } - - assertEquals('c', exec("return (Character)\"c\"")); - assertEquals('c', exec("return (Character)'c'")); - assertEquals("c", exec("return (String)(Character)\"c\"")); - assertEquals("c", exec("return (String)(Character)'c'")); - - assertEquals('c', exec("String s = \"c\"; (Character)s")); - assertEquals('c', exec("String s = 'c'; (Character)s")); - - try { - assertEquals("cc", exec("return (String)(Character)\"cc\"")); - fail(); - } catch (final ClassCastException ise) { - assertTrue(ise.getMessage().contains("Cannot cast [String] with length greater than one to [Character].")); - } - - try { - assertEquals("cc", exec("return (String)(Character)'cc'")); - fail(); - } catch (final ClassCastException ise) { - assertTrue(ise.getMessage().contains("Cannot cast [String] with length greater than one to [Character].")); - } - - try { - assertEquals('c', exec("String s = \"cc\"; (Character)s")); - fail(); - } catch (final ClassCastException cce) { - assertTrue(cce.getMessage().contains("Cannot cast [String] with length greater than one to [Character].")); - } - - try { - assertEquals('c', exec("String s = 'cc'; (Character)s")); - fail(); - } catch (final ClassCastException cce) { - assertTrue(cce.getMessage().contains("Cannot cast [String] with length greater than one to [Character].")); - } } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java deleted file mode 100644 index ba476fac7f2..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import org.elasticsearch.test.ESTestCase; - -/** - * Tests utility methods (typically built-ins) - */ -public class UtilityTests extends ESTestCase { - - public void testDivideWithoutOverflowInt() { - assertEquals(5 / 2, Utility.divideWithoutOverflow(5, 2)); - - try { - Utility.divideWithoutOverflow(Integer.MIN_VALUE, -1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5, 0); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowLong() { - assertEquals(5L / 2L, Utility.divideWithoutOverflow(5L, 2L)); - - try { - Utility.divideWithoutOverflow(Long.MIN_VALUE, -1L); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5L, 0L); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToByteExact() { - for (int b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) { - assertEquals((byte)b, Utility.toByteExact(b)); - } - - try { - Utility.toByteExact(Byte.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toByteExact(Byte.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToShortExact() { - for (int s = Short.MIN_VALUE; s < Short.MAX_VALUE; s++) { - assertEquals((short)s, Utility.toShortExact(s)); - } - - try { - Utility.toShortExact(Short.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toShortExact(Short.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToCharExact() { - for (int c = Character.MIN_VALUE; c < Character.MAX_VALUE; c++) { - assertEquals((char)c, Utility.toCharExact(c)); - } - - try { - Utility.toCharExact(Character.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toCharExact(Character.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddWithoutOverflowFloat() { - assertEquals(10F, Utility.addWithoutOverflow(5F, 5F), 0F); - assertTrue(Float.isNaN(Utility.addWithoutOverflow(5F, Float.NaN))); - assertTrue(Float.isNaN(Utility.addWithoutOverflow(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY))); - - try { - Utility.addWithoutOverflow(Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.addWithoutOverflow(-Float.MAX_VALUE, -Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddWithoutOverflowDouble() { - assertEquals(10D, Utility.addWithoutOverflow(5D, 5D), 0D); - assertTrue(Double.isNaN(Utility.addWithoutOverflow(5D, Double.NaN))); - assertTrue(Double.isNaN(Utility.addWithoutOverflow(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY))); - - try { - Utility.addWithoutOverflow(Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.addWithoutOverflow(-Double.MAX_VALUE, -Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractWithoutOverflowFloat() { - assertEquals(5F, Utility.subtractWithoutOverflow(10F, 5F), 0F); - assertTrue(Float.isNaN(Utility.subtractWithoutOverflow(5F, Float.NaN))); - assertTrue(Float.isNaN(Utility.subtractWithoutOverflow(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY))); - - try { - Utility.subtractWithoutOverflow(Float.MAX_VALUE, -Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.subtractWithoutOverflow(-Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractWithoutOverflowDouble() { - assertEquals(5D, Utility.subtractWithoutOverflow(10D, 5D), 0D); - assertTrue(Double.isNaN(Utility.subtractWithoutOverflow(5D, Double.NaN))); - assertTrue(Double.isNaN(Utility.subtractWithoutOverflow(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - - try { - Utility.subtractWithoutOverflow(Double.MAX_VALUE, -Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.subtractWithoutOverflow(-Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplyWithoutOverflowFloat() { - assertEquals(25F, Utility.multiplyWithoutOverflow(5F, 5F), 0F); - assertTrue(Float.isNaN(Utility.multiplyWithoutOverflow(5F, Float.NaN))); - assertEquals(Float.POSITIVE_INFINITY, Utility.multiplyWithoutOverflow(5F, Float.POSITIVE_INFINITY), 0F); - - try { - Utility.multiplyWithoutOverflow(Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplyWithoutOverflowDouble() { - assertEquals(25D, Utility.multiplyWithoutOverflow(5D, 5D), 0D); - assertTrue(Double.isNaN(Utility.multiplyWithoutOverflow(5D, Double.NaN))); - assertEquals(Double.POSITIVE_INFINITY, Utility.multiplyWithoutOverflow(5D, Double.POSITIVE_INFINITY), 0D); - - try { - Utility.multiplyWithoutOverflow(Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowFloat() { - assertEquals(5F, Utility.divideWithoutOverflow(25F, 5F), 0F); - assertTrue(Float.isNaN(Utility.divideWithoutOverflow(5F, Float.NaN))); - assertEquals(Float.POSITIVE_INFINITY, Utility.divideWithoutOverflow(Float.POSITIVE_INFINITY, 5F), 0F); - - try { - Utility.divideWithoutOverflow(Float.MAX_VALUE, Float.MIN_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(0F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowDouble() { - assertEquals(5D, Utility.divideWithoutOverflow(25D, 5D), 0D); - assertTrue(Double.isNaN(Utility.divideWithoutOverflow(5D, Double.NaN))); - assertEquals(Double.POSITIVE_INFINITY, Utility.divideWithoutOverflow(Double.POSITIVE_INFINITY, 5D), 0D); - - try { - Utility.divideWithoutOverflow(Double.MAX_VALUE, Double.MIN_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(0D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderWithoutOverflowFloat() { - assertEquals(1F, Utility.remainderWithoutOverflow(25F, 4F), 0F); - - try { - Utility.remainderWithoutOverflow(5F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderWithoutOverflowDouble() { - assertEquals(1D, Utility.remainderWithoutOverflow(25D, 4D), 0D); - - try { - Utility.remainderWithoutOverflow(5D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } -}