// We distinguish three cases for the second operand: either it is known statically to deliver
// nodes only (a traditional path expression), or it is known statically to deliver atomic values
// only (a simple mapping expression), or we don't yet know.
ItemType stepType = step.getItemType(th);
if (th.isSubType(stepType, Type.NODE_TYPE)) {
if ((step.getSpecialProperties() & StaticProperty.NON_CREATIVE) != 0) {
// A traditional path expression
// We don't need the operands to be sorted; any sorting that's needed
// will be done at the top level
Optimizer opt = visitor.getConfiguration().getOptimizer();
start2 = ExpressionTool.unsorted(opt, start, false);
Expression step2 = ExpressionTool.unsorted(opt, step, false);
PathExpression path = new PathExpression(start2, step2);
ExpressionTool.copyLocationInfo(this, path);
Expression sortedPath = path.addDocumentSorter();
ExpressionTool.copyLocationInfo(this, sortedPath);
sortedPath = sortedPath.simplify(visitor);
return sortedPath.typeCheck(visitor, contextItemType);
} else {
// We can still use a path expression, but need to retain the sorting of operands
PathExpression path = new PathExpression(start, step);
ExpressionTool.copyLocationInfo(this, path);
Expression sortedPath = path.addDocumentSorter();
ExpressionTool.copyLocationInfo(this, sortedPath);
sortedPath = sortedPath.simplify(visitor);
return sortedPath.typeCheck(visitor, contextItemType);
}
// Decide whether the result needs to be wrapped in a sorting
// expression to deliver the results in document order
// int props = getSpecialProperties();
//
// if ((props & StaticProperty.ORDERED_NODESET) != 0) {
// return this;
// } else if ((props & StaticProperty.REVERSE_DOCUMENT_ORDER) != 0) {
// return SystemFunction.makeSystemFunction("reverse", new Expression[]{this});
// } else {
// return new DocumentSorter(this);
// }
} else if (stepType.isAtomicType()) {
// This is a simple mapping expression: a/b where b returns atomic values
ForEach ame = new ForEach(start, step, false);
ExpressionTool.copyLocationInfo(this, ame);
return visitor.typeCheck(visitor.simplify(ame), contextItemType);
} else {