Re: A (hopefully comprehensive) versioning proposal

"Toman_Vojtech@emc.com" <Toman_Vojtech@emc.com> writes:
>> ============================================================
>> 
>> Proposal 1: Add a version attribute.
>> 
>> The version attribute is allowed on any element. On an element in the
>> XProc namespace, it is "version" in no namespace. On an element not in
>> the XProc namespace, it is "p:version" in the XProc namespace.
>
> Are you suggesting we could use p:version on, for instance, c:data,
> c:directory or c:request?
> I can probably see what you were aiming at (we may decide to add new
> elements to the c:request model in Vnext), but I don't really see how
> this can work in practice. It seems to me you would have to add some
> intelligence to steps that consume (and probably produce?) documents in
> the xproc-step namespace, so that they can filter them based on
> p:version.
>
> Personally, I wouldn't support "p:version" on non-XProc elements. I
> would just say that you have to use "p:use-when" in this case.

Fair enough. In that case, I propose that it's only allowed on
p:library, p:pipeline, and p:declare-step.

>> ============================================================
>>
>> Proposal 2: The version attribute is required on top-level
>> p:pipeline, p:declare-step, and p:library elements.
>
> +1 from me. Just a question: At the moment, we allow explicitly
> importing a standard XProc library using p:import. With the "version"
> attribute, shouldn't we make this forbidden? Because with the "version"
> attribute and the defaulting rules, the processor would always know what
> to do.

I'm not sure. We could forbid it. Yes, maybe that's the simplest thing
to do.

>> ============================================================
>> 
>> Proposal 3: Add a use-when attribute
>> 
>> The use-when attribute is allowed on any element. On an element in the
>> XProc namespace, it is "use-when" in no namespace. On an 
>> element not in
>> the XProc namespace, it is "p:use-when" in the XProc namespace.
>
> +1
>
> So, if you wan't to preserve p:use-when elements in your XML documents,
> you would either have to escape/unescape the documents (p:escape-markup,
> p:unescape-markup), or make them external, right?

You mean in documents inside p:inline, yes? I don't think they come
into play anywhere else. We could say that p:use-when processing is
suspended within p:inline elements. On reflection, I think we probably
should.

>> ============================================================
>> 
>> Proposal 3: Attempt to treate unknown XProc step types as 
>> dynamic errors
>> 
>> Pipelines that attempt to unconditionally evaluate unknown step types
>> are guaranteed to fail. It's possible that some new XProc steps may
>> have attributes or children that a previous processor could not be
>> expected to interpret.
>> 
>> In order to minimize the disruption such elements cause, while at the
>> same time making it as easy as possible to write pipelines that will
>> run in fowards-compatible mode on an earlier processor, we adopt the
>> following rules:
>> 
>> In forwards-compatible mode:
>> 
>> Steps in the XProc namespace which the processor does not recognize
>> are marked invalid. It is a dynamic error (err:XD00??) to attempt to
>> evaluate a step that is marked invalid.
>> 
>> Any subpipeline that directly contains a step which has been marked
>> invalid is also invalid.
>> 
>> If a p:when directly contains an unknown XProc step type, that entire
>> branch is marked invalid. No static analysis is performed on the steps
>> within that pipeline. It is a dynamic error (err:XD00??) if that
>> branch of the p:choose is selected at runtime.
>
> I think you *MUST* statically check the pipe bindings in the branch; not
> doing so may break the dependency graph. The steps in the when- or
> otherwise- branch may contain dependencies on steps outside p:choose,
> and not statically checking the branch may result in the p:choose being
> executed before the steps it actually depends on!

I don't think so. Only the invalid branch is being ignored. And you
can't ever run that branch so it can't matter as far as the order goes.

Consider:

  <p:choose name="choice">
    <p:when test="some-condition">
      <p:fribble>
        <p:input port="purple">
          <p:pipe step="ident" port="result"/>
        </p:input>
      </p:fribble>
    </p:when>
    <p:otherwise>
      <p:identity>
        <p:input port="source">
          <p:inline><doc/></p:inline>
        </p:input>
      </p:identity>
    </p:otherwise>
  </p:choose>

  <p:identity name="ident">
    <p:input port="source">
      <p:inline><doc/></p:inline>
    </p:input>
  </p:identity>

If you understood the fribble step, then you'd always run "ident" first.
Since you don't understand the fribble step, you might not. Suppose
you don't:

  - If some-condition is true, then the pipeline fails and it doesn't matter.
  - If some-condition is false, then you executed the branch that didn't use
    the dependency and it doesn't matter.

I suppose you might occasionally run pipelines that a V2.0 processor
would assert contain loops, but since you can never run the "looping"
path, I don't think it matters.

