Project

Profile

Help

Revision a3561dc8

Added by Michael Kay over 7 years ago

See issue 2063.

View differences:

latest9.5/hej/net/sf/saxon/expr/ArithmeticExpression.java
14 14
import net.sf.saxon.expr.parser.Token;
15 15
import net.sf.saxon.expr.parser.TypeChecker;
16 16
import net.sf.saxon.om.SequenceTool;
17
import net.sf.saxon.om.StandardNames;
18 17
import net.sf.saxon.trans.XPathException;
19 18
import net.sf.saxon.type.*;
20
import net.sf.saxon.value.*;
19
import net.sf.saxon.value.AtomicValue;
20
import net.sf.saxon.value.IntegerValue;
21
import net.sf.saxon.value.NumericValue;
22
import net.sf.saxon.value.SequenceType;
21 23

  
22 24
/**
23 25
 * Arithmetic Expression: an expression using one of the operators
......
110 112
        if (itemType0 instanceof ErrorType) {
111 113
            return Literal.makeEmptySequence();
112 114
        }
113
        AtomicType type0 = (AtomicType) itemType0.getPrimitiveItemType();
114
        if (type0.getFingerprint() == StandardNames.XS_UNTYPED_ATOMIC) {
115
        PlainType type0 = (PlainType) itemType0.getPrimitiveItemType();
116
        if (type0 == BuiltInAtomicType.UNTYPED_ATOMIC) {
115 117
        	operand0 = UntypedSequenceConverter.makeUntypedSequenceConverter(visitor.getConfiguration(), operand0, BuiltInAtomicType.DOUBLE);
116 118
            type0 = BuiltInAtomicType.DOUBLE;
117 119
        } else if (/*!(operand0 instanceof UntypedAtomicConverter)*/
118 120
                (operand0.getSpecialProperties()&StaticProperty.NOT_UNTYPED_ATOMIC) == 0 &&
119 121
                th.relationship(type0, BuiltInAtomicType.UNTYPED_ATOMIC) != TypeHierarchy.DISJOINT) {
120 122
        	operand0 = UntypedSequenceConverter.makeUntypedSequenceConverter(visitor.getConfiguration(), operand0, BuiltInAtomicType.DOUBLE);
121
            type0 = (AtomicType)operand0.getItemType(th);
123
            type0 = (PlainType)operand0.getItemType(th);
122 124
        }
123 125

  
124 126
        // System.err.println("First operand"); operand0.display(10);
......
130 132
        if (itemType1 instanceof ErrorType) {
131 133
            return Literal.makeEmptySequence();
132 134
        }
133
        AtomicType type1 = (AtomicType)itemType1.getPrimitiveItemType();
