Browse Source

Merge pull request #18463 from rmuir/whitelist_cleanup

painless: steps at definition cleanup
Robert Muir 9 years ago
parent
commit
a2ff002e2b
80 changed files with 2317 additions and 4782 deletions
  1. 3 3
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java
  2. 734 189
      modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java
  3. 3 3
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java
  4. 0 31
      modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java
  5. 15 156
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java
  6. 3 3
      modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java
  7. 183 1256
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java
  8. 118 281
      modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java
  9. 6 0
      modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java
  10. 2 10
      modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java
  11. 0 785
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java
  12. 12 14
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java
  13. 5 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java
  14. 37 70
      modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java
  15. 9 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java
  16. 13 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java
  17. 6 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ALink.java
  18. 3 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AStatement.java
  19. 106 131
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java
  20. 18 19
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java
  21. 4 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java
  22. 4 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java
  23. 44 51
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java
  24. 88 84
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java
  25. 16 16
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java
  26. 12 13
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java
  27. 5 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java
  28. 9 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java
  29. 4 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java
  30. 10 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java
  31. 33 47
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java
  32. 6 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LArrayLength.java
  33. 13 14
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LBrace.java
  34. 11 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCall.java
  35. 7 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCast.java
  36. 11 12
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefArray.java
  37. 11 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefCall.java
  38. 8 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java
  39. 11 20
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LField.java
  40. 9 10
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LListShortcut.java
  41. 8 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LMapShortcut.java
  42. 12 13
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewArray.java
  43. 11 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LNewObj.java
  44. 5 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LShortcut.java
  45. 6 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LString.java
  46. 6 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LVariable.java
  47. 7 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java
  48. 3 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java
  49. 3 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java
  50. 5 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java
  51. 6 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java
  52. 12 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java
  53. 8 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java
  54. 19 18
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java
  55. 11 13
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java
  56. 8 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java
  57. 5 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java
  58. 7 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java
  59. 5 7
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STrap.java
  60. 7 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java
  61. 12 11
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java
  62. 1 0
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java
  63. 375 0
      modules/lang-painless/src/main/resources/org/elasticsearch/painless/definition.txt
  64. 9 9
      modules/lang-painless/src/test/java/org/elasticsearch/painless/ArrayTests.java
  65. 21 17
      modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicAPITests.java
  66. 3 3
      modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java
  67. 4 4
      modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java
  68. 24 24
      modules/lang-painless/src/test/java/org/elasticsearch/painless/CompoundAssignmentTests.java
  69. 1 3
      modules/lang-painless/src/test/java/org/elasticsearch/painless/ConditionalTests.java
  70. 79 79
      modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOperationTests.java
  71. 26 59
      modules/lang-painless/src/test/java/org/elasticsearch/painless/EqualsTests.java
  72. 0 293
      modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java
  73. 2 11
      modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java
  74. 0 444
      modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java
  75. 2 11
      modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java
  76. 1 0
      modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java
  77. 4 4
      modules/lang-painless/src/test/java/org/elasticsearch/painless/NoSemiColonTests.java
  78. 1 1
      modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java
  79. 6 42
      modules/lang-painless/src/test/java/org/elasticsearch/painless/StringTests.java
  80. 0 250
      modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java

+ 3 - 3
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;
     }

File diff suppressed because it is too large
+ 734 - 189
modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerCaster.java


