Option inheritance

Hi all,

See below for a more detailed description of the "option inheritance"
proposal. It closely relates to parameters, but it is a more general idea.
It can be described as the "inheritance from above" approach.


Proposed changes
================

1. Support option/variable shadowing, i.e. allow the following:

   <p:pipeline>
    <p:option name="opt" select="'foo'"/>
    <!-- $opt is bound to 'foo' here -->
    ...
    <p:group>
      <p:variable name="opt" select="'bar'"/>
      <!-- $opt is bound to 'bar' here --> 
      ...
    </p:group>
    <!-- $opt is bound to 'foo' here -->
    ...
  </p:pipeline>

2. On p:option and p:variable, introduce an optional boolean attribute
   'autobind' (default true or false depending on whether we want autobinding by
   default, or not).

   Note: Initially, I proposed a new attribute called 'inherit' on
   p:option/p:variable. On further thought, I think it would be better to call
   it 'autobind' or something similar to avoid confusion with normal
   option/variable inheritance that already exists in XProc.

   The sole purpose of the new attribute is to allow automatic binding of
   unspecified options on the step level. One application of this feature is
   supporting a similar level of convenience/magic that XProc 1.0 provides with
   regard to parameters. But it is a general mechanism that applies to all types
   of step options.

3. During the static pipeline analysis phase, if the processor encounters a
   step with an unspecified option OPT, it will traverse (bottom up) the
   in-scope option/variable declarations with the name OPT until one of the
   following conditions hold:

   a) A declaration is found that specifies autobind='true' - in that case, the
   processor will bind the unspecified step option to this option/variable.

   b) A declaration is found that specifies autobind='false', or there are no
   more declarations left - in that case, the step option will remain
   unspecified. If the step option is required, you will get the usual static
   error err:XS0018.

Examples of 3a:

<p:pipeline>
  <p:option name='match' autobind='true' select='"foo"'/>
  <p:delete/>
</p:pipeline>

<p:pipeline>
  <p:option name='match' autobind='false' select='"foo"'/>
  <p:group>
    <!-- overrides both the value and the autobind flag of 'match' -->
    <p:variable name='match' autobind='true' select='"bar"'/>
    <p:delete/>
  </p:group>
</p:pipeline>

Examples of 3b:

<p:pipeline>
  <p:option name='match' autobind='true' select='"foo"'/>
  <p:group>
    <!-- disables autobinding of 'match' in this context;
         the invocation of p:delete will fail -->
    <p:variable name='match' autobind='false' select='"bar"'/>
    <p:delete/>
  </p:group>
</p:pipeline>

<p:pipeline>
  <!-- no in-scope option/variable with the name 'match';
       the invocation of p:delete will fail -->
  <p:delete/>
</p:pipeline>


To have more control over which autobinding of options/variables, we could
consider some of the following:

- Introduce some kind of enable-autobind/disable-autobind attributes on the
  compound step level (p:group, p:for, ...) that would take a sequence of
  option/variable names and that would enable/disable autobinding for the listed
  options/variables in the context of the compound step.

- Introduce p:variable with an optional select attribute. A p:variable without
  the select attribute would merely override the inherited autobind setting for
  that option/variable.


Type safety
===========

In XProc 1.0, the values of options are simple strings (or xs:untypedAtomic
instances). Once we move to supporting any XDM instance, we would have to have a
reasonable set of rules about what happens if you bind a step option to a value
of incompatible type. The autobinding mechanism would, of course, honor the same
rules.


Better support for unspecified optional options
===============================================

Autobinding could in help in some cases when dealing with unspecified optional
options, such as:

<p:pipeline>
  <p:option name="group-adjacent"/>

  ...
  <p:wrap-sequence wrapper="foo"/>
  ...
</p:pipeline>

The group-adjacent option of p:wrap-sequence is optional and with no default
value. With autobinding, the above pipeline would work both in the case when the
pipeline's group-adjacent option is set and in the case when it is not set. In
the latter case, the group-adjacent option of the p:wrap-sequence step will
remain unset. This is something not currently possible in XProc 1.0 where you
have to use p:with-option.


Application of autobinding to parameters
========================================

Suppose we model parameters as an XSLT 3.0 map. With the autobinding facility,
we could make the p:pipeline shortcut equivalent to:

<p:declare-step>
  <p:input port="source">
  <p:output port="result"/>
  <p:option name="parameters" autobind="true" type="map(*)"/>
  ...
</p:declare-step>

Suppose that the steps in the standard library use maps for parameters:

<p:declare-step type="p:xslt">
  <p:input port="source" sequence="true" primary="true"/>
  <p:input port="stylesheet"/>
  <p:output port="result" primary="true"/>
  <p:output port="secondary" sequence="true"/>
  <p:option name="parameters" type="map(*)"/>
  ...
</p:declare-step>

then this pipeline would work as expected:

<p:pipeline>
  <p:xslt/>
</p:pipeline>

because processor would automatically bind the unspecified option "parameters"
of the p:xslt step to the p:pipelines "parameters" option.

Things would get little complicated if you want to create a pipeline with an
p:xslt step and an p:xquery step, where each of these steps should use different
sets of parameters:

<p:declare-step>
  <p:option name="parameters" autobind="true" type="map(*)"/>
  <p:option name="parameters2" autobind="true" type="map(*)"/>

  <p:xslt/>
  ...
  <p:xquery/>
  ...
</p:declare-step>

As written, the above pipeline would bind  p:xslt and p:xquery to the same
"parameter" option of the containing p:declare-step. To make sure that, for
example, p:xquery uses "parameters2", you would have to provide an explicit
p:with-option binding on the p:xquery step.

But we have a similar situation with XProc 1.0, too, if you want to use two
parameter ports.


--
Vojtech Toman
Consultant Software Engineer
EMC | Information Intelligence Group
vojtech.toman@emc.com
http://developer.emc.com/xmltech

Received on Tuesday, 29 January 2013 12:49:28 UTC