This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 25679 - [XSLT 3.0] Streamable stylesheet functions
Summary: [XSLT 3.0] Streamable stylesheet functions
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Working drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-13 09:05 UTC by Michael Kay
Modified: 2015-10-29 09:50 UTC (History)
1 user (show)

See Also:


Attachments

Description Michael Kay 2014-05-13 09:05:41 UTC
This is to allocate an entry to the WG discussions on streamable stylesheet functions, resulting in development of a proposal which can be found in (member-only) email here:

https://lists.w3.org/Archives/Member/w3c-xsl-wg/2014May/0008.html

The essence of the proposal is to allow stylesheet functions under certain circumstances and conditions to be declared streamable and to be invoked from streamable templates.
Comment 1 Abel Braaksma 2014-06-04 12:38:35 UTC
-------------------
-- recap/summary --
-------------------

The essence of the proposal (1.e in 19.8.7.12) is that upon a call to a stylesheet function, the sweep is the wider sweep of the streaming argument and body of the function. 

A special exception (1.f) is made for recursive functions and non-final/private functions which are considered "non-analyzable", with either a striding or motionless argument, the result is striding and consuming.

---------------------------
-- motionless w/crawling --
---------------------------

This makes f:test(.//bar) with the following non-streamable:

<xsl:function name="f:exists" streamable="yes">
   <xsl:param name="n" />
   <xsl:value-of select="exists($n)" />
</xsl:function>

It fails because of rule 1.c, which disallows climbing/crawling arguments. I think we can resolve this by:
- moving 1.c down to between 1.f and 1.e (non-analyzable functions)
- under 1.e we add "if the body is motionless and grounded, then grounded and the larger sweep of the streaming argument and the body"
- under that we add "if the body is consuming and grounded and the streaming argument is not climbing, then grounded and the larger sweep of the streaming argument and the body"

----------------------
-- working examples --
----------------------

This works, because the posture of f:test() is the posture of the body of f:test, which means that also the following is streamable:

<xsl:function name="f:grandparent" streamable="yes">
   <xsl:param name="n" />
   <xsl:value-of select="$n/ancestor::*[2]/name()" />
</xsl:function>

This works. Under 19.8.7.10 the new rule says that param refs are always striding, but because path expressions that are crawling or string, then climbing are motionless and because we force the result of the body to be grounded, it is streamable and fits with existing rules.

Then this:

<xsl:function name="f:value" streamable="yes">
   <xsl:param name="n" />
   <xsl:value-of select="$n" />
</xsl:function>

would become consuming and grounded. Because we now allow crawling expressions to be consumed in atomizing expressions (bug 25185) and because higher order usage of the streaming argument is disallowed (19.8.7.10) this works for the general case.

For any non-grounded function body, I don't think we can widen the rules, and we should stick to the limitation of striding-in-striding-out.

----------------
-- Overriding --
----------------

The new rules effectively make it impossible to write an analyzable streamable function in a library package that is not final. You could argue that a non-final function can be overridden with a final signature, but that requires copying the whole body (which may be hidden to the package user), because reliance on the base function with a call on xsl:original() is not allowed (it violates rule 1.d "contains a call to a potential caller of F).

I think this is too strict and I think we can completely loose the restriction of non-final functions which makes the rules easier, allows abstract and non-final, yet analyzable functions, by adding one rule in 10.3.5 (Streamability of Stylesheet Functions):

- an overriding function must have the same sweep and posture as its overridden function

This rule might be better placed under "3.6.2.5 Overriding Components from a Used Package".

----------------
-- some typos --
----------------

19.8.7.12, 1.c: "the the"
19.8.7.10: "U{N} (see specref ref="determining-static-type")"
10.3.5: missing closing paren in the last paragraph before the examples
Comment 2 Michael Kay 2014-06-05 16:32:32 UTC
The typos have been dealt with - thanks.
Comment 3 Michael Kay 2014-07-31 14:06:37 UTC
The WG resolved as follows:

In 19.8.7.12

- move 1.c down to between 1.f and 1.e (non-analyzable functions)
- under 1.e we add "if the body is motionless and grounded, then grounded and the larger sweep 
of the streaming argument and the body"

Add one rule in 10.3.5 (Streamability of Stylesheet Functions):

- an overriding function must have the same sweep and posture as its overridden function

replacing the rule in 1.d that analyzable streamable functions must be final or private

(This rule might be better placed under "3.6.2.5 Overriding Components from a Used Package".)
Comment 4 Michael Kay 2014-08-04 17:14:36 UTC
For the revised definition of analyzable functions in 10.3.5 I think we need to add a rule that a function is a potential caller of F if it contains a dynamic function call.
Comment 5 Michael Kay 2014-08-04 19:52:24 UTC
Regarding comment 4, I don't think we need to treat dynamic function calls as potentially recursive after all, but I think we need to explain why. The posture and sweep of a dynamic function call depend on the type-determined usage of the arguments. If the dynamic function call is capable of passing streamed nodes without grounding them, then it will be deemed roaming/free-ranging and the calling function will therefore be deemed non-streamable anyway.
Comment 6 Abel Braaksma 2014-08-19 13:07:35 UTC
I think that is correct (comment#4 and comment#5). However, in solving the streamability for fn:fold-left et al, it would be a pity if you cannot use a named function reference to a streamable stylesheet function. Not quite sure how to move forward there.