// discarding the sort keys and returning only the true result. The tuple
// is implemented as a Java object wrapped inside an ObjectValue, which is
// a general-purpose wrapper for objects that don't fit in the XPath type system.
if (sortSpecList != null) {
TupleExpression exp = new TupleExpression(1 + sortSpecList.size());
setLocation(exp);
exp.setExpression(0, action);
for (int i = 0; i < sortSpecList.size(); i++) {
try {
Expression sk =
TypeChecker.staticTypeCheck(
((SortSpec) sortSpecList.get(i)).sortKey,
SequenceType.OPTIONAL_ATOMIC,
false,
new RoleLocator(RoleLocator.ORDER_BY, "FLWR", i), env);
exp.setExpression(i + 1, sk);
} catch (XPathException err) {
grumble(err.getMessage());
}
}
action = exp;
}
for (int i = clauseList.size() - 1; i >= 0; i--) {
Object clause = clauseList.get(i);
if (clause instanceof ExpressionParser.ForClause) {
ExpressionParser.ForClause fc = (ExpressionParser.ForClause) clause;
ForExpression exp = new ForExpression();
exp.setVariableDeclaration(fc.rangeVariable);
exp.setPositionVariable(fc.positionVariable);
exp.setLocationId(env.getLocationMap().allocateLocationId(env.getSystemId(), t.getLineNumber(fc.offset)));
exp.setSequence(fc.sequence);
exp.setAction(action);
action = makeTracer(fc.offset, exp, Location.FOR_EXPRESSION, fc.rangeVariable.getNameCode());
} else {
LetClause lc = (LetClause) clause;
LetExpression exp = makeLetExpression();
exp.setVariableDeclaration(lc.variable);
exp.setLocationId(env.getLocationMap().allocateLocationId(env.getSystemId(), t.getLineNumber(lc.offset)));
exp.setSequence(lc.value);
exp.setAction(action);
action = makeTracer(lc.offset, exp, Location.LET_EXPRESSION, lc.variable.getNameCode());
}
}
// Now wrap the whole expression in a TupleSorter if there is a sort specification