Literal.isEmptySequence(operand1)) {
return new Literal(EmptySequence.getInstance());
}
if (type0.isExternalType() || type1.isExternalType()) {
XPathException de = new XPathException("Arithmetic operators are not defined for external objects");
de.setLocator(this);
de.setErrorCode("XPTY0004");
throw de;
}
if (operator == Token.NEGATE) {
if (operand1 instanceof Literal && ((Literal)operand1).getValue() instanceof NumericValue) {
NumericValue nv = (NumericValue)((Literal)operand1).getValue();
return new Literal(nv.negate());
} else {
NegateExpression ne = new NegateExpression(operand1);
ne.setBackwardsCompatible(false);
return visitor.typeCheck(ne, contextItemType);
}
}
// Get a calculator to implement the arithmetic operation. If the types are not yet specifically known,
// we allow this to return an "ANY" calculator which defers the decision. However, we only allow this if
// at least one of the operand types is AnyAtomicType or (otherwise unspecified) numeric.
boolean mustResolve = !(type0.equals(BuiltInAtomicType.ANY_ATOMIC) || type1.equals(BuiltInAtomicType.ANY_ATOMIC)
|| type0.equals(BuiltInAtomicType.NUMERIC) || type1.equals(BuiltInAtomicType.NUMERIC));
calculator = Calculator.getCalculator(
type0.getFingerprint(), type1.getFingerprint(), mapOpCode(operator), mustResolve);
if (calculator == null) {
XPathException de = new XPathException("Arithmetic operator is not defined for arguments of types (" +
type0.getDescription() + ", " + type1.getDescription() + ")");
de.setLocator(this);
de.setErrorCode("XPTY0004");
throw de;
}
try {
if ((operand0 instanceof Literal) && (operand1 instanceof Literal)) {