private boolean isScalarConstants(Expression expr1, Expression expr2) { if ((expr1 instanceof Constant) && (expr2 instanceof Constant)) { return (expr1.getResultStructure() == Expression.STRUCT_SCALAR) && (expr2.getResultStructure() == Expression.STRUCT_SCALAR); } else { return false; } }
private void fillObjectField(Object[] fields) { int varargIndex = fields.length - 1; Object[] array = new Object[exprs.size() - varargIndex]; for (int i = 0; i < exprs.size(); i++) { Expression expr = exprs.get(i); Object result = expr.eval(); if (i < varargIndex) { fields[i] = result; } else { array[i - varargIndex] = result; } } fields[varargIndex] = array; }
private Expression simplify(UnaryExpression unary) { Expression expr = unary.getExpression(); expr = simplify(expr); if (unary instanceof ExprNOT) { if (expr instanceof Constant) { if (expr.equals(Constant.TRUE)) { return Constant.FALSE; } else if (expr.equals(Constant.FALSE)) { return Constant.TRUE; } } } unary.setExpression(expr); return unary; }
private void fillIntField(Object[] fields) { int varargIndex = fields.length - 1; int[] array = new int[exprs.size() - varargIndex]; for (int i = 0; i < exprs.size(); i++) { Expression expr = exprs.get(i); Object result = expr.eval(); if (i < varargIndex) { fields[i] = result; } else { if (result instanceof Float) { array[i - varargIndex] = ((Float) result).intValue(); } else if (result instanceof Double) { array[i - varargIndex] = ((Double) result).intValue(); } else { array[i - varargIndex] = ((Integer) result).intValue(); } } } fields[varargIndex] = array; }
private Expression simplify(AryExpression ary) { Expression expr1 = ary.getExpression1(); expr1 = simplify(expr1); Expression expr2 = ary.getExpression2(); expr2 = simplify(expr2); if (ary instanceof ExprADD) { if (isScalarConstants(expr1, expr2)) { if ((expr2.getResultType() == Expression.TYPE_INTEGER) && (expr1.getResultType() == Expression.TYPE_INTEGER)) { Constant constant = new Constant(Expression.TYPE_INTEGER, Expression.STRUCT_SCALAR); constant.setValue(expr1.evalAsInt() + expr2.evalAsInt()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_FLOAT) || (expr1.getResultType() == Expression.TYPE_FLOAT)) { Constant constant = new Constant(Expression.TYPE_FLOAT, Expression.STRUCT_SCALAR); constant.setValue(expr1.evalAsFloat() + expr2.evalAsFloat()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_NUMERIC) || (expr1.getResultType() == Expression.TYPE_NUMERIC)) { Constant constant = new Constant(Expression.TYPE_NUMERIC, Expression.STRUCT_SCALAR); constant.setValue(expr1.evalAsFloat() + expr2.evalAsFloat()); return constant; } else { return ary; } } else if ((expr1 instanceof Constant) || (expr2 instanceof Constant)) { if (expr1.equals(Constant.ZERO_F)) { return expr2; } else if (expr1.equals(Constant.ZERO_I)) { return expr2; } else if (expr1.equals(Constant.EMPTY_STRING)) { return expr2; } else if (expr2.equals(Constant.ZERO_F)) { return expr1; } else if (expr2.equals(Constant.ZERO_I)) { return expr1; } else if (expr2.equals(Constant.EMPTY_STRING)) { return expr1; } } } else if (ary instanceof ExprSUB) { if (isScalarConstants(expr1, expr2)) { if ((expr2.getResultType() == Expression.TYPE_INTEGER) && (expr1.getResultType() == Expression.TYPE_INTEGER)) { Constant constant = new Constant(Expression.TYPE_INTEGER, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsInt() - expr1.evalAsInt()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_FLOAT) || (expr1.getResultType() == Expression.TYPE_FLOAT)) { Constant constant = new Constant(Expression.TYPE_FLOAT, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() - expr1.evalAsFloat()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_NUMERIC) || (expr1.getResultType() == Expression.TYPE_NUMERIC)) { Constant constant = new Constant(Expression.TYPE_NUMERIC, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() - expr1.evalAsFloat()); return constant; } else { return ary; } } else if (expr1 instanceof Constant) { if (expr1.equals(Constant.ZERO_F)) { return expr2; } else if (expr1.equals(Constant.ZERO_I)) { return expr2; } } } else if (ary instanceof ExprMULT) { if (isScalarConstants(expr1, expr2)) { if ((expr2.getResultType() == Expression.TYPE_INTEGER) && (expr1.getResultType() == Expression.TYPE_INTEGER)) { Constant constant = new Constant(Expression.TYPE_INTEGER, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsInt() * expr1.evalAsInt()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_FLOAT) || (expr1.getResultType() == Expression.TYPE_FLOAT)) { Constant constant = new Constant(Expression.TYPE_FLOAT, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() * expr1.evalAsFloat()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_NUMERIC) || (expr1.getResultType() == Expression.TYPE_NUMERIC)) { Constant constant = new Constant(Expression.TYPE_NUMERIC, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() * expr1.evalAsFloat()); return constant; } else { return ary; } } else if ((expr1 instanceof Constant) || (expr2 instanceof Constant)) { if (expr1.equals(Constant.ZERO_F)) { return Constant.ZERO_F; } else if (expr1.equals(Constant.ZERO_I)) { return Constant.ZERO_I; } else if (expr2.equals(Constant.ZERO_F)) { return Constant.ZERO_F; } else if (expr2.equals(Constant.ZERO_I)) { return Constant.ZERO_I; } else if (expr1.equals(Constant.ONE_F)) { return expr2; } else if (expr1.equals(Constant.ONE_I)) { return expr2; } else if (expr2.equals(Constant.ONE_F)) { return expr1; } else if (expr2.equals(Constant.ONE_I)) { return expr1; } } } else if (ary instanceof ExprDIV) { if (isScalarConstants(expr1, expr2)) { if ((expr2.getResultType() == Expression.TYPE_INTEGER) && (expr1.getResultType() == Expression.TYPE_INTEGER)) { Constant constant = new Constant(Expression.TYPE_FLOAT, Expression.STRUCT_SCALAR); constant.setValue((float) expr2.evalAsInt() / (float) expr1.evalAsInt()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_FLOAT) || (expr1.getResultType() == Expression.TYPE_FLOAT)) { Constant constant = new Constant(Expression.TYPE_FLOAT, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() / expr1.evalAsFloat()); return constant; } else if ((expr2.getResultType() == Expression.TYPE_NUMERIC) || (expr1.getResultType() == Expression.TYPE_NUMERIC)) { Constant constant = new Constant(Expression.TYPE_NUMERIC, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsFloat() / expr1.evalAsFloat()); return constant; } else { return ary; } } else if ((expr1 instanceof Constant) || (expr2 instanceof Constant)) { if (expr1.equals(Constant.ONE_F)) { return expr2; } else if (expr1.equals(Constant.ONE_I)) { return expr2; } else if (expr2.equals(Constant.ZERO_F)) { return Constant.ZERO_F; } else if (expr2.equals(Constant.ZERO_I)) { return Constant.ZERO_I; } } } else if (ary instanceof ExprAND) { if ((expr1 instanceof Constant) && (expr2 instanceof Constant)) { ((Constant) expr1).setValue(expr2.evalAsBoolean() && expr1.evalAsBoolean()); return expr1; } else if ((expr1 instanceof Constant) || (expr2 instanceof Constant)) { if (expr1.equals(Constant.TRUE)) { return expr2; } else if (expr1.equals(Constant.FALSE)) { return Constant.FALSE; } else if (expr2.equals(Constant.TRUE)) { return expr1; } else if (expr2.equals(Constant.FALSE)) { return Constant.FALSE; } } } else if (ary instanceof ExprOR) { if (isScalarConstants(expr1, expr2)) { Constant constant = new Constant(Expression.TYPE_BOOL, Expression.STRUCT_SCALAR); constant.setValue(expr2.evalAsBoolean() || expr1.evalAsBoolean()); return constant; } else if ((expr1 instanceof Constant) || (expr2 instanceof Constant)) { if (expr1.equals(Constant.TRUE)) { return Constant.TRUE; } else if (expr1.equals(Constant.FALSE)) { return Constant.FALSE; } else if (expr2.equals(Constant.TRUE)) { return Constant.TRUE; } else if (expr2.equals(Constant.FALSE)) { return Constant.FALSE; } } } ary.setExpression1(expr1); ary.setExpression2(expr2); return ary; }
@Override public final Object eval() throws ArithmeticException { FunctionsDefinitions def = FunctionsDefinitions.getInstance(); Function function = def.getFunction(key); if (function == null) { throw new ArithmeticException( "Function " + key.getName() + "( " + key.getParamsSize() + " parameters) does not exist"); } else { Method method = function.getMethod(); if (fields == null) { initFieldsArray(function, method); } Object obj = function.getObject(); if (varargs) { Class clazz = method.getParameterTypes()[fields.length - 1]; Class ctype = getVarargType(clazz); if (ctype == Integer.TYPE) { fillIntField(fields); } else if (ctype == Float.TYPE) { fillFloatField(fields); } else { fillObjectField(fields); } } else { for (int i = 0; i < exprs.size(); i++) { Expression expr = exprs.get(i); Object _f = null; if (expr.getResultType() == TYPE_INTEGER) { _f = getField(expr.evalAsInt(), method.getParameterTypes()[i]); } else if (expr.getResultType() == TYPE_FLOAT) { _f = getField(expr.evalAsFloat(), method.getParameterTypes()[i]); } else if (expr.getResultType() == TYPE_BOOL) { _f = getField(expr.evalAsBoolean(), method.getParameterTypes()[i]); } else { _f = getField(expr.eval(), method.getParameterTypes()[i]); } fields[i] = _f; } } try { Object result = null; if (varargs) { result = method.invoke(obj, fields); } else { result = method.invoke(obj, fields); } if (method.getReturnType() == Integer.TYPE) { return result; } else if (method.getReturnType() == Short.TYPE) { return ((Short) result).intValue(); } else if (method.getReturnType() == Double.TYPE) { return ((Double) result).floatValue(); } else if (method.getReturnType() == Float.TYPE) { Float f = (Float) result; if (f.isInfinite()) { throw newArithmeticException(function); } return f; } else if (method.getReturnType() == Boolean.TYPE) { return ((Boolean) result).booleanValue(); } else { return result; } } catch (IllegalAccessException ex) { ArithmeticException e = new ArithmeticException("IllegalAccessException for function " + function.getName()); throw e; } catch (IllegalArgumentException ex) { ArithmeticException e = new ArithmeticException("Illegal argument for function " + function.getName()); throw e; } catch (InvocationTargetException ex) { Throwable _ex = ex.getCause(); String message = null; if (_ex != null) { message = "Exception in function " + function.getName() + " (" + _ex.getMessage() + ")"; } else { message = "Exception in function " + function.getName(); } ArithmeticException e = new ArithmeticException(message); e.initCause(_ex); e.setStackTrace(_ex.getStackTrace()); throw e; } } }