`f:set-args' setter and `f:args' accessor implemented
As operations on dynamic function references become more complex, and since evolution of the reference structure is planned to evolve, maintaining an abstraction is vital for both grokking and maintenance.master
parent
cd278c31d4
commit
18c1614777
|
@ -104,19 +104,24 @@
|
||||||
<!--
|
<!--
|
||||||
Retrieve the QName of the target dynamic function
|
Retrieve the QName of the target dynamic function
|
||||||
|
|
||||||
Usually, this would match precisely the QName of the target
|
Usually, this will match precisely the QName of the target
|
||||||
function.
|
function.
|
||||||
|
|
||||||
|
@var{fnreF} must be a valid dynamic function reference.
|
||||||
|
|
||||||
@i{Implementation details:} This actually represents the QName of
|
@i{Implementation details:} This actually represents the QName of
|
||||||
the @emph{application template}, which could differ from the target
|
the @emph{application template}, which could differ from the target
|
||||||
function name. One reason this may be the case is to provide a
|
function name. One reason this may be the case is to provide a
|
||||||
function alias.
|
function alias.
|
||||||
-->
|
-->
|
||||||
<function name="f:QName" as="xs:QName?">
|
<function name="f:QName" as="xs:QName?">
|
||||||
<param name="fnref" as="element( f:ref )" />
|
<param name="fnref" as="item()+" />
|
||||||
|
|
||||||
|
<variable name="desc" as="element( f:ref )"
|
||||||
|
select="$fnref[ 1 ]" />
|
||||||
|
|
||||||
<variable name="target" as="element()?"
|
<variable name="target" as="element()?"
|
||||||
select="$fnref/element()[ 1 ]" />
|
select="$desc/element()[ 1 ]" />
|
||||||
|
|
||||||
<sequence select="node-name( $target )" />
|
<sequence select="node-name( $target )" />
|
||||||
</function>
|
</function>
|
||||||
|
@ -143,4 +148,58 @@
|
||||||
<sequence select="$arity" />
|
<sequence select="$arity" />
|
||||||
</function>
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Retrieve a sequence of the partially applied arguments of
|
||||||
|
@var{fnref}
|
||||||
|
|
||||||
|
The resulting sequence may be empty. @var{fnref} is assumed to be a
|
||||||
|
valid dynamic function reference; you should verify that assumption
|
||||||
|
beforehand.
|
||||||
|
-->
|
||||||
|
<function name="f:args" as="item()*">
|
||||||
|
<param name="fnref" as="item()+" />
|
||||||
|
|
||||||
|
<sequence select="remove( $fnref, 1 )" />
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Set partially applied arguments of @var{fnref} to @var{args},
|
||||||
|
replacing any existing arguments
|
||||||
|
|
||||||
|
The arity of @var{fnref} will be adjusted relative to the number of
|
||||||
|
items in @var{args} such that the resulting dynamic function
|
||||||
|
reference has the illusion of being its own, new function:
|
||||||
|
increasing the argument count of @var{fnref} will @emph{decrease}
|
||||||
|
the arity of the resulting reference and vice versa.
|
||||||
|
|
||||||
|
@var{fnref} must be a valid dynamic function reference.
|
||||||
|
-->
|
||||||
|
<function name="f:set-args" as="item()+">
|
||||||
|
<param name="fnref" as="item()+" />
|
||||||
|
<param name="args" as="item()*" />
|
||||||
|
|
||||||
|
<variable name="desc" as="element( f:ref )"
|
||||||
|
select="$fnref[ 1 ]" />
|
||||||
|
|
||||||
|
<!-- this reference may be partially applied; see below arity
|
||||||
|
adjustment -->
|
||||||
|
<variable name="target-arity" as="xs:double"
|
||||||
|
select="$desc/@arity + count( f:args( $fnref ) )" />
|
||||||
|
|
||||||
|
<f:ref>
|
||||||
|
<sequence select="$desc/@*" />
|
||||||
|
|
||||||
|
<!-- treat partial applications as their own functions (with their
|
||||||
|
own arities) -->
|
||||||
|
<attribute name="arity"
|
||||||
|
select="$target-arity - count( $args )" />
|
||||||
|
|
||||||
|
<sequence select="$desc/*" />
|
||||||
|
</f:ref>
|
||||||
|
|
||||||
|
<sequence select="$args" />
|
||||||
|
</function>
|
||||||
|
|
||||||
</stylesheet>
|
</stylesheet>
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
select="f:make-ref( QName( $foo-uri, 'foo:bar' ),
|
select="f:make-ref( QName( $foo-uri, 'foo:bar' ),
|
||||||
$test-arity )" />
|
$test-arity )" />
|
||||||
|
|
||||||
|
<variable name="args">
|
||||||
|
<foo:args>
|
||||||
|
<foo:a />
|
||||||
|
<foo:b />
|
||||||
|
<foo:c />
|
||||||
|
</foo:args>
|
||||||
|
</variable>
|
||||||
|
|
||||||
|
|
||||||
<scenario label="f:make-ref constructor">
|
<scenario label="f:make-ref constructor">
|
||||||
<scenario label="when called with a function QName and arity">
|
<scenario label="when called with a function QName and arity">
|
||||||
|
@ -169,10 +177,11 @@
|
||||||
|
|
||||||
|
|
||||||
<scenario label="f:QName accessor">
|
<scenario label="f:QName accessor">
|
||||||
<scenario label="given a valid dynamic function reference">
|
|
||||||
<variable name="foo-qname"
|
<variable name="foo-qname"
|
||||||
select="QName( $foo-uri, 'foo' )" />
|
select="QName( $foo-uri, 'foo' )" />
|
||||||
|
|
||||||
|
<scenario label="given a valid dynamic function reference with no
|
||||||
|
argments">
|
||||||
<call function="f:QName">
|
<call function="f:QName">
|
||||||
<param name="fnref"
|
<param name="fnref"
|
||||||
select="f:make-ref( $foo-qname, 0 )" />
|
select="f:make-ref( $foo-qname, 0 )" />
|
||||||
|
@ -186,6 +195,22 @@
|
||||||
</scenario>
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="given a valid dynamic function reference with
|
||||||
|
argments">
|
||||||
|
<call function="f:QName">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args( f:make-ref( $foo-qname, 0 ),
|
||||||
|
(1, 2) )" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="returns QName"
|
||||||
|
test="$x:result instance of xs:QName" />
|
||||||
|
|
||||||
|
<expect label="returns QName of target dynamic function"
|
||||||
|
select="$foo-qname" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
<scenario label="given a dynamic function reference with no target
|
<scenario label="given a dynamic function reference with no target
|
||||||
node">
|
node">
|
||||||
<call function="f:QName">
|
<call function="f:QName">
|
||||||
|
@ -241,4 +266,134 @@
|
||||||
select="$test-arity - 3" />
|
select="$test-arity - 3" />
|
||||||
</scenario>
|
</scenario>
|
||||||
</scenario>
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="f:set-args setter">
|
||||||
|
<scenario label="setting empty args on reference with no args">
|
||||||
|
<call function="f:set-args">
|
||||||
|
<param name="fnref" select="$test-fn" />
|
||||||
|
<param name="args" select="()" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="retains target QName"
|
||||||
|
test="f:QName( $x:result ) = f:QName( $test-fn )" />
|
||||||
|
|
||||||
|
<expect label="retains target arity"
|
||||||
|
test="f:arity( $x:result ) = f:arity( $test-fn )" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="setting args on reference with no args">
|
||||||
|
<call function="f:set-args">
|
||||||
|
<param name="fnref" select="$test-fn" />
|
||||||
|
<param name="args" select="(1, 2)" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="retains target QName"
|
||||||
|
test="f:QName( $x:result ) = f:QName( $test-fn )" />
|
||||||
|
|
||||||
|
<!-- the function is now partially applied -->
|
||||||
|
<expect label="reduces arity by number of arguments"
|
||||||
|
test="f:arity( $x:result ) = f:arity( $test-fn ) - 2" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="clearing args on reference with args">
|
||||||
|
<call function="f:set-args">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args( $test-fn, (1, 2) )" />
|
||||||
|
<param name="args"
|
||||||
|
select="()" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="retains target QName"
|
||||||
|
test="f:QName( $x:result ) = f:QName( $test-fn )" />
|
||||||
|
|
||||||
|
<!-- the function is no longer partially applied -->
|
||||||
|
<expect label="restores target function arity"
|
||||||
|
test="f:arity( $x:result ) = f:arity( $test-fn )" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="increasing reference argument count">
|
||||||
|
<call function="f:set-args">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args( $test-fn, (1, 2) )" />
|
||||||
|
<param name="args"
|
||||||
|
select="(1, 2, 3)" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="retains target QName"
|
||||||
|
test="f:QName( $x:result ) = f:QName( $test-fn )" />
|
||||||
|
|
||||||
|
<!-- 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" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="decrasing reference argument count">
|
||||||
|
<call function="f:set-args">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args( $test-fn, (1, 2) )" />
|
||||||
|
<param name="args"
|
||||||
|
select="1" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="retains target QName"
|
||||||
|
test="f:QName( $x:result ) = f:QName( $test-fn )" />
|
||||||
|
|
||||||
|
<!-- 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" />
|
||||||
|
</scenario>
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="f:args accessor">
|
||||||
|
<scenario label="given a new dynamic function reference">
|
||||||
|
<call function="f:args">
|
||||||
|
<param name="fnref" select="$test-fn" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="produces empty argument list"
|
||||||
|
select="()" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="after an initial f:set-args">
|
||||||
|
<call function="f:args">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args( $test-fn, ($args/foo:a,
|
||||||
|
$args/foo:b) )" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="returns sequence of arguments by reference"
|
||||||
|
test="$x:result[ 1 ] is $args/foo:a
|
||||||
|
and $x:result[ 2 ] is $args/foo:b" />
|
||||||
|
|
||||||
|
<expect label="returns no other items"
|
||||||
|
test="count( $x:result ) = 2" />
|
||||||
|
</scenario>
|
||||||
|
|
||||||
|
|
||||||
|
<scenario label="after a f:set-args on an existing argument list">
|
||||||
|
<call function="f:args">
|
||||||
|
<param name="fnref"
|
||||||
|
select="f:set-args(
|
||||||
|
f:set-args( $test-fn, ($args/foo:a,
|
||||||
|
$args/foo:b) ),
|
||||||
|
($args/foo:b,
|
||||||
|
$args/foo:c) )" />
|
||||||
|
</call>
|
||||||
|
|
||||||
|
<expect label="returns sequence of arguments by reference,
|
||||||
|
discarding previously set arguments"
|
||||||
|
test="$x:result[ 1 ] is $args/foo:b
|
||||||
|
and $x:result[ 2 ] is $args/foo:c" />
|
||||||
|
|
||||||
|
<expect label="returns no other items"
|
||||||
|
test="count( $x:result ) = 2" />
|
||||||
|
</scenario>
|
||||||
|
</scenario>
|
||||||
</description>
|
</description>
|
||||||
|
|
Loading…
Reference in New Issue