`f:length' added

This is aggressively tested in every instance where it could be affected,
since any mishandling of this value would be incredibly dangerous (best
case, it would blow up and abort; worst case, data are interchanged between
refs).
master
Mike Gerwitz 2014-12-04 02:15:22 -05:00
parent 4f7bb0fcef
commit 09d2231fc0
2 changed files with 79 additions and 1 deletions

View File

@ -66,7 +66,7 @@
<variable name="ns"
select="namespace-uri-from-QName( $name )" />
<f:ref arity="{$arity}">
<f:ref arity="{$arity}" length="1">
<element name="{$name}"
namespace="{$ns}" />
</f:ref>
@ -200,6 +200,9 @@
<attribute name="arity"
select="$target-arity - count( $args )" />
<attribute name="length"
select="count( $args ) + 1" />
<sequence select="$desc/*" />
</f:ref>
@ -234,4 +237,28 @@
($args, f:args( $fnref )) )" />
</function>
<!--
Retrieve length of @var{fnref} as a number of sequence items
While the reference is intended to be opaque, it is no secret that
the data are stored as a sequence. The length is therefore
important for stepping through that sequence of data, similar to how
data/struct length are required for pointer arithmetic when dealing
with memory in C.
So, this doesn't break encapsulation: it just tells us how big we
are, which is an external quality that can be easily discovered
without our help; we just cache it for both performance and
convenience. Aren't we nice?
-->
<function name="f:length" as="xs:double">
<param name="fnref" as="item()+" />
<variable name="desc" as="element( f:ref )"
select="$fnref[ 1 ]" />
<sequence select="number( $desc/@length )" />
</function>
</stylesheet>

View File

@ -68,6 +68,13 @@
<expect label="produces reference to expected QName"
test="f:QName( $x:result ) = $qname" />
<!-- this isn't breaking encapsulation: we know that a sequence
is returned and we must know how to delimit the references
within it -->
<expect label="produces length equal to length of returned
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -281,6 +288,10 @@
<expect label="retains target arity"
test="f:arity( $x:result ) = f:arity( $test-fn )" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -296,6 +307,10 @@
<!-- the function is now partially applied -->
<expect label="reduces arity by number of arguments"
test="f:arity( $x:result ) = f:arity( $test-fn ) - 2" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -313,6 +328,10 @@
<!-- the function is no longer partially applied -->
<expect label="restores target function arity"
test="f:arity( $x:result ) = f:arity( $test-fn )" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -330,6 +349,10 @@
<!-- the function is no longer partially applied -->
<expect label="reduces arity by number of argments"
test="f:arity( $x:result ) = f:arity( $test-fn ) - 3" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -347,6 +370,10 @@
<!-- the function is no longer partially applied -->
<expect label="increases arity by difference in argument count"
test="f:arity( $x:result ) = f:arity( $test-fn ) - 1" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
</scenario>
@ -419,6 +446,10 @@
<expect label="sets arguments by reference"
test="f:args( $x:result )[ 1 ] is $args/foo:a
and f:args( $x:result )[ 2 ] is $args/foo:b" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -448,6 +479,10 @@
<expect label="pushes new arguments by reference"
test="f:args( $x:result )[ 3 ] is $args/foo:c
and f:args( $x:result )[ 4 ] is $args/foo:d" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -470,6 +505,10 @@
<expect label="retains previous arguments by reference"
test="f:args( $x:result )[ 1 ] is $args/foo:a
and f:args( $x:result )[ 2 ] is $args/foo:b" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
</scenario>
@ -494,6 +533,10 @@
<expect label="sets arguments by reference"
test="f:args( $x:result )[ 1 ] is $args/foo:a
and f:args( $x:result )[ 2 ] is $args/foo:b" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -523,6 +566,10 @@
<expect label="unshifts new arguments by reference"
test="f:args( $x:result )[ 1 ] is $args/foo:c
and f:args( $x:result )[ 2 ] is $args/foo:d" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
@ -545,6 +592,10 @@
<expect label="retains previous arguments by reference"
test="f:args( $x:result )[ 1 ] is $args/foo:a
and f:args( $x:result )[ 2 ] is $args/foo:b" />
<expect label="produces length equal to length of constructed
sequence"
test="f:length( $x:result ) = count( $x:result )" />
</scenario>
</scenario>
</description>