in modules/lang-painless/src/main/java/org/elasticsearch/painless/phase/DefaultConstantFoldingOptimizationPhase.java [156:398]
public void visitBinaryMath(BinaryMathNode irBinaryMathNode, Consumer<ExpressionNode> scope) {
irBinaryMathNode.getLeftNode().visit(this, irBinaryMathNode::setLeftNode);
irBinaryMathNode.getRightNode().visit(this, irBinaryMathNode::setRightNode);
if (irBinaryMathNode.getLeftNode() instanceof ConstantNode && irBinaryMathNode.getRightNode() instanceof ConstantNode) {
ExpressionNode irLeftConstantNode = irBinaryMathNode.getLeftNode();
ExpressionNode irRightConstantNode = irBinaryMathNode.getRightNode();
Object leftConstantValue = irLeftConstantNode.getDecorationValue(IRDConstant.class);
Object rightConstantValue = irRightConstantNode.getDecorationValue(IRDConstant.class);
Operation operation = irBinaryMathNode.getDecorationValue(IRDOperation.class);
Class<?> type = irBinaryMathNode.getDecorationValue(IRDExpressionType.class);
if (operation == Operation.MUL) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue * (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue * (long) rightConstantValue));
} else if (type == float.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((float) leftConstantValue * (float) rightConstantValue));
} else if (type == double.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((double) leftConstantValue * (double) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.DIV) {
try {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue / (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue / (long) rightConstantValue));
} else if (type == float.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((float) leftConstantValue / (float) rightConstantValue));
} else if (type == double.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((double) leftConstantValue / (double) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
} catch (ArithmeticException ae) {
throw irBinaryMathNode.getLocation().createError(ae);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.REM) {
try {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue % (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue % (long) rightConstantValue));
} else if (type == float.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((float) leftConstantValue % (float) rightConstantValue));
} else if (type == double.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((double) leftConstantValue % (double) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
} catch (ArithmeticException ae) {
throw irBinaryMathNode.getLocation().createError(ae);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.ADD) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue + (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue + (long) rightConstantValue));
} else if (type == float.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((float) leftConstantValue + (float) rightConstantValue));
} else if (type == double.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((double) leftConstantValue + (double) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.SUB) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue - (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue - (long) rightConstantValue));
} else if (type == float.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((float) leftConstantValue - (float) rightConstantValue));
} else if (type == double.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((double) leftConstantValue - (double) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.LSH) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue << (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue << (int) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.RSH) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue >> (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue >> (int) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.USH) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue >>> (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue >>> (int) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.BWAND) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue & (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue & (long) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.XOR) {
if (type == boolean.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((boolean) leftConstantValue ^ (boolean) rightConstantValue));
} else if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue ^ (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue ^ (long) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
} else if (operation == Operation.BWOR) {
if (type == int.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((int) leftConstantValue | (int) rightConstantValue));
} else if (type == long.class) {
irLeftConstantNode.attachDecoration(new IRDConstant((long) leftConstantValue | (long) rightConstantValue));
} else {
throw irBinaryMathNode.getLocation()
.createError(
binaryError(
PainlessLookupUtility.typeToCanonicalTypeName(type),
operation.symbol,
irLeftConstantNode.getDecorationString(IRDConstant.class),
irRightConstantNode.getDecorationString(IRDConstant.class)
)
);
}
scope.accept(irLeftConstantNode);
}
}
}