You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2019/03/28 17:20:52 UTC
[commons-jexl] branch master updated: JEXL-295: positivize performs
integral promotion of char, byte,
short Task #JEXL-295 - Add unary plus operator
This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/master by this push:
new 76af65b JEXL-295: positivize performs integral promotion of char, byte, short Task #JEXL-295 - Add unary plus operator
76af65b is described below
commit 76af65b52c04ed9962372388db824041d008fe01
Author: henrib <he...@apache.org>
AuthorDate: Thu Mar 28 18:20:25 2019 +0100
JEXL-295: positivize performs integral promotion of char, byte, short
Task #JEXL-295 - Add unary plus operator
---
.../org/apache/commons/jexl3/JexlArithmetic.java | 48 ++++++++--------
.../org/apache/commons/jexl3/JexlOperator.java | 4 +-
.../apache/commons/jexl3/internal/Interpreter.java | 21 +++++--
.../apache/commons/jexl3/internal/Operators.java | 8 ++-
.../org/apache/commons/jexl3/ArithmeticTest.java | 66 ++++++++++++----------
5 files changed, 83 insertions(+), 64 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 6078bab..5a2c015 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -466,7 +466,7 @@ public class JexlArithmetic {
BigDecimal bigd = (BigDecimal) original;
// if it's bigger than a double it can't be narrowed
if (bigd.compareTo(BIGD_DOUBLE_MAX_VALUE) > 0
- || bigd.compareTo(BIGD_DOUBLE_MIN_VALUE) < 0) {
+ || bigd.compareTo(BIGD_DOUBLE_MIN_VALUE) < 0) {
return original;
} else {
try {
@@ -827,34 +827,32 @@ public class JexlArithmetic {
}
/**
- * Absolute (positive) value (unary plus for numbers).
- *
- * @param val the value to get the absolute value from
+ * Positivize value (unary plus for numbers).
+ * <p>C/C++/C#/Java perform integral promotion of the operand, ie
+ * cast to int if type can represented as int without loss of precision.
+ * @param val the value to positivize
* @return the positive value
*/
public Object positivize(Object val) {
- if (val instanceof Integer) {
- return Math.abs((Integer) val);
- } else if (val instanceof Double) {
- return Math.abs((Double) val);
- } else if (val instanceof Long) {
- return Math.abs((Long) val);
- } else if (val instanceof BigDecimal) {
- return ((BigDecimal) val).abs();
- } else if (val instanceof BigInteger) {
- return ((BigInteger) val).abs();
- } else if (val instanceof Float) {
- return Math.abs((Float) val);
- } else if (val instanceof Short) {
- return (short) Math.abs((Short) val);
- } else if (val instanceof Byte) {
- return (byte) Math.abs((Byte) val);
- } else if (val instanceof Boolean) {
- return Boolean.TRUE;
- } else if (val instanceof AtomicBoolean) {
- return Boolean.TRUE;
+ if (val instanceof Short) {
+ return ((Short) val).intValue();
+ }
+ if (val instanceof Byte) {
+ return ((Byte) val).intValue();
+ }
+ if (val instanceof Number) {
+ return val;
+ }
+ if (val instanceof Character) {
+ return (int) (Character) val;
+ }
+ if (val instanceof Boolean) {
+ return val;
+ }
+ if (val instanceof AtomicBoolean) {
+ return ((AtomicBoolean) val).get();
}
- throw new ArithmeticException("Object abs:(" + val + ")");
+ throw new ArithmeticException("Object positivize:(" + val + ")");
}
/**
diff --git a/src/main/java/org/apache/commons/jexl3/JexlOperator.java b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
index eab309e..f510612 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlOperator.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
@@ -193,9 +193,9 @@ public enum JexlOperator {
NEGATE("-", "negate", 1),
/**
- * Absolute operator.
+ * Positivize operator.
* <br><strong>Syntax:</strong> <code>+x</code>
- * <br><strong>Method:</strong> <code>T plus(L x);</code>.
+ * <br><strong>Method:</strong> <code>T positivize(L x);</code>.
* @see JexlArithmetic#positivize
*/
POSITIVIZE("+", "positivize", 1),
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index aaea4d9..8b5b284 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -582,6 +582,11 @@ public class Interpreter extends InterpreterBase {
@Override
protected Object visit(ASTUnaryMinusNode node, Object data) {
+ // use cached value if literal
+ Object value = node.jjtGetValue();
+ if (value != null && !(value instanceof JexlMethod)) {
+ return value;
+ }
JexlNode valNode = node.jjtGetChild(0);
Object val = valNode.jjtAccept(this, data);
try {
@@ -591,8 +596,12 @@ public class Interpreter extends InterpreterBase {
}
Object number = arithmetic.negate(val);
// attempt to recoerce to literal class
- if (valNode instanceof ASTNumberLiteral && number instanceof Number) {
- number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass());
+ if ((number instanceof Number)) {
+ // cache it
+ if (valNode instanceof ASTNumberLiteral) {
+ number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass());
+ node.jjtSetValue(number);
+ }
}
return number;
} catch (ArithmeticException xrt) {
@@ -602,6 +611,11 @@ public class Interpreter extends InterpreterBase {
@Override
protected Object visit(ASTUnaryPlusNode node, Object data) {
+ // use cached value if literal
+ Object value = node.jjtGetValue();
+ if (value != null && !(value instanceof JexlMethod)) {
+ return value;
+ }
JexlNode valNode = node.jjtGetChild(0);
Object val = valNode.jjtAccept(this, data);
try {
@@ -610,9 +624,8 @@ public class Interpreter extends InterpreterBase {
return result;
}
Object number = arithmetic.positivize(val);
- // attempt to recoerce to literal class
if (valNode instanceof ASTNumberLiteral && number instanceof Number) {
- number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass());
+ node.jjtSetValue(number);
}
return number;
} catch (ArithmeticException xrt) {
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Operators.java b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
index d157445..a4ab493 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Operators.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
@@ -107,14 +107,16 @@ public class Operators {
* @param node the syntactic node
* @param operator the operator
* @param args the arguments, the first one being the target of assignment
- * @return the result of the operator evaluation
+ * @return JexlOperator.ASSIGN if operation assignment has been performed,
+ * JexlEngine.TRY_FAILED if no operation was performed,
+ * the value to use as the side effect argument otherwise
*/
protected Object tryAssignOverload(JexlNode node, JexlOperator operator, Object...args) {
final JexlArithmetic arithmetic = interpreter.arithmetic;
if (args.length != operator.getArity()) {
return JexlEngine.TRY_FAILED;
}
- // try to call overload on side effect
+ // try to call overload with side effect
Object result = tryOverload(node, operator, args);
if (result != JexlEngine.TRY_FAILED) {
return result;
@@ -125,7 +127,7 @@ public class Operators {
throw new IllegalArgumentException("must be called with a side-effect operator");
}
if (operators != null && operators.overloads(base)) {
- // in case there is an overload
+ // in case there is an overload on the base operator
try {
JexlMethod vm = operators.getOperator(base, args);
if (vm != null) {
diff --git a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
index 3a50d66..ce9ccae 100644
--- a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
@@ -142,42 +142,48 @@ public class ArithmeticTest extends JexlTestCase {
asserter.setVariable("aBigInteger", new BigInteger("7"));
asserter.setVariable("aBigDecimal", new BigDecimal("8.8"));
- asserter.assertExpression("-3", new Integer("-3"));
- asserter.assertExpression("-3.0", new Double("-3.0"));
- asserter.assertExpression("-aByte", new Byte((byte) -1));
- asserter.assertExpression("-aShort", new Short((short) -2));
- asserter.assertExpression("-anInteger", new Integer(-3));
- asserter.assertExpression("-aLong", new Long(-4));
- asserter.assertExpression("-aFloat", new Float(-5.5));
- asserter.assertExpression("-aDouble", new Double(-6.6));
- asserter.assertExpression("-aBigInteger", new BigInteger("-7"));
- asserter.assertExpression("-aBigDecimal", new BigDecimal("-8.8"));
+ // loop to allow checking caching of constant numerals (debug)
+ for(int i = 0 ; i < 2; ++i) {
+ asserter.assertExpression("-3", new Integer("-3"));
+ asserter.assertExpression("-3.0", new Double("-3.0"));
+ asserter.assertExpression("-aByte", new Byte((byte) -1));
+ asserter.assertExpression("-aShort", new Short((short) -2));
+ asserter.assertExpression("-anInteger", new Integer(-3));
+ asserter.assertExpression("-aLong", new Long(-4));
+ asserter.assertExpression("-aFloat", new Float(-5.5));
+ asserter.assertExpression("-aDouble", new Double(-6.6));
+ asserter.assertExpression("-aBigInteger", new BigInteger("-7"));
+ asserter.assertExpression("-aBigDecimal", new BigDecimal("-8.8"));
+ }
}
/**
* test some simple mathematical calculations
*/
@Test
- public void testUnaryPlusus() throws Exception {
- asserter.setVariable("aByte", new Byte((byte) -1));
- asserter.setVariable("aShort", new Short((short) -2));
- asserter.setVariable("anInteger", new Integer(-3));
- asserter.setVariable("aLong", new Long(-4));
- asserter.setVariable("aFloat", new Float(-5.5));
- asserter.setVariable("aDouble", new Double(-6.6));
- asserter.setVariable("aBigInteger", new BigInteger("-7"));
- asserter.setVariable("aBigDecimal", new BigDecimal("-8.8"));
-
- asserter.assertExpression("+3", new Integer("3"));
- asserter.assertExpression("+3.0", new Double("3.0"));
- asserter.assertExpression("+aByte", new Byte((byte) 1));
- asserter.assertExpression("+aShort", new Short((short) 2));
- asserter.assertExpression("+anInteger", new Integer(3));
- asserter.assertExpression("+aLong", new Long(4));
- asserter.assertExpression("+aFloat", new Float(5.5));
- asserter.assertExpression("+aDouble", new Double(6.6));
- asserter.assertExpression("+aBigInteger", new BigInteger("7"));
- asserter.assertExpression("+aBigDecimal", new BigDecimal("8.8"));
+ public void testUnaryPlus() throws Exception {
+ asserter.setVariable("aByte", new Byte((byte) 1));
+ asserter.setVariable("aShort", new Short((short) 2));
+ asserter.setVariable("anInteger", new Integer(3));
+ asserter.setVariable("aLong", new Long(4));
+ asserter.setVariable("aFloat", new Float(5.5));
+ asserter.setVariable("aDouble", new Double(6.6));
+ asserter.setVariable("aBigInteger", new BigInteger("7"));
+ asserter.setVariable("aBigDecimal", new BigDecimal("8.8"));
+
+ // loop to allow checking caching of constant numerals (debug)
+ for(int i = 0 ; i < 2; ++i) {
+ asserter.assertExpression("+3", new Integer("3"));
+ asserter.assertExpression("+3.0", new Double("3.0"));
+ asserter.assertExpression("+aByte", new Integer(1));
+ asserter.assertExpression("+aShort", new Integer(2));
+ asserter.assertExpression("+anInteger", new Integer(3));
+ asserter.assertExpression("+aLong", new Long(4));
+ asserter.assertExpression("+aFloat", new Float(5.5));
+ asserter.assertExpression("+aDouble", new Double(6.6));
+ asserter.assertExpression("+aBigInteger", new BigInteger("7"));
+ asserter.assertExpression("+aBigDecimal", new BigDecimal("8.8"));
+ }
}
/**