134
        if (type1.getFingerprint() == StandardNames.XS_UNTYPED_ATOMIC) {
135
        PlainType type1 = (PlainType)itemType1.getPrimitiveItemType();
136
        if (type1 == BuiltInAtomicType.UNTYPED_ATOMIC) {
135 137
        	operand1 = UntypedSequenceConverter.makeUntypedSequenceConverter(visitor.getConfiguration(), operand1, BuiltInAtomicType.DOUBLE);
136 138
            type1 = BuiltInAtomicType.DOUBLE;
137 139
        } else if (/*!(operand1 instanceof UntypedAtomicConverter) &&*/
138 140
                (operand1.getSpecialProperties()&StaticProperty.NOT_UNTYPED_ATOMIC) == 0 &&
139 141
                th.relationship(type1, BuiltInAtomicType.UNTYPED_ATOMIC) != TypeHierarchy.DISJOINT) {
140 142
        	operand1 = UntypedSequenceConverter.makeUntypedSequenceConverter(visitor.getConfiguration(), operand1, BuiltInAtomicType.DOUBLE);
141
            type1 = (AtomicType)operand1.getItemType(th);
143
            type1 = (PlainType)operand1.getItemType(th);
142 144
        }
143 145

  
144 146
        if (operand0 != oldOp0) {
......
179 181
        boolean mustResolve = !(type0.equals(BuiltInAtomicType.ANY_ATOMIC) || type1.equals(BuiltInAtomicType.ANY_ATOMIC)
180 182
                || type0.equals(BuiltInAtomicType.NUMERIC) || type1.equals(BuiltInAtomicType.NUMERIC));
181 183

  
182
        calculator = Calculator.getCalculator(
183
                type0.getFingerprint(), type1.getFingerprint(), mapOpCode(operator), mustResolve);
184
        if (type0 instanceof AtomicType && type1 instanceof AtomicType) {
185
            calculator = Calculator.getCalculator(
186
                    ((AtomicType)type0).getFingerprint(), ((AtomicType)type1).getFingerprint(), mapOpCode(operator), mustResolve);
184 187

  
185
        if (calculator == null) {
186
            XPathException de = new XPathException("Arithmetic operator is not defined for arguments of types (" +
187
                    type0.getDescription() + ", " + type1.getDescription() + ")");
188
            de.setLocator(this);
189
            de.setErrorCode("XPTY0004");
190
            throw de;
188
            if (calculator == null) {
189
                XPathException de = new XPathException("Arithmetic operator is not defined for arguments of types (" +
190
                        ((AtomicType)type0).getDescription() + ", " + ((AtomicType)type1).getDescription() + ")");
191
                de.setLocator(this);
192
                de.setErrorCode("XPTY0004");
193
                throw de;
194
            }
191 195
        }
192 196

  
193 197
        try {
latest9.5/hej/net/sf/saxon/expr/ArithmeticExpression10.java
13 13
import net.sf.saxon.functions.NumberFn;
14 14
import net.sf.saxon.functions.SystemFunctionCall;
15 15
import net.sf.saxon.lib.NamespaceConstant;
16
import net.sf.saxon.om.*;
16
import net.sf.saxon.om.GroundedValue;
17
import net.sf.saxon.om.Sequence;
18
import net.sf.saxon.om.SequenceTool;
19
import net.sf.saxon.om.StructuredQName;
17 20
import net.sf.saxon.trans.XPathException;
18 21
import net.sf.saxon.type.*;
19 22
import net.sf.saxon.value.*;
......
89 92
        if (itemType0 instanceof ErrorType) {
90 93
            return Literal.makeLiteral(DoubleValue.NaN);
91 94
        }
92
        AtomicType type0 = (AtomicType) itemType0.getPrimitiveItemType();
95
        PlainType type0 = (PlainType) itemType0.getPrimitiveItemType();
93 96

  
94 97
        final ItemType itemType1 = operand1.getItemType(th);
95 98
        if (itemType1 instanceof ErrorType) {
96 99
            return Literal.makeLiteral(DoubleValue.NaN);
97 100
        }
98
        AtomicType type1 = (AtomicType)itemType1.getPrimitiveItemType();
101
        PlainType type1 = (PlainType)itemType1.getPrimitiveItemType();
99 102

  
100 103
        // If both operands are integers, use integer arithmetic and convert the result to a double
101 104
        if (th.isSubType(type0, BuiltInAtomicType.INTEGER) &&
......
146 149
         // we allow this to return an "ANY" calculator which defers the decision. However, we only allow this if
147 150
         // at least one of the operand types is AnyAtomicType or (otherwise unspecified) numeric.
148 151

  
152
        if (!(type0 instanceof AtomicType)) {
153
            // it's a union type
154
            type0 = BuiltInAtomicType.ANY_ATOMIC;
155
        }
156

  
157
        if (!(type1 instanceof AtomicType)) {
158
            // it's a union type
159
            type1 = BuiltInAtomicType.ANY_ATOMIC;
160
        }
161

  
149 162
        boolean mustResolve = !(type0.equals(BuiltInAtomicType.ANY_ATOMIC) || type1.equals(BuiltInAtomicType.ANY_ATOMIC)
150 163
                || type0.equals(BuiltInAtomicType.NUMERIC) || type1.equals(BuiltInAtomicType.NUMERIC));
151 164

  
152
        calculator = assignCalculator(type0, type1, mustResolve);
165
        calculator = assignCalculator((AtomicType)type0, (AtomicType)type1, mustResolve);
153 166

  
154 167
        try {
155 168
            if ((operand0 instanceof Literal) && (operand1 instanceof Literal)) {
......
178 191
    }
179 192

  
180 193
    private Expression createConversionCode(
181
            Expression operand, final Configuration config, AtomicType type) {
194
            Expression operand, final Configuration config, PlainType type) {
182 195
        TypeHierarchy th = config.getTypeHierarchy();
183 196
        if (Cardinality.allowsMany(operand.getCardinality())) {               
184 197
            Expression fie = FirstItemExpression.makeFirstItemExpression(operand);

Also available in: Unified diff