|
@@ -21,8 +21,8 @@ package org.elasticsearch.painless;
|
|
|
|
|
|
import java.lang.invoke.MethodHandle;
|
|
import java.lang.invoke.MethodHandle;
|
|
import java.lang.invoke.MethodHandles;
|
|
import java.lang.invoke.MethodHandles;
|
|
-import java.lang.invoke.MethodType;
|
|
|
|
import java.lang.invoke.MethodHandles.Lookup;
|
|
import java.lang.invoke.MethodHandles.Lookup;
|
|
|
|
+import java.lang.invoke.MethodType;
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
@@ -31,38 +31,38 @@ import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
import java.util.stream.Stream;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Dynamic operators for painless.
|
|
|
|
|
|
+ * Dynamic operators for painless.
|
|
* <p>
|
|
* <p>
|
|
* Each operator must "support" the following types:
|
|
* Each operator must "support" the following types:
|
|
- * {@code int,long,float,double,boolean,Object}. Operators can throw exceptions if
|
|
|
|
|
|
+ * {@code int,long,float,double,boolean,Object}. Operators can throw exceptions if
|
|
* the type is illegal. The {@code Object} type must be a "generic" handler that
|
|
* the type is illegal. The {@code Object} type must be a "generic" handler that
|
|
* handles all legal types: it must be convertible to every possible legal signature.
|
|
* handles all legal types: it must be convertible to every possible legal signature.
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
@SuppressWarnings("unused")
|
|
public class DefMath {
|
|
public class DefMath {
|
|
-
|
|
|
|
|
|
+
|
|
// Unary not: only applicable to integral types
|
|
// Unary not: only applicable to integral types
|
|
|
|
|
|
private static int not(int v) {
|
|
private static int not(int v) {
|
|
return ~v;
|
|
return ~v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long not(long v) {
|
|
private static long not(long v) {
|
|
return ~v;
|
|
return ~v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float not(float v) {
|
|
private static float not(float v) {
|
|
throw new ClassCastException("Cannot apply not [~] to type [float]");
|
|
throw new ClassCastException("Cannot apply not [~] to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double not(double v) {
|
|
private static double not(double v) {
|
|
throw new ClassCastException("Cannot apply not [~] to type [double]");
|
|
throw new ClassCastException("Cannot apply not [~] to type [double]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean not(boolean v) {
|
|
private static boolean not(boolean v) {
|
|
throw new ClassCastException("Cannot apply not [~] to type [boolean]");
|
|
throw new ClassCastException("Cannot apply not [~] to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object not(Object unary) {
|
|
private static Object not(Object unary) {
|
|
if (unary instanceof Long) {
|
|
if (unary instanceof Long) {
|
|
return ~(Long)unary;
|
|
return ~(Long)unary;
|
|
@@ -79,29 +79,29 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [~] operation to type " +
|
|
throw new ClassCastException("Cannot apply [~] operation to type " +
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// unary negation and plus: applicable to all numeric types
|
|
// unary negation and plus: applicable to all numeric types
|
|
|
|
|
|
private static int neg(int v) {
|
|
private static int neg(int v) {
|
|
return -v;
|
|
return -v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long neg(long v) {
|
|
private static long neg(long v) {
|
|
return -v;
|
|
return -v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float neg(float v) {
|
|
private static float neg(float v) {
|
|
return -v;
|
|
return -v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double neg(double v) {
|
|
private static double neg(double v) {
|
|
return -v;
|
|
return -v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean neg(boolean v) {
|
|
private static boolean neg(boolean v) {
|
|
throw new ClassCastException("Cannot apply [-] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [-] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object neg(final Object unary) {
|
|
private static Object neg(final Object unary) {
|
|
if (unary instanceof Double) {
|
|
if (unary instanceof Double) {
|
|
return -(double)unary;
|
|
return -(double)unary;
|
|
@@ -122,27 +122,27 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [-] operation to type " +
|
|
throw new ClassCastException("Cannot apply [-] operation to type " +
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int plus(int v) {
|
|
private static int plus(int v) {
|
|
return +v;
|
|
return +v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long plus(long v) {
|
|
private static long plus(long v) {
|
|
return +v;
|
|
return +v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float plus(float v) {
|
|
private static float plus(float v) {
|
|
return +v;
|
|
return +v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double plus(double v) {
|
|
private static double plus(double v) {
|
|
return +v;
|
|
return +v;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean plus(boolean v) {
|
|
private static boolean plus(boolean v) {
|
|
throw new ClassCastException("Cannot apply [+] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [+] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object plus(final Object unary) {
|
|
private static Object plus(final Object unary) {
|
|
if (unary instanceof Double) {
|
|
if (unary instanceof Double) {
|
|
return +(double)unary;
|
|
return +(double)unary;
|
|
@@ -163,29 +163,29 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [+] operation to type " +
|
|
throw new ClassCastException("Cannot apply [+] operation to type " +
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
"[" + unary.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// multiplication/division/remainder/subtraction: applicable to all integer types
|
|
// multiplication/division/remainder/subtraction: applicable to all integer types
|
|
-
|
|
|
|
|
|
+
|
|
private static int mul(int a, int b) {
|
|
private static int mul(int a, int b) {
|
|
return a * b;
|
|
return a * b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long mul(long a, long b) {
|
|
private static long mul(long a, long b) {
|
|
return a * b;
|
|
return a * b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float mul(float a, float b) {
|
|
private static float mul(float a, float b) {
|
|
return a * b;
|
|
return a * b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double mul(double a, double b) {
|
|
private static double mul(double a, double b) {
|
|
return a * b;
|
|
return a * b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean mul(boolean a, boolean b) {
|
|
private static boolean mul(boolean a, boolean b) {
|
|
throw new ClassCastException("Cannot apply [*] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [*] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object mul(Object left, Object right) {
|
|
private static Object mul(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -228,27 +228,27 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [*] operation to types " +
|
|
throw new ClassCastException("Cannot apply [*] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int div(int a, int b) {
|
|
private static int div(int a, int b) {
|
|
return a / b;
|
|
return a / b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long div(long a, long b) {
|
|
private static long div(long a, long b) {
|
|
return a / b;
|
|
return a / b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float div(float a, float b) {
|
|
private static float div(float a, float b) {
|
|
return a / b;
|
|
return a / b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double div(double a, double b) {
|
|
private static double div(double a, double b) {
|
|
return a / b;
|
|
return a / b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean div(boolean a, boolean b) {
|
|
private static boolean div(boolean a, boolean b) {
|
|
throw new ClassCastException("Cannot apply [/] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [/] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object div(Object left, Object right) {
|
|
private static Object div(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -291,27 +291,27 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [/] operation to types " +
|
|
throw new ClassCastException("Cannot apply [/] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int rem(int a, int b) {
|
|
private static int rem(int a, int b) {
|
|
return a % b;
|
|
return a % b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long rem(long a, long b) {
|
|
private static long rem(long a, long b) {
|
|
return a % b;
|
|
return a % b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float rem(float a, float b) {
|
|
private static float rem(float a, float b) {
|
|
return a % b;
|
|
return a % b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double rem(double a, double b) {
|
|
private static double rem(double a, double b) {
|
|
return a % b;
|
|
return a % b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean rem(boolean a, boolean b) {
|
|
private static boolean rem(boolean a, boolean b) {
|
|
throw new ClassCastException("Cannot apply [%] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [%] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object rem(Object left, Object right) {
|
|
private static Object rem(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -354,30 +354,30 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [%] operation to types " +
|
|
throw new ClassCastException("Cannot apply [%] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// addition: applicable to all numeric types.
|
|
// addition: applicable to all numeric types.
|
|
// additionally, if either type is a string, the other type can be any arbitrary type (including null)
|
|
// additionally, if either type is a string, the other type can be any arbitrary type (including null)
|
|
-
|
|
|
|
|
|
+
|
|
private static int add(int a, int b) {
|
|
private static int add(int a, int b) {
|
|
return a + b;
|
|
return a + b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long add(long a, long b) {
|
|
private static long add(long a, long b) {
|
|
return a + b;
|
|
return a + b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float add(float a, float b) {
|
|
private static float add(float a, float b) {
|
|
return a + b;
|
|
return a + b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double add(double a, double b) {
|
|
private static double add(double a, double b) {
|
|
return a + b;
|
|
return a + b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean add(boolean a, boolean b) {
|
|
private static boolean add(boolean a, boolean b) {
|
|
throw new ClassCastException("Cannot apply [+] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [+] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object add(Object left, Object right) {
|
|
private static Object add(Object left, Object right) {
|
|
if (left instanceof String) {
|
|
if (left instanceof String) {
|
|
return (String) left + right;
|
|
return (String) left + right;
|
|
@@ -424,27 +424,27 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [+] operation to types " +
|
|
throw new ClassCastException("Cannot apply [+] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int sub(int a, int b) {
|
|
private static int sub(int a, int b) {
|
|
return a - b;
|
|
return a - b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long sub(long a, long b) {
|
|
private static long sub(long a, long b) {
|
|
return a - b;
|
|
return a - b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float sub(float a, float b) {
|
|
private static float sub(float a, float b) {
|
|
return a - b;
|
|
return a - b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double sub(double a, double b) {
|
|
private static double sub(double a, double b) {
|
|
return a - b;
|
|
return a - b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean sub(boolean a, boolean b) {
|
|
private static boolean sub(boolean a, boolean b) {
|
|
throw new ClassCastException("Cannot apply [-] operation to type [boolean]");
|
|
throw new ClassCastException("Cannot apply [-] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object sub(Object left, Object right) {
|
|
private static Object sub(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -487,29 +487,29 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [-] operation to types " +
|
|
throw new ClassCastException("Cannot apply [-] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// eq: applicable to any arbitrary type, including nulls for both arguments!!!
|
|
// eq: applicable to any arbitrary type, including nulls for both arguments!!!
|
|
|
|
|
|
private static boolean eq(int a, int b) {
|
|
private static boolean eq(int a, int b) {
|
|
return a == b;
|
|
return a == b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean eq(long a, long b) {
|
|
private static boolean eq(long a, long b) {
|
|
return a == b;
|
|
return a == b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean eq(float a, float b) {
|
|
private static boolean eq(float a, float b) {
|
|
return a == b;
|
|
return a == b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean eq(double a, double b) {
|
|
private static boolean eq(double a, double b) {
|
|
return a == b;
|
|
return a == b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean eq(boolean a, boolean b) {
|
|
private static boolean eq(boolean a, boolean b) {
|
|
return a == b;
|
|
return a == b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean eq(Object left, Object right) {
|
|
private static boolean eq(Object left, Object right) {
|
|
if (left != null && right != null) {
|
|
if (left != null && right != null) {
|
|
if (left instanceof Double) {
|
|
if (left instanceof Double) {
|
|
@@ -565,29 +565,29 @@ public class DefMath {
|
|
|
|
|
|
return left == null && right == null;
|
|
return left == null && right == null;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// comparison operators: applicable for any numeric type
|
|
// comparison operators: applicable for any numeric type
|
|
|
|
|
|
private static boolean lt(int a, int b) {
|
|
private static boolean lt(int a, int b) {
|
|
return a < b;
|
|
return a < b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lt(long a, long b) {
|
|
private static boolean lt(long a, long b) {
|
|
return a < b;
|
|
return a < b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lt(float a, float b) {
|
|
private static boolean lt(float a, float b) {
|
|
return a < b;
|
|
return a < b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lt(double a, double b) {
|
|
private static boolean lt(double a, double b) {
|
|
return a < b;
|
|
return a < b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lt(boolean a, boolean b) {
|
|
private static boolean lt(boolean a, boolean b) {
|
|
- throw new ClassCastException("Cannot apply [<] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [<] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lt(Object left, Object right) {
|
|
private static boolean lt(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -634,23 +634,23 @@ public class DefMath {
|
|
private static boolean lte(int a, int b) {
|
|
private static boolean lte(int a, int b) {
|
|
return a <= b;
|
|
return a <= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lte(long a, long b) {
|
|
private static boolean lte(long a, long b) {
|
|
return a <= b;
|
|
return a <= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lte(float a, float b) {
|
|
private static boolean lte(float a, float b) {
|
|
return a <= b;
|
|
return a <= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lte(double a, double b) {
|
|
private static boolean lte(double a, double b) {
|
|
return a <= b;
|
|
return a <= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lte(boolean a, boolean b) {
|
|
private static boolean lte(boolean a, boolean b) {
|
|
- throw new ClassCastException("Cannot apply [<=] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [<=] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lte(Object left, Object right) {
|
|
private static boolean lte(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -697,23 +697,23 @@ public class DefMath {
|
|
private static boolean gt(int a, int b) {
|
|
private static boolean gt(int a, int b) {
|
|
return a > b;
|
|
return a > b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gt(long a, long b) {
|
|
private static boolean gt(long a, long b) {
|
|
return a > b;
|
|
return a > b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gt(float a, float b) {
|
|
private static boolean gt(float a, float b) {
|
|
return a > b;
|
|
return a > b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gt(double a, double b) {
|
|
private static boolean gt(double a, double b) {
|
|
return a > b;
|
|
return a > b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gt(boolean a, boolean b) {
|
|
private static boolean gt(boolean a, boolean b) {
|
|
- throw new ClassCastException("Cannot apply [>] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gt(Object left, Object right) {
|
|
private static boolean gt(Object left, Object right) {
|
|
if (left instanceof Number) {
|
|
if (left instanceof Number) {
|
|
if (right instanceof Number) {
|
|
if (right instanceof Number) {
|
|
@@ -756,25 +756,25 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [>] operation to types " +
|
|
throw new ClassCastException("Cannot apply [>] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gte(int a, int b) {
|
|
private static boolean gte(int a, int b) {
|
|
return a >= b;
|
|
return a >= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gte(long a, long b) {
|
|
private static boolean gte(long a, long b) {
|
|
return a >= b;
|
|
return a >= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gte(float a, float b) {
|
|
private static boolean gte(float a, float b) {
|
|
return a >= b;
|
|
return a >= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gte(double a, double b) {
|
|
private static boolean gte(double a, double b) {
|
|
return a >= b;
|
|
return a >= b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean gte(boolean a, boolean b) {
|
|
private static boolean gte(boolean a, boolean b) {
|
|
- throw new ClassCastException("Cannot apply [>=] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>=] operation to type [boolean]");
|
|
}
|
|
}
|
|
|
|
|
|
private static boolean gte(Object left, Object right) {
|
|
private static boolean gte(Object left, Object right) {
|
|
@@ -819,10 +819,10 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot apply [>] operation to types " +
|
|
throw new ClassCastException("Cannot apply [>] operation to types " +
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
"[" + left.getClass().getCanonicalName() + "] and [" + right.getClass().getCanonicalName() + "].");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// helper methods to convert an integral according to numeric promotion
|
|
// helper methods to convert an integral according to numeric promotion
|
|
// this is used by the generic code for bitwise and shift operators
|
|
// this is used by the generic code for bitwise and shift operators
|
|
-
|
|
|
|
|
|
+
|
|
private static long longIntegralValue(Object o) {
|
|
private static long longIntegralValue(Object o) {
|
|
if (o instanceof Long) {
|
|
if (o instanceof Long) {
|
|
return (long)o;
|
|
return (long)o;
|
|
@@ -834,7 +834,7 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
|
|
throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int intIntegralValue(Object o) {
|
|
private static int intIntegralValue(Object o) {
|
|
if (o instanceof Integer || o instanceof Short || o instanceof Byte) {
|
|
if (o instanceof Integer || o instanceof Short || o instanceof Byte) {
|
|
return ((Number)o).intValue();
|
|
return ((Number)o).intValue();
|
|
@@ -844,29 +844,29 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
|
|
throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// bitwise operators: valid only for integral types
|
|
// bitwise operators: valid only for integral types
|
|
|
|
|
|
private static int and(int a, int b) {
|
|
private static int and(int a, int b) {
|
|
return a & b;
|
|
return a & b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long and(long a, long b) {
|
|
private static long and(long a, long b) {
|
|
return a & b;
|
|
return a & b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float and(float a, float b) {
|
|
private static float and(float a, float b) {
|
|
- throw new ClassCastException("Cannot apply [&] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [&] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double and(double a, double b) {
|
|
private static double and(double a, double b) {
|
|
- throw new ClassCastException("Cannot apply [&] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [&] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean and(boolean a, boolean b) {
|
|
private static boolean and(boolean a, boolean b) {
|
|
return a & b;
|
|
return a & b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object and(Object left, Object right) {
|
|
private static Object and(Object left, Object right) {
|
|
if (left instanceof Boolean && right instanceof Boolean) {
|
|
if (left instanceof Boolean && right instanceof Boolean) {
|
|
return (boolean)left & (boolean)right;
|
|
return (boolean)left & (boolean)right;
|
|
@@ -876,23 +876,23 @@ public class DefMath {
|
|
return intIntegralValue(left) & intIntegralValue(right);
|
|
return intIntegralValue(left) & intIntegralValue(right);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int xor(int a, int b) {
|
|
private static int xor(int a, int b) {
|
|
return a ^ b;
|
|
return a ^ b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long xor(long a, long b) {
|
|
private static long xor(long a, long b) {
|
|
return a ^ b;
|
|
return a ^ b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float xor(float a, float b) {
|
|
private static float xor(float a, float b) {
|
|
- throw new ClassCastException("Cannot apply [^] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [^] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double xor(double a, double b) {
|
|
private static double xor(double a, double b) {
|
|
- throw new ClassCastException("Cannot apply [^] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [^] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean xor(boolean a, boolean b) {
|
|
private static boolean xor(boolean a, boolean b) {
|
|
return a ^ b;
|
|
return a ^ b;
|
|
}
|
|
}
|
|
@@ -910,23 +910,23 @@ public class DefMath {
|
|
private static int or(int a, int b) {
|
|
private static int or(int a, int b) {
|
|
return a | b;
|
|
return a | b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long or(long a, long b) {
|
|
private static long or(long a, long b) {
|
|
return a | b;
|
|
return a | b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float or(float a, float b) {
|
|
private static float or(float a, float b) {
|
|
- throw new ClassCastException("Cannot apply [|] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [|] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double or(double a, double b) {
|
|
private static double or(double a, double b) {
|
|
- throw new ClassCastException("Cannot apply [|] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [|] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean or(boolean a, boolean b) {
|
|
private static boolean or(boolean a, boolean b) {
|
|
return a | b;
|
|
return a | b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static Object or(Object left, Object right) {
|
|
private static Object or(Object left, Object right) {
|
|
if (left instanceof Boolean && right instanceof Boolean) {
|
|
if (left instanceof Boolean && right instanceof Boolean) {
|
|
return (boolean)left | (boolean)right;
|
|
return (boolean)left | (boolean)right;
|
|
@@ -936,30 +936,30 @@ public class DefMath {
|
|
return intIntegralValue(left) | intIntegralValue(right);
|
|
return intIntegralValue(left) | intIntegralValue(right);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// shift operators, valid for any integral types, but does not promote.
|
|
// shift operators, valid for any integral types, but does not promote.
|
|
// we implement all shifts as long shifts, because the extra bits are ignored anyway.
|
|
// we implement all shifts as long shifts, because the extra bits are ignored anyway.
|
|
-
|
|
|
|
|
|
+
|
|
private static int lsh(int a, long b) {
|
|
private static int lsh(int a, long b) {
|
|
return a << b;
|
|
return a << b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long lsh(long a, long b) {
|
|
private static long lsh(long a, long b) {
|
|
return a << b;
|
|
return a << b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float lsh(float a, long b) {
|
|
private static float lsh(float a, long b) {
|
|
- throw new ClassCastException("Cannot apply [<<] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [<<] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double lsh(double a, long b) {
|
|
private static double lsh(double a, long b) {
|
|
- throw new ClassCastException("Cannot apply [<<] operation to type [double]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [<<] operation to type [double]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean lsh(boolean a, long b) {
|
|
private static boolean lsh(boolean a, long b) {
|
|
- throw new ClassCastException("Cannot apply [<<] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [<<] operation to type [boolean]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
public static Object lsh(Object left, long right) {
|
|
public static Object lsh(Object left, long right) {
|
|
if (left instanceof Long) {
|
|
if (left instanceof Long) {
|
|
return (long)(left) << right;
|
|
return (long)(left) << right;
|
|
@@ -967,25 +967,25 @@ public class DefMath {
|
|
return intIntegralValue(left) << right;
|
|
return intIntegralValue(left) << right;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int rsh(int a, long b) {
|
|
private static int rsh(int a, long b) {
|
|
return a >> b;
|
|
return a >> b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long rsh(long a, long b) {
|
|
private static long rsh(long a, long b) {
|
|
return a >> b;
|
|
return a >> b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float rsh(float a, long b) {
|
|
private static float rsh(float a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double rsh(double a, long b) {
|
|
private static double rsh(double a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>] operation to type [double]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>] operation to type [double]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean rsh(boolean a, long b) {
|
|
private static boolean rsh(boolean a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>] operation to type [boolean]");
|
|
}
|
|
}
|
|
|
|
|
|
public static Object rsh(Object left, long right) {
|
|
public static Object rsh(Object left, long right) {
|
|
@@ -995,25 +995,25 @@ public class DefMath {
|
|
return intIntegralValue(left) >> right;
|
|
return intIntegralValue(left) >> right;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static int ush(int a, long b) {
|
|
private static int ush(int a, long b) {
|
|
return a >>> b;
|
|
return a >>> b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static long ush(long a, long b) {
|
|
private static long ush(long a, long b) {
|
|
return a >>> b;
|
|
return a >>> b;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static float ush(float a, long b) {
|
|
private static float ush(float a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>>] operation to type [float]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>>] operation to type [float]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static double ush(double a, long b) {
|
|
private static double ush(double a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>>] operation to type [double]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>>] operation to type [double]");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static boolean ush(boolean a, long b) {
|
|
private static boolean ush(boolean a, long b) {
|
|
- throw new ClassCastException("Cannot apply [>>>] operation to type [boolean]");
|
|
|
|
|
|
+ throw new ClassCastException("Cannot apply [>>>] operation to type [boolean]");
|
|
}
|
|
}
|
|
|
|
|
|
public static Object ush(Object left, long right) {
|
|
public static Object ush(Object left, long right) {
|
|
@@ -1023,15 +1023,15 @@ public class DefMath {
|
|
return intIntegralValue(left) >>> right;
|
|
return intIntegralValue(left) >>> right;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- /**
|
|
|
|
- * unboxes a class to its primitive type, or returns the original
|
|
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * unboxes a class to its primitive type, or returns the original
|
|
* class if its not a boxed type.
|
|
* class if its not a boxed type.
|
|
*/
|
|
*/
|
|
private static Class<?> unbox(Class<?> clazz) {
|
|
private static Class<?> unbox(Class<?> clazz) {
|
|
return MethodType.methodType(clazz).unwrap().returnType();
|
|
return MethodType.methodType(clazz).unwrap().returnType();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Unary promotion. All Objects are promoted to Object. */
|
|
/** Unary promotion. All Objects are promoted to Object. */
|
|
private static Class<?> promote(Class<?> clazz) {
|
|
private static Class<?> promote(Class<?> clazz) {
|
|
// if either is a non-primitive type -> Object.
|
|
// if either is a non-primitive type -> Object.
|
|
@@ -1039,25 +1039,25 @@ public class DefMath {
|
|
return Object.class;
|
|
return Object.class;
|
|
}
|
|
}
|
|
// always promoted to integer
|
|
// always promoted to integer
|
|
- if (clazz == byte.class || clazz == short.class || clazz == char.class || clazz == int.class) {
|
|
|
|
- return int.class;
|
|
|
|
- } else {
|
|
|
|
- return clazz;
|
|
|
|
- }
|
|
|
|
|
|
+ if (clazz == byte.class || clazz == short.class || clazz == char.class || clazz == int.class) {
|
|
|
|
+ return int.class;
|
|
|
|
+ } else {
|
|
|
|
+ return clazz;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Binary promotion. */
|
|
/** Binary promotion. */
|
|
private static Class<?> promote(Class<?> a, Class<?> b) {
|
|
private static Class<?> promote(Class<?> a, Class<?> b) {
|
|
// if either is a non-primitive type -> Object.
|
|
// if either is a non-primitive type -> Object.
|
|
if (a.isPrimitive() == false || b.isPrimitive() == false) {
|
|
if (a.isPrimitive() == false || b.isPrimitive() == false) {
|
|
return Object.class;
|
|
return Object.class;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// boolean -> boolean
|
|
// boolean -> boolean
|
|
if (a == boolean.class && b == boolean.class) {
|
|
if (a == boolean.class && b == boolean.class) {
|
|
return boolean.class;
|
|
return boolean.class;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// ordinary numeric promotion
|
|
// ordinary numeric promotion
|
|
if (a == double.class || b == double.class) {
|
|
if (a == double.class || b == double.class) {
|
|
return double.class;
|
|
return double.class;
|
|
@@ -1069,7 +1069,7 @@ public class DefMath {
|
|
return int.class;
|
|
return int.class;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static final Lookup PRIV_LOOKUP = MethodHandles.lookup();
|
|
private static final Lookup PRIV_LOOKUP = MethodHandles.lookup();
|
|
|
|
|
|
private static final Map<Class<?>,Map<String,MethodHandle>> TYPE_OP_MAPPING = Collections.unmodifiableMap(
|
|
private static final Map<Class<?>,Map<String,MethodHandle>> TYPE_OP_MAPPING = Collections.unmodifiableMap(
|
|
@@ -1107,7 +1107,7 @@ public class DefMath {
|
|
}
|
|
}
|
|
}))
|
|
}))
|
|
);
|
|
);
|
|
-
|
|
|
|
|
|
+
|
|
/** Returns an appropriate method handle for a unary or shift operator, based only on the receiver (LHS) */
|
|
/** Returns an appropriate method handle for a unary or shift operator, based only on the receiver (LHS) */
|
|
public static MethodHandle lookupUnary(Class<?> receiverClass, String name) {
|
|
public static MethodHandle lookupUnary(Class<?> receiverClass, String name) {
|
|
MethodHandle handle = TYPE_OP_MAPPING.get(promote(unbox(receiverClass))).get(name);
|
|
MethodHandle handle = TYPE_OP_MAPPING.get(promote(unbox(receiverClass))).get(name);
|
|
@@ -1116,7 +1116,7 @@ public class DefMath {
|
|
}
|
|
}
|
|
return handle;
|
|
return handle;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Returns an appropriate method handle for a binary operator, based on promotion of the LHS and RHS arguments */
|
|
/** Returns an appropriate method handle for a binary operator, based on promotion of the LHS and RHS arguments */
|
|
public static MethodHandle lookupBinary(Class<?> classA, Class<?> classB, String name) {
|
|
public static MethodHandle lookupBinary(Class<?> classA, Class<?> classB, String name) {
|
|
MethodHandle handle = TYPE_OP_MAPPING.get(promote(promote(unbox(classA)), promote(unbox(classB)))).get(name);
|
|
MethodHandle handle = TYPE_OP_MAPPING.get(promote(promote(unbox(classA)), promote(unbox(classB)))).get(name);
|
|
@@ -1125,7 +1125,7 @@ public class DefMath {
|
|
}
|
|
}
|
|
return handle;
|
|
return handle;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Returns a generic method handle for any operator, that can handle all valid signatures, nulls, corner cases */
|
|
/** Returns a generic method handle for any operator, that can handle all valid signatures, nulls, corner cases */
|
|
public static MethodHandle lookupGeneric(String name) {
|
|
public static MethodHandle lookupGeneric(String name) {
|
|
return TYPE_OP_MAPPING.get(Object.class).get(name);
|
|
return TYPE_OP_MAPPING.get(Object.class).get(name);
|
|
@@ -1143,7 +1143,7 @@ public class DefMath {
|
|
return returnValue;
|
|
return returnValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Slow dynamic cast: casts {@code value} to an instance of {@code clazz}
|
|
* Slow dynamic cast: casts {@code value} to an instance of {@code clazz}
|
|
* based upon inspection. If {@code lhs} is null, no cast takes place.
|
|
* based upon inspection. If {@code lhs} is null, no cast takes place.
|
|
@@ -1173,7 +1173,7 @@ public class DefMath {
|
|
return value;
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Slowly returns a Number for o. Just for supporting dynamicCast */
|
|
/** Slowly returns a Number for o. Just for supporting dynamicCast */
|
|
static Number getNumber(Object o) {
|
|
static Number getNumber(Object o) {
|
|
if (o instanceof Number) {
|
|
if (o instanceof Number) {
|
|
@@ -1184,17 +1184,17 @@ public class DefMath {
|
|
throw new ClassCastException("Cannot convert [" + o.getClass() + "] to a Number");
|
|
throw new ClassCastException("Cannot convert [" + o.getClass() + "] to a Number");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static final MethodHandle DYNAMIC_CAST;
|
|
private static final MethodHandle DYNAMIC_CAST;
|
|
private static final MethodHandle DYNAMIC_RECEIVER_CAST;
|
|
private static final MethodHandle DYNAMIC_RECEIVER_CAST;
|
|
static {
|
|
static {
|
|
final Lookup lookup = MethodHandles.lookup();
|
|
final Lookup lookup = MethodHandles.lookup();
|
|
try {
|
|
try {
|
|
- DYNAMIC_CAST = lookup.findStatic(lookup.lookupClass(),
|
|
|
|
- "dynamicCast",
|
|
|
|
|
|
+ DYNAMIC_CAST = lookup.findStatic(lookup.lookupClass(),
|
|
|
|
+ "dynamicCast",
|
|
MethodType.methodType(Object.class, Class.class, Object.class));
|
|
MethodType.methodType(Object.class, Class.class, Object.class));
|
|
- DYNAMIC_RECEIVER_CAST = lookup.findStatic(lookup.lookupClass(),
|
|
|
|
- "dynamicReceiverCast",
|
|
|
|
|
|
+ DYNAMIC_RECEIVER_CAST = lookup.findStatic(lookup.lookupClass(),
|
|
|
|
+ "dynamicReceiverCast",
|
|
MethodType.methodType(Object.class, Object.class, Object.class));
|
|
MethodType.methodType(Object.class, Object.class, Object.class));
|
|
} catch (ReflectiveOperationException e) {
|
|
} catch (ReflectiveOperationException e) {
|
|
throw new AssertionError(e);
|
|
throw new AssertionError(e);
|
|
@@ -1204,7 +1204,7 @@ public class DefMath {
|
|
/** Looks up generic method, with a dynamic cast to the receiver's type. (compound assignment) */
|
|
/** Looks up generic method, with a dynamic cast to the receiver's type. (compound assignment) */
|
|
public static MethodHandle dynamicCast(MethodHandle target) {
|
|
public static MethodHandle dynamicCast(MethodHandle target) {
|
|
// adapt dynamic receiver cast to the generic method
|
|
// adapt dynamic receiver cast to the generic method
|
|
- MethodHandle cast = DYNAMIC_RECEIVER_CAST.asType(MethodType.methodType(target.type().returnType(),
|
|
|
|
|
|
+ MethodHandle cast = DYNAMIC_RECEIVER_CAST.asType(MethodType.methodType(target.type().returnType(),
|
|
target.type().returnType(),
|
|
target.type().returnType(),
|
|
target.type().parameterType(0)));
|
|
target.type().parameterType(0)));
|
|
// drop the RHS parameter
|
|
// drop the RHS parameter
|
|
@@ -1212,7 +1212,7 @@ public class DefMath {
|
|
// combine: f(x,y) -> g(f(x,y), x, y);
|
|
// combine: f(x,y) -> g(f(x,y), x, y);
|
|
return MethodHandles.foldArguments(cast, target);
|
|
return MethodHandles.foldArguments(cast, target);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Looks up generic method, with a dynamic cast to the specified type. (explicit assignment) */
|
|
/** Looks up generic method, with a dynamic cast to the specified type. (explicit assignment) */
|
|
public static MethodHandle dynamicCast(MethodHandle target, Class<?> desired) {
|
|
public static MethodHandle dynamicCast(MethodHandle target, Class<?> desired) {
|
|
// adapt dynamic cast to the generic method
|
|
// adapt dynamic cast to the generic method
|
|
@@ -1221,23 +1221,23 @@ public class DefMath {
|
|
MethodHandle cast = DYNAMIC_CAST.bindTo(desired);
|
|
MethodHandle cast = DYNAMIC_CAST.bindTo(desired);
|
|
return MethodHandles.filterReturnValue(target, cast);
|
|
return MethodHandles.filterReturnValue(target, cast);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/** Forces a cast to class A for target (only if types differ) */
|
|
/** Forces a cast to class A for target (only if types differ) */
|
|
public static MethodHandle cast(Class<?> classA, MethodHandle target) {
|
|
public static MethodHandle cast(Class<?> classA, MethodHandle target) {
|
|
MethodType newType = MethodType.methodType(classA).unwrap();
|
|
MethodType newType = MethodType.methodType(classA).unwrap();
|
|
MethodType targetType = MethodType.methodType(target.type().returnType()).unwrap();
|
|
MethodType targetType = MethodType.methodType(target.type().returnType()).unwrap();
|
|
-
|
|
|
|
|
|
+
|
|
// don't do a conversion if types are the same. explicitCastArguments has this opto,
|
|
// don't do a conversion if types are the same. explicitCastArguments has this opto,
|
|
// but we do it explicitly, to make the boolean check simpler
|
|
// but we do it explicitly, to make the boolean check simpler
|
|
if (newType.returnType() == targetType.returnType()) {
|
|
if (newType.returnType() == targetType.returnType()) {
|
|
return target;
|
|
return target;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// we don't allow the to/from boolean conversions of explicitCastArguments
|
|
// we don't allow the to/from boolean conversions of explicitCastArguments
|
|
if (newType.returnType() == boolean.class || targetType.returnType() == boolean.class) {
|
|
if (newType.returnType() == boolean.class || targetType.returnType() == boolean.class) {
|
|
throw new ClassCastException("Cannot cast " + targetType.returnType() + " to " + newType.returnType());
|
|
throw new ClassCastException("Cannot cast " + targetType.returnType() + " to " + newType.returnType());
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// null return values are not possible for our arguments.
|
|
// null return values are not possible for our arguments.
|
|
return MethodHandles.explicitCastArguments(target, target.type().changeReturnType(newType.returnType()));
|
|
return MethodHandles.explicitCastArguments(target, target.type().changeReturnType(newType.returnType()));
|
|
}
|
|
}
|