+ 3 - 3
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);
     }
 
     /**

+ 0 - 31
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.
-     * <p>
-     * 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

+ 15 - 156
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 {
      * <p>
      * @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 {
      * <p>
      * @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();
-        }
-    }
 }

+ 3 - 3
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:

File diff suppressed because it is too large
+ 183 - 1256
modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java


+ 118 - 281
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 == 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);
             }
+        }
+    }
 
-            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);
-                }
+    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,229 +253,49 @@ 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;
-                    }
 
-                    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.");
-                    }
+        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;
+        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.");
-                }
-            }
-        }
-    }
-
-    /**
-     * 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;
+            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.");
             }
-        } else {
-            return false;
         }
-
-        return true;
     }
 
     public void writeDup(final int size, final int xsize) {

+ 6 - 0
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";

+ 2 - 10
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<String, String> 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.
     }
 }

+ 0 - 785
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);

+ 12 - 14
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<Integer> scopes = new ArrayDeque<>();
     private final Deque<Variable> 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<String,Def>, 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.

+ 5 - 7
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(" @ <inline script>");
         } 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();
     }
 

+ 37 - 70
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());

+ 9 - 6
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<ANode> {
 
-    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<ANode> {
 
         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<ANode> {
 
         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<ANode> {
 
         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

+ 13 - 9
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."));

+ 6 - 8
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;

+ 3 - 5
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);
 }

+ 106 - 131
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);

+ 18 - 19
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);

+ 4 - 5
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."));
     }
 }

+ 4 - 6
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);
     }

+ 44 - 51
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<ALink> links,
-                  final boolean pre, final boolean post, final Operation operation, final AExpression expression) {
+    public EChain(int line, String location, List<ALink> 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);
             }
         }
 

+ 88 - 84
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);

+ 16 - 16
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);
     }
 }

+ 12 - 13
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) {

+ 5 - 6
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."));
     }
 }

+ 9 - 9
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);
     }
 }

+ 4 - 5
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);
     }
 }

+ 10 - 11
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."));
     }
 }

+ 33 - 47
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."));

+ 6 - 7
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."));
     }
 }

+ 13 - 14
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);
     }
 

+ 11 - 11
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<AExpression> arguments) {
+    public LCall(int line, String location, String name, List<AExpression> 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."));
     }
 }

+ 7 - 8
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."));
     }
 }

+ 11 - 12
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);
     }

+ 11 - 11
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<AExpression> arguments;
 
-    LDefCall(final int line, final String location, final String name, final List<AExpression> arguments) {
+    LDefCall(int line, String location, String name, List<AExpression> 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."));
     }
 }

+ 8 - 9
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);
     }
 }

+ 11 - 20
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 {

+ 9 - 10
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 {

+ 8 - 9
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 {

+ 12 - 13
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<AExpression> arguments;
 
-    public LNewArray(final int line, final String location, final String type, final List<AExpression> arguments) {
+    public LNewArray(int line, String location, String type, List<AExpression> 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."));
     }
 }

+ 11 - 11
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<AExpression> arguments) {
+    public LNewObj(int line, String location, String type, List<AExpression> 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."));
     }
 }

+ 5 - 6
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 {

+ 6 - 7
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."));
     }
 }

+ 6 - 7
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);
     }
 }

+ 7 - 9
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<AStatement> statements;
 
-    public SBlock(final int line, final String location, final List<AStatement> statements) {
+    public SBlock(int line, String location, List<AStatement> 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);
         }
     }
 }

+ 3 - 5
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);
     }

+ 3 - 5
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);
     }

+ 5 - 7
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<SDeclaration> declarations;
 
-    public SDeclBlock(final int line, final String location, final List<SDeclaration> declarations) {
+    public SDeclBlock(int line, String location, List<SDeclaration> 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);
         }
     }
 }

+ 6 - 8
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) {

+ 12 - 11
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));
 

+ 8 - 8
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();

+ 19 - 18
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) {

+ 11 - 13
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);

+ 8 - 8
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();
     }
 }

+ 5 - 7
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<AStatement> statements;
 
-    public SSource(final int line, final String location, final List<AStatement> statements) {
+    public SSource(int line, String location, List<AStatement> 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) {

+ 7 - 8
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();
     }
 }

+ 5 - 7
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());

+ 7 - 9
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<STrap> traps;
 
-    public STry(final int line, final String location, final AStatement block, final List<STrap> traps) {
+    public STry(int line, String location, AStatement block, List<STrap> 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) {

+ 12 - 11
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);
         }

+ 1 - 0
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/package-info.java

@@ -22,6 +22,7 @@
  * <p>
  * 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.

+ 375 - 0
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 <init>()
+  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 <init>()
+}
+
+class Set -> java.util.Set extends Collection,Object {
+}
+
+class HashSet -> java.util.HashSet extends Set,Collection,Object {
+  HashSet <init>()
+}
+
+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 <init>()
+}
+
+class Exception -> java.lang.Exception extends Object {
+  String getMessage()
+}
+
+class ArithmeticException -> java.lang.ArithmeticException extends Exception,Object {
+  ArithmeticException <init>()
+}
+
+class IllegalArgumentException -> java.lang.IllegalArgumentException extends Exception,Object {
+  IllegalArgumentException <init>()
+}
+
+class IllegalStateException -> java.lang.IllegalStateException extends Exception,Object {
+  IllegalStateException <init>()
+}
+
+class NumberFormatException -> java.lang.NumberFormatException extends Exception,Object {
+  NumberFormatException <init>()
+}
+
+# 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 <init>()
+  FeatureTest <init>(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 {
+}

+ 9 - 9
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;"));
     }
-    
+
 }

+ 21 - 17
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<Object> x = new ArrayList(); x.add(2); x.add(3); x.add(-2); Iterator<Object> y = x.iterator(); " +
-            "int total = 0; while (y.hasNext()) total += (int)y.next(); return total;"));
-        assertEquals("abc", exec("List<String> x = new ArrayList(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " +
-            "Iterator<String> 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<Object> x = new HashSet(); x.add(2); x.add(3); x.add(-2); Iterator<Object> y = x.iterator(); " +
-            "int total = 0; while (y.hasNext()) total += (int)y.next(); return total;"));
-        assertEquals("abc", exec("Set<String> x = new HashSet(); x.add(\"a\"); x.add(\"b\"); x.add(\"c\"); " +
-            "Iterator<String> 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<String> x = new ArrayList<String>(); x.add('Hallo'); return x.length"));
-        assertEquals(1, exec("List<Object> x = new ArrayList<Object>(); 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;");
+    }
 }

+ 3 - 3
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() {

+ 4 - 4
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<String,Object> a = new HashMap<String,Object>(); 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<String,Object>[] a = new Map<String,Object>[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<String,Object>[][][] a = new Map<String,Object>[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<String, Object> 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"));
     }
 }

+ 24 - 24
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;"));

+ 1 - 3
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() {

+ 79 - 79
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() {

+ 26 - 59
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;"));
     }
 }

+ 0 - 293
modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java

@@ -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<String, Object> 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) {}
-    }
-}

+ 2 - 11
modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java → 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<String, Object> 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

+ 0 - 444
modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java

@@ -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<String, Object> 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) {}
-    }
-}

+ 2 - 11
modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java → 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<String, Object> vars) {
-        return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "true"));
-    }
+/** Tests integer overflow cases */
+public class IntegerOverflowTests extends ScriptTestCase {
 
     public void testAssignmentAdditionOverflow() {
         // byte

+ 1 - 0
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.<String, Object>emptyMap());
         assertTrue(ss.needsScores());
+        service.close();
     }
 
 }

+ 4 - 4
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<String, Object> a = new HashMap<String, Object>(); 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<String,Object>[] a = new Map<String,Object>[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<String,Object>[][][] a = new Map<String,Object>[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<String,Object> 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"));
     }
 }

+ 1 - 1
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<String, Object> 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 */

+ 6 - 42
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]."));
-        }
     }
 }

+ 0 - 250
modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java

@@ -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) {}
-    }
-}

Some files were not shown because too many files changed in this diff