Internal changes
Comparison of two integer values was converting both to doubles; this has been fixed.
Handling of "head-tail recursion" has been made more efficient. Constructs that select
all items in a sequence after the first (for example $x[position()!=1]
) are now
recognized specially when doing deferred evaluation; in effect they return a view of the
underlying sequence. (Previous Saxon versions handled this in some cases, in a different way).
In XQuery, tail calls within user-defined functions are now optimized. This enables deeply recursive algorithms to execute without running out of stack space.
All the decisions about sorting a path expression into document order are now made at compile time.
Union, intersect, and except expressions of the form E[c1] | E[c2]
are now rewritten
as E[c1 or c2]
. This avoids the need to evaluate E twice, and may avoid a sort.
The coding of the cast, instance of, and castable operators has been cleaned up.
The implementation of substring
now optimizes for the case where the second
and third arguments are integers - it no longer does everything using double arithmetic.
The StringValue
class can now encapsulate any CharSequence
, not
necessarily always a String
. This avoids some unnnecessary conversions, though
for full effect the Item#getStringValue()
method will also have to be changed to
return a CharSequence
.
The implementation of xsl:sequence
has been improved. When a required type is
given in the as
attribute, the type of the value is now checked "on the fly"
as items are written to the current output destination. The SequenceChecker
is
also capable of atomizing any nodes that are written (in fact, the nodes are atomized before they
are even created). It also converts untyped atomic values to the required type.
This is an inverse of the way checking is
done by SequenceIterators during XPath evaluation; we now have a "pull" pipeline (the SequenceIterator)
for iterating over the results of XPath expressions, and a "push" pipeline (the Receiver) for generating
events on a result tree. Both are capable of on-the-fly type checking. The capability of
xsl:sequence
to do this is reused in xsl:template
and xsl:function
:
an implicit xsl:sequence
instruction is generated to wrap the contents of the template or function, and this inner instruction
is responsible for any type checking and atomization.
Eventually I am hoping to move more and more to a "pull" model, where instructions are evaluated using iterators in the same way as expressions are evaluated today. The current model can be seen as transitional. Some instructions, in particular those used by XQuery such as Element and Attribute, are currently dual-mode - they work both as instructions and as expressions.
The expression generate-id(A) = generate-id(B)
, which is often used in XSLT 1.0
to compare node identities, is now rewritten internally as A is B
. This requires some
minor tweaks to ensure that the result is correct when either A or B or both is an empty sequence.