<?xml version="1.0" encoding="UTF-8"?>
<consistencyruleset
  xmlns="http://www.xlinkit.com/ConsistencyRuleSet/5.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:meta="http://www.xlinkit.com/Metadata/5.0"
  xmlns:macro="http://www.xlinkit.com/Macro/5.0"
  xsi:schemaLocation="http://www.xlinkit.com/ConsistencyRuleSet/5.0 consistencyrule.xsd">


  <consistencyrule id="ruleRequisiteParamsAreIn">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        All nonlocal parameters of pre- and post-requisites must be IN, not
        OUT or IN/OUT.
      </description>

      <meta:msg mode="error"/>
      <meta:operand seq="1" title="Requisite"/>
      <meta:operand seq="2" title="Step"/>
      <meta:operand seq="3" title="Parameter Decl"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>
    
    <forall var="r" in="//prerequisite | //postrequisite">
      <exists var="s" in="//step[@id = $r/@target]">
        <forall var="p" in="$s/interface/parameter-decl">
          <or>
            <equal op1="$p/@mode" op2="'in'"/>
            <equal op1="$p/@mode" op2="'local'"/>
          </or>
        </forall>
      </exists>
    </forall>
    
  </consistencyrule>

  

  <consistencyrule id="ruleParamBindingsSatisfied">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description> 
        Every parameter of a substep, reaction, requisite, or handler
        binding must be bound.
      </description>

      <meta:msg mode="error"/>
      <meta:operand seq="1" title="Parent Step"/>
      <meta:operand seq="2" title="Incomplete binding"/>
      <meta:operand seq="3" title="Unbound Parameter"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>
    
    <forall var="parentstep" in="//step">  <!-- for each parent P -->
      <and> <!-- we have to handle handlers differently, since they have
                 different structure... sigh -->

        <!-- for each substep/reaction/requisite[/handler] binding -->
        <forall var="bind" 
          in="$parentstep/substeps/substep-binding |
              $parentstep/reactions/reaction-binding |
              $parentstep/prerequisite | 
              $parentstep/postrequisite">
          
          <!-- for each of that substep's params -->
          <forall var="subparam" 
            in="id($bind/@target)/interface/parameter-decl">
            
            <implies>
              <!-- if nonlocal -->
              <notequal op1="$subparam/@mode" op2="'local'"/>
              
              <!-- then the parent step has a binding for that param -->
              <exists var="pbind" 
                in="$bind/parameter-binding">
                
                <equal op1="$subparam/@id" op2="$pbind/@in-child"/>
              </exists>
              
            </implies>
          </forall>
        </forall>
        
        <!-- for each handler step (a handler-binding may or may not contain a
             handler-step element -->
        <forall var="hstep" 
          in="$parentstep/handlers/handler-binding/handler-step">
          
          <!-- for each of that handler-step's params -->
          <forall var="subparam" 
            in="id($hstep/@target)/interface/parameter-decl">
            <implies>
              <!-- if nonlocal -->
              <notequal op1="$subparam/@mode" op2="'local'"/>
              
              <!-- then the handler binding binds that param -->
              <exists var="pbind" 
                in="$hstep/../parameter-binding">
                
                <equal op1="$subparam/@id" op2="$pbind/@in-child"/>
              </exists>
              
            </implies>
          </forall>
        </forall>
      </and>
      
    </forall>
  </consistencyrule>
        


  <consistencyrule id="warnNonLeafNoChildren">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Non-leaf step with no substeps: very strange.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Step"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>
    
    <forall var="s" in="//step[@kind != 'leaf']">
      <exists var="sub" in="$s/substeps/substep-binding"/>
      <!-- we only care that it exists; truth condition is implicit -->
    </forall>
    
  </consistencyrule>



  <consistencyrule id="warnDiagramsConnected">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Step unreachable from diagram root.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Diagram"/>
      <meta:operand seq="2" title="Unreachable"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>


    <forall var="d" in="//diagram">
      <forall var="s" in="$d/step">

        <exists var="c"
          in="closure(id($d/@root),
                      id(prerequisite/@target) |
                      id(postrequisite/@target) |
                      id(substeps/substep-binding/@target) |
                      id(reactions/reaction-binding/@target) |
                      id(handlers/handler-binding/handler-step/@target)
                     ) 
              | id($d/@root)">
          <same op1="$s" op2="$c"/>
        </exists>
      </forall>
    </forall>
    
  </consistencyrule>



  <consistencyrule id="ruleRootHasAgent">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Root step must have an agent.
      </description>

      <meta:msg mode="error"/>
      <meta:operand seq="1" title="Program"/>
      <meta:operand seq="2" title="Agent interface declaration"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="p" in="/program"> <!-- consistency rules must begin with
      forall -->
      <!-- get root step from root diagram, check there -->
      <exists var="i" in="id(id($p/@root)/@root)/interface/resource-decl/interface-decl[@name = 'agent']"/>
    </forall>
    
  </consistencyrule>




  <consistencyrule id="warnExceptionsCaught">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Parent step does not handle nor declare exception thrown by substep,
        requisite, reaction, or handler.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Exception declaration"/>
      <meta:operand seq="2" title="Step throwing exception"/>
      <meta:operand seq="3" title="Parent step"/>
      <meta:operand seq="4" title="Handler trigger"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="e" in="/program/diagram/step/interface/exception-decl">
      <forall var="s" in="$e/../.."> <!-- this must exist, just listed for
                                          output information -->

        <!-- this must be "forall" to cover every possible parent -->
        <forall var="parent" 
          in="//substep-binding[@target = $e/../../@id]/../.. |
              //prerequisite[@target = $e/../../@id]/.. |
              //postrequisite[@target = $e/../../@id]/.. |
              //reaction-binding[@target = $e/../../@id]/../.. |
              //handler-binding/handler-step[@target = $e/../../@id]/../../..
          ">

          <or>

            <!-- parent has handler -->
            <exists var="t" in="$parent/handlers/handler-binding/trigger">
              <equal op1="$e/@type" op2="$t/@type"/>
            </exists>

            <!-- or parent declares exception -->
            <exists var="t" 
              in="$parent/interface/exception-decl[@type = $e/@type]">
            </exists>

          </or>
          
        </forall>

        <!-- Turns out, we actually don't need the transitive closure;
             each step must either handle or declare that it throws the
             exceptions which may be thrown by its substeps.  But I spent a
             long time trying to figure out how to do this, so here it is,
             for posterity.

        <forall var="parent" 
          in="//substep-binding[@target = $e/../../@id]/../.. |
              closure(//substep-binding[@target = $e/../../@id]/../..,
                      //substep-binding[@target = current()/../../@id])
          ">

          <exists var="t" in="$parent/handlers/handler-binding/trigger">
            <equal op1="$e/@type" op2="$t/@type"/>
          </exists>
          
        </forall>
        -->

      </forall>
    </forall>    
  </consistencyrule>



  <consistencyrule id="warnExtraHandlers">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Step has handler for an exception which is not thrown by any of its
        substeps, requisites, reactions, or handlers.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Handler binding trigger"/>
      <meta:operand seq="2" title="Step with handler"/>
      <meta:operand seq="3" title="Child step"/>
      <meta:operand seq="4" title="Child step exception"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="t" 
      in="/program/diagram/step/handlers/handler-binding/trigger">
      <forall var="s" in="$t/../../.."> <!-- this must exist, just listed for
                                             output information -->

        <exists var="childstep"
          in="id($s/substeps/substep-binding/@target) |
              id($s/prerequisite/@target) |
              id($s/postrequisite/@target) |
              id($s/reactions/reaction-binding/@target) |
              id($s/handlers/handler-binding/handler-step/@target)
          ">
          
          <exists var="childex" in="$childstep/interface/exception-decl">
            <equal op1="$t/@type" op2="$childex/@type"/>
          </exists>

        </exists>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnNonLeafThrowsNew">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Non-leaf step throws exception which is not thrown by any of its
        substeps, requisites, reactions, or handlers.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="New exception declaration"/>
      <meta:operand seq="2" title="Non-leaf step throwing this exception"/>
      <meta:operand seq="3" title="Propagating from"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="t" 
      in="//step[@kind != 'leaf']/interface/exception-decl">
      <forall var="s" in="$t/../.."> <!-- this must exist, just listed for
                                             output information -->

        <exists var="childstep"
          in="id($s/substeps/substep-binding/@target) |
              id($s/prerequisite/@target) |
              id($s/postrequisite/@target) |
              id($s/reactions/reaction-binding/@target) |
              id($s/handlers/handler-binding/handler-step/@target)
          ">
          
          <exists var="childex" in="$childstep/interface/exception-decl">
            <equal op1="$t/@type" op2="$childex/@type"/>
          </exists>

        </exists>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnParallelRace">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Race condition: multiple substeps of parallel-sequenced step
        accessing a parameter which is written to.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Parallel step"/>
      <meta:operand seq="2" title="Parameter binding 1"/>
      <meta:operand seq="3" title="Parameter binding 2"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind = 'parallel']">
      <forall var="pa" in="$s/substeps/substep-binding/parameter-binding
        [@mode != 'copy-in']"> <!-- if there is one writer, there can be no 
        other readers or writers -->
        <forall var="pb" in="$s/substeps/substep-binding/parameter-binding">
          
          <implies>
            <equal op1="$pa/@in-parent" op2="$pb/@in-parent"/>
            <same op1="$pa" op2="$pb"/>
          </implies>
          
        </forall>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnNullInParam">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Value of parameter used in an IN or IN/OUT parameter binding has no
        static initializer, is not passed in from a parent, and is not bound
        to an out parameter of a previous substep.
      </description>

      <!-- Note: this rule simply looks for the word "null" in the
      <external-object> element of a part of the interface.  It may give off
      false alarms, since the content of this element is simply a toString()
      of the object in question. -->

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="In/in-out binding"/>
      <meta:operand seq="2" title="Null external-object value"/>
      <meta:operand seq="3" title="Step containing uninitialized parameter"/>
      <meta:operand seq="4" title="Parent binding missing initializer"/>
      <meta:operand seq="5" title="Parent binding missing initializer"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="bind" 
      in="/program/diagram/step/substeps/substep-binding/parameter-binding
      [@mode = 'copy-in' or @mode = 'copy-in-and-out']">

      <forall var="nullparent"
        in="id($bind/@in-parent)/external-object[contains(normalize-space(),'null')]">
        <!-- we want to make sure this will be initialized by a preceding
        substep -->

        <!-- for output & rule readability: step containing null param -->
        <forall var="s" in="$nullparent/../../.."> 

          <or> <!-- it is passed in from all parents -->

            <and> <!-- we have to make sure there actually *is* a parent -->

              <exists var="parent" 
                in="//substep-binding[@target = $s/@id] |
                    //reaction-binding[@target = $s/@id] |
                    //handler-binding[handler-step/@target = $s/@id]
                "/>
              <forall var="parent" 
                in="//substep-binding[@target = $s/@id] |
                    //reaction-binding[@target = $s/@id] |
                    //handler-binding[handler-step/@target = $s/@id]
                ">

                <exists var="init"
                  in="$parent/parameter-binding
                  [@in-child = $bind/@in-parent and 
                  @mode = 'copy-in' or
                  @mode = 'copy-in-and-out'
                  ]"/>

              </forall>

            </and>

          <!-- OR it must be sequential and initialization must occur
               previously -->
          <and>

            <equal op1="$s/@kind" op2="'sequential'"/>

            <!-- we need to look at a parameter binding in a previous step. -->
            <exists var="init"
              in="$bind/../preceding-sibling::substep-binding/parameter-binding
              [@in-parent = $bind/@in-parent and 
              @mode = 'copy-out']"/>

          </and>

          </or>

        </forall>

      </forall>

    </forall>

  </consistencyrule>

  <consistencyrule id="warnNullInParamHandler">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Value of parameter used in an IN or IN/OUT parameter binding with a
        handler step has no static initializer, is not passed in from a
        parent, and is not bound to an out parameter of a substep which will
        be executed before one throwing the exception being handled.
      </description>

      <!-- Note: this rule simply looks for the word "null" in the
      <external-object> element of a part of the interface.  It may give off
      false alarms, since the content of this element is simply a toString()
      of the object in question. -->

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="In/in-out binding"/>
      <meta:operand seq="2" title="Null external-object value"/>
      <meta:operand seq="3" title="Step containing uninitialized parameter"/>
      <meta:operand seq="4" title="Parent binding missing initializer"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="bind" 
      in="/program/diagram/step/handlers/handler-binding/parameter-binding
      [@mode = 'copy-in' or @mode = 'copy-in-and-out']">

      <forall var="nullparent"
        in="id($bind/@in-parent)/external-object[contains(normalize-space(),'null')]">
        <!-- we want to make sure this will be initialized by a preceding
        substep; that is, before one which may trigger the handler -->

        <!-- for output & rule readability: step containing null param -->
        <forall var="s" in="$nullparent/../../.."> 

          <or> <!-- it is passed in from all parents -->

            <and> <!-- we have to make sure there actually *is* a parent -->

              <exists var="parent" 
                in="//substep-binding[@target = $s/@id] |
                    //reaction-binding[@target = $s/@id] |
                    //handler-binding[handler-step/@target = $s/@id]
                "/>

              <forall var="parent" 
                in="//substep-binding[@target = $s/@id] |
                    //reaction-binding[@target = $s/@id] |
                    //handler-binding[handler-step/@target = $s/@id]
                ">

                <exists var="init"
                  in="$parent/parameter-binding
                  [@in-child = $bind/@in-parent and 
                  @mode = 'copy-in' or
                  @mode = 'copy-in-and-out'
                  ]"/>

              </forall>
              
            </and>

          <!-- OR it must be sequential and initialization must occur
            previously; that is, before the handler is triggered -->
            <and>
              
              <equal op1="$s/@kind" op2="'sequential'"/>
              
              <!-- forall substeps which could trigger the handler... -->
              <forall var="canTrigger" 
                in="$bind/../../../substeps/substep-binding
                    [id(@target)/interface/exception-decl/@type = 
                    $bind/../trigger/@type]">
                
                <!-- ...a preceding step must initialize the parameter. -->
                <exists var="init"
                  in="$canTrigger/preceding-sibling::substep-binding/
                      parameter-binding[@in-parent = $bind/@in-parent and 
                                        @mode = 'copy-out']"/>
              </forall>
              
            </and>

          </or>
          
        </forall>

      </forall>
      
    </forall>
    
  </consistencyrule>


  <consistencyrule id="warnInterfaceNameRepeated">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Multiple interface items (in same step) with same name.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Step"/>
      <meta:operand seq="2" title="Item"/>
      <meta:operand seq="3" title="Item"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
      <eliminatesymmetry status="on"/>
    </linkgeneration>

    <forall var="s" in="//step">
      <forall var="ia" in="$s/interface//*[@name]">
        <forall var="ib" in="$s/interface//*[@name]">
          <implies>
            <equal op1="$ia/@name" op2="$ib/@name"/>
            <same op1="$ia" op2="$ib"/>
          </implies>
        </forall>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="ruleAgentResourceUse">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        If a step has a "resource use" named "agent", it must be bound in a
        parameter binding to its parent.
      </description>

      <meta:msg mode="error"/>
      <meta:operand seq="1" title="Resource Use"/>
      <meta:operand seq="2" title="Parent binding"/>
      <meta:operand seq="3" title="Parent step"/>
      <meta:operand seq="4" title="Agent parameter binding"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="ru" in="//resource-use[@name = 'agent']">
      <!-- in every parent -->
      <forall var="parentbinding" 
        in="//substep-binding[@target = $ru/../../@id] |
            //reaction-binding[@target = $ru/../../@id] |
            //handler-binding/handler-step[@target = $ru/../../@id]/..
        ">
        
        <!-- select the parent step just for kicks -->
        <forall var="parentstepdummy" in="$parentbinding/../..">

          <!-- there is a binding for the agent resource use" -->
          <exists var="agentBinding" 
            in="$parentbinding/parameter-binding[@in-child = $ru/@id]" />

        </forall>
      </forall>        
    </forall>

  </consistencyrule>


  <consistencyrule id="warnLeafStepWithNullLocal">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Leaf step has an uninitialized local variable.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Leaf step"/>
      <meta:operand seq="2" title="Local variable"/>
      <meta:operand seq="3" title="Static initializer"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind = 'leaf']">
      <forall var="par" in="$s/interface/parameter-decl[@mode = 'local']">
        <exists var="init" 
          in="$par/external-object[not(contains(normalize-space(),'null'))]"/>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnNonLeafParamNotBound">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Non-leaf step has a parameter or local that is never bound.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Step"/>
      <meta:operand seq="2" title="Unbound parameter"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind != 'leaf']">
      <forall var="par" in="$s/interface/parameter-decl">
        <exists var="bind" in="//parameter-binding[@in-parent = $par/@id or
                                                   @in-child = $par/@id]"/>
      </forall>
    </forall>

  </consistencyrule>



  <consistencyrule id="warnDeadlinesOnLeafsOnly">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Deadlines (indicated by parameter "deadline") only apply to leaf
        steps.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Non-leaf step"/>
      <meta:operand seq="2" title="Deadline parameter"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind != 'leaf']">
      <not>
        <exists var="p" 
          in="$s/interface/parameter-decl/interface-decl[@name =
              'deadline']"/>
      </not>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnTrySubstepsUnreachable">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Try step has unreachable substeps; a nonfinal substep does not throw
        any exceptions handled by the try step with continue semantics.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Try step"/>
      <meta:operand seq="2" title="Nonfinal completing substep"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind = 'try']">
      <forall var="child"
        in="id($s/substeps/substep-binding[position() != last()]/@target)">
        <exists var="exc" in="$child/interface/exception-decl">
          <exists var="handler" in="$s/handlers/handler-binding/trigger">
            <and>
              <equal op1="$handler/@type" op2="$exc/@type"/>
              <equal op1="$handler/../@mode" op2="'continue'"/>
            </and>
          </exists>
        </exists>
      </forall>
    </forall>

  </consistencyrule>


  <consistencyrule id="warnNonLeafLostOutParam">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Non-leaf step receives out parameter, but does not propogate to a
        parent, later substep, reaction, exception, or postrequisite.
      </description>

      <!-- 
      NOTE: this rule COULD just check that the parameter value is used in a
      copy-in or copy-in-and-out binding which is not the one where is gets
      set.  The other data flow rule would detect if the other use occurs
      before initialization.  HOWEVER, this will not catch the case that
      e.g. a local has a static initializer, is used in the first substep of
      a sequential step, gets a value from an out parameter in the second
      substep, and then that out value is never used.  Thus, to catch this
      esoteric case, this rule is much much more complex.
      -->

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Non-leaf Step"/>
      <meta:operand seq="2" title="Substep parameter binding"/>
      <meta:operand seq="3" title="Substep"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind != 'leaf']">

      <forall var="outParamBinding" 
        in="$s/substeps/substep-binding/parameter-binding[@mode = 'copy-out'
          or @mode = 'copy-in-and-out']">

        <forall var="substep" in="id($outParamBinding/../@target)">

        <or>
          <or>
            <!-- used in later step -->
            <and>
              <or>
                <equal op1="$s/@kind" op2="'sequential'"/>
                <equal op1="$s/@kind" op2="'try'"/>
              </or>
              
              <exists var="usage"
                in="$outParamBinding/../following-sibling::substep-binding
                /parameter-binding[
                @in-parent = $outParamBinding/@in-parent and 
                @mode != 'copy-out']"/>
            </and>
            
            <!-- passed to parent -->
            <exists var="usage"
              in="//substep-binding[@target = $s/@id]
              /parameter-binding[@in-child = $outParamBinding/@in-parent
              and @mode != 'copy-in']"/>
          </or>
          <or>
            <!-- reaction, exception, or postreq -->
            <!-- for reactions we can't judge when they occur. -->
            <exists var="usage"
              in="$s/reactions/reaction-binding/parameter-binding
              [@in-parent = $outParamBinding/@in-parent
              and @mode != 'copy-out']"/>

            <or>
              <!-- for handlers, we could judge but it's too complex. -->
              <exists var="usage"
                in="$s/handlers/handler-binding/parameter-binding
                [@in-parent = $outParamBinding/@in-parent
                and @mode != 'copy-out']"/>
              
              <!-- postreqs of course always follow... simple! -->
              <exists var="usage"
                in="$s/postrequisite/parameter-binding
                [@in-parent = $outParamBinding/@in-parent
                and @mode != 'copy-out']"/>
            </or>
          </or>
        </or>
      </forall>
      </forall>
    </forall>

  </consistencyrule>

  <consistencyrule id="warnNonLeafNullOutParam">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Non-leaf step's out parameter is never set: it has no static
        initializer and is never bound.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Non-leaf Step"/>
      <meta:operand seq="2" title="Out Parameter"/>
      <meta:operand seq="3" title="?"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[@kind != 'leaf']">
      <!-- forall out params without a static initializer -->
      <forall var="outp" 
        in="$s/interface/parameter-decl[(@mode='out' or @mode='in-and-out')
        and external-object[contains(normalize-space(),'null')]
        ]">

        <!-- there is a binding -->
        <exists var="binding" 
          in="$s/substeps/substep-binding/parameter-binding
          |   $s/reactions/reaction-binding/parameter-binding
          |   $s/handlers/handler-binding/parameter-binding
          ">
          
          <equal op1="$outp/@id" op2="$binding/@in-parent"/>
          
        </exists>
        
      </forall>
    </forall>
  </consistencyrule>


  <consistencyrule id="warnUnreachableStepsInRecursion">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Unreachable substeps of a sequential step: recursive substep
        precedes other substeps and throws no exception handled by the
        parent with continue semantics.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Sequential step"/>
      <meta:operand seq="2" title="Recursive Substep Binding"/>
      <meta:operand seq="3" title="(repeat) Sequential step"/>
      <meta:operand seq="4" title="Exception Thrown"/>
      <meta:operand seq="5" title="Exception Handler"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>
    
    <forall var="root" in="//step[@kind = 'sequential']">

      <forall var="nonlastsubstep"
      in="id($root/substeps/substep-binding[position() != last()]/@target)">

        <implies> <!-- if this leads to recursion -->
          <exists var="reachableStep" in="
            closure($nonlastsubstep,
                    id(prerequisite/@target) |
                    id(postrequisite/@target) |
                    id(substeps/substep-binding/@target)
                    ) 
            | $nonlastsubstep">

            <same op1="$root" op2="$reachableStep"/>

          </exists>

          <!-- then there is an exception thrown & handled with continue -->
          <exists var="exc" in="$nonlastsubstep/interface/exception-decl">
            <exists var="handler" 
              in="$root/handlers/handler-binding[@mode = 'continue']/trigger">

              <equal op1="$handler/@type" op2="$exc/@type"/>

            </exists>
          </exists>

        </implies>

      </forall>
        
    </forall>

  </consistencyrule>



  <consistencyrule id="warnPreRequisiteLoop">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Prerequisite loop: step has itself as a prerequisite or
        prerequisite's[...] prerequisite, and thus will never execute.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Step"/>
      <meta:operand seq="2" title="(repeat)Step"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[prerequisite]"> <!-- any step w/a prereq -->

      <not>
        
        <exists var="prepre" in="id($s/prerequisite/@target) |
          closure(id($s/prerequisite/@target),
                  id(prerequisite/@target))">

          <same op1="$prepre" op2="$s"/>
        </exists>

      </not>

    </forall>

  </consistencyrule>


  <consistencyrule id="warnPostRequisiteLoop">

    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Postrequisite loop: step has itself as a postrequisite or
        postrequisite's[...] postrequisite, and thus will never complete.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Step"/>
      <meta:operand seq="2" title="(repeat)Step"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
    </linkgeneration>

    <forall var="s" in="//step[postrequisite]"> <!-- any step w/a postreq -->

      <not>
        
        <exists var="postpost" in="id($s/postrequisite/@target) |
          closure(id($s/postrequisite/@target),
                  id(postrequisite/@target))">

          <same op1="$postpost" op2="$s"/>
        </exists>

      </not>

    </forall>

  </consistencyrule>


  <consistencyrule id="warnInfiniteRecursion">
  
    <header>
      <author>Shimon Rura, shimon@rura.org</author>

      <description>
        Steps along a step's recursive cycle throw no exceptions
        and do no resource acquisitions, and the step has no rethrow or
        complete handlers.  Recursion may be infinite.
      </description>

      <meta:msg mode="warning"/>
      <meta:operand seq="1" title="Recursive step"/>
      <meta:operand seq="2" title="recursive path item"/>
    </header>

    <linkgeneration>
      <consistent status="off"/>
      <eliminatesymmetry status="off"/> <!-- this idea of symmetry is BS -->
    </linkgeneration>
    
    <!-- forall recursive sequential steps -->
    <forall var="root" in="//step[(@kind = 'sequential' or @kind = 'parallel') 
      and
      . = closure(., id(substeps/substep-binding/@target))]">

      <!-- if root is in its own substep-closure, then compute path -->
      
      <!-- the following actually computes the set of nodes on all
      recursive paths, and only includes nodes leading to recursion on
      $root.  This took me forever to figure out, but I'll be damned if it
      doesn't actually work!
      
      I would like to point out the nested closure.  That is awesome.

      And by awesome I mean totally sweet.
      -->
      <exists var="pathStep"
        in="closure($root,
        id(substeps/substep-binding[
         $root/@id = @target or
         $root = closure(id(@target), id(substeps/substep-binding/@target))
        ]/@target))">

        <or>
          <or> <!-- throws exception or does resource acquisition -->
            <exists var="ex" in="$pathStep/interface/exception-decl"/>
            <exists var="ra" in="$pathStep/interface/resource-decl"/>
          </or>

          <!-- or it's a parstep and one of it's children does! -->
          <and>

            <equal op1="$pathStep/@kind" op2="'parallel'"/>

            <or> <!-- a child throws exception or does resource acquisition -->
              <exists var="ex" 
                in="id($pathStep/substeps/substep-binding/@target)
                    /interface/exception-decl"/>
              <exists var="ra"
                in="id($pathStep/substeps/substep-binding/@target)
                    /interface/resource-decl"/>
            </or>

          </and>
        </or>
    
      </exists>

    </forall>
    
  </consistencyrule>
  
</consistencyruleset>