I don't see how a processor *can* do the dependency analysis in a pipeline
that contains a step it doesn't understand. It certainly can't be guaranteed
to build the *correct* graph, so why build one at all?

>> If a p:group inside a p:try directly contains an unknown XProc step
>> type, that group is marked invalid. No static analysis is performed on
>> the steps within that group. An attempt to evaluate the p:try will
>> immediately evaluate the p:catch with an empty errors port.
>
> Again, I think the same as with p:choose applies here and you MUST do
> some sort of static analysis in p:group in p:try and p:catch.

I'll wait and see if I've convinced you otherwise above :-)

>> If all of the branches of a p:choose or p:try are invalid, the
>> p:choose or p:try is treated as if it had no primary output port.
>
> Why?

So that if it's the last step in a subpipeline, you can't wind up with
a default binding. The alternative is to say that it is treated as if
it did have a primary output port, which would also be an error
sometimes. It's irrelevant which choice we make, but I think we have
to make one.

>> ============================================================
>> 
>> Proposal 4: Support binding defaults in forwards-compatible mode
>> 
>> In forwards-compatible mode:
>> 
>> It is not a static error to encounter an unknown XProc step type. Such
>> steps are assumed to have no primary input ports, no primary output
>> ports, and no parameter input ports. It is a static error if, under
>> these assumptions, a valid dependency graph cannot be constructed.
>> 
>> It is not a static error to encounter explicit bindings to unknown
>> ports on an XProc step type. Such bindings are assumed to be correct.
>> Dynamically, a step must ignore all inputs that appear on an unknown
>> input port and must produce an empty sequence of documents on unknown
>> output ports.
>
> +1
>
>> ============================================================
>
>> E. Dynamic errors 1
>> 
>> The following pipeline is statically valid to an XProc 1.0 processor
>> and will run without errors.
>> 
>>   <p:pipeline version="2.0">
>> 
>>     <p:choose>
>>       <p:when test="system-property('p:version') &gt; 1.0">
>>         <p:fribble/>
>>         <p:sink/>
>>       </p:when>
>>       <p:otherwise>
>>         <p:identity/>
>>       </p:otherwise>
>>     </p:choose>
>> 
>>   </pipeline>
>
>> 
>> The first p:when branch is marked invalid because it contains the
>> unknown (from the 1.0 perspective) step p:fribble. As a result, no
>> static analysis is performed on that subpipeline
>
> Again, I think you have to check the pipe bindings in the branch

Again, I'll see if I've convinced you otherwise :-)

>> and that subpipeline
>> does not contribute to the constraint that all the branches of a
>> p:choose must declare the same outputs.
>
> Hmm. Even if the when branch explicitly declared the outputs, or if the
> last step of the subpipeline is a known step?

If there are other branches that don't contain unknown steps, then they 
all have to be consistent and if one of them runs, the right thing will
happen. If the branch that contains the invalid step runs, the pipeline
will fail, so it doesn't matter.

This comes back to my earlier point that I don't think the processor
*can know* what the outputs are for a subpipeline that contains a step
it doesn't understand.

(If all the bindings are explicit, it can, but it can't know what the
implicit bindings should be, so in general it can't know.)

>> K. Static errors 2
>> 
>> This pipeline is statically *in*valid:
>> 
>>   <p:pipeline version="2.0">
>>     <p:choose>
>>       <p:when test="system-property('p:version') &gt; 1.0">
>>         <p:unknown/>
>>       </p:when>
>>       <p:otherwise>
>>         <p:unknown/>
>>       </p:otherwise>
>>     </p:choose>
>>   </p:pipeline>
>> 
>> There's nothing for the p:output on the p:pipeline to bind to by
>> default.
>
> Because all branches of p:choose are invalid and they don't participate
> in the test that all branches have the same output signature - and
> therefore the p:choose has no output ports, right?

Right.

>> I haven't attempted to propose what a 1.0 processor should do if the
>> 2.0 step declarations are loaded and they differ from what it expected
>> in 1.0.
>
> I mentioned that earlier, but is there still any point in supporting
> importing standard XProc step declarations if we introduce the required
> "version" attribute?

I think not. Good catch.

                                        Be seeing you,
                                          norm

-- 
Norman Walsh <ndw@nwalsh.com> | If man were never to fade away like the
http://nwalsh.com/            | dews of Adashino, never to vanish like
                              | the smoke over Toribeyama, but lingered
                              | on forever in the world, how things
                              | would lose their power to move us! The
                              | most precious thing in life is its
                              | uncertainty.--Yoshida Kenko

Received on Friday, 16 October 2009 18:00:33 UTC