<?xml version="1.0"?>
<!--
  Primitive calculation validation

  Copyright (C) 2014-2023 Ryan Specialty, LLC.

    This file is part of TAME.

    TAME is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see
    <http://www.gnu.org/licenses/>.

  Unfortunately, this is now of limited uses in its current form beacuse of
  the heavy use of templates in code written in TAME.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.lovullo.com/calc"
  xmlns="http://www.lovullo.com/calc"
  elementFormDefault="qualified">


<!--basicTypes-->
  <xs:simpleType name="nameType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Generic name reference restriction, intended to be generic enough to
        work with most systems (supporting both C-style and Lisp-style
        identifiers).

        The systems that implement this schema should perform their own, more
        strict, type checks.
      </xs:documentation>
    </xs:annotation>

    <!-- we need to allow '@' since that's used in macros -->
    <xs:restriction base="xs:string">
      <xs:pattern value="#[0-9]+|[a-zA-Z_@{-][a-zA-Z0-9_@{}-]*" />
      <xs:maxLength value="50" />
    </xs:restriction>
  </xs:simpleType>


  <xs:simpleType name="constValueType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Valid value for constants.
      </xs:documentation>
    </xs:annotation>

    <!-- we need to allow '@' since that's used in macros -->
    <xs:restriction base="xs:string">
      <xs:pattern value="-?[0-9]+(.[0-9]+)?[mek]?|\{?@[a-z][a-zA-Z0-9_]*@\}?" />
      <xs:maxLength value="50" />
    </xs:restriction>
  </xs:simpleType>


  <xs:simpleType name="descType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Documentation for a specific element.

        The documentation must not be sparse; please provide something
        descriptive that will be useful to someone completely new to the code.
      </xs:documentation>
    </xs:annotation>

    <xs:restriction base="xs:string">
      <xs:minLength value="2" />
    </xs:restriction>
  </xs:simpleType>


  <xs:simpleType name="indexNameType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Single-character index variable
      </xs:documentation>
    </xs:annotation>

    <xs:restriction base="xs:string">
      <xs:pattern value="[a-z]|\{?@[a-z][a-zA-Z0-9_]*@\}?" />
    </xs:restriction>
  </xs:simpleType>


  <xs:simpleType name="symbolType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Symbol used to represent an entity when rendered.

        The string should consist of TeX/LaTeX commands and should produce a
        single symbol.
      </xs:documentation>
    </xs:annotation>

    <xs:restriction base="xs:string" />
  </xs:simpleType>
<!--/basicTypes-->


<!--calculations-->
  <!--operators-->
    <xs:element name="operator" type="operatorBaseType" abstract="true">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Abstract operator type used to classify elements as operators.

          Operators are portions of the calculation that perform a portion of
          the calculation. For example, a summation would classify as an
          operation (operator), but value-of would not (as it is only
          representing a value, but not performing a calculation).
        </xs:documentation>
      </xs:annotation>
    </xs:element>


    <xs:complexType name="operatorBaseType" abstract="true">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Elements/attributes common to all operator types (see the operator
          element for a description on what qualifies as an operator).

          All operators may include child calculations. Furthermore, they may
          be labeled and may have an identifier associated with their result.
        </xs:documentation>
      </xs:annotation>

      <xs:sequence>
        <xs:element name="when" type="whenType" minOccurs="0" maxOccurs="unbounded" />
        <xs:group ref="calculation" minOccurs="0" maxOccurs="unbounded" />
        <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
      </xs:sequence>

      <xs:attribute name="yields" type="nameType">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Optional identifier with which the result of the calculation may be
            referenced.
          </xs:documentation>
        </xs:annotation>
      </xs:attribute>
      <xs:attribute name="label" type="xs:string">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Optional description of a calculation. @label is used in place of
            @desc to ensure that it is not confused with the otherwise required
            @desc attribute.
          </xs:documentation>
        </xs:annotation>
      </xs:attribute>
      <xs:attribute name="desc" type="xs:string">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            @desc should be used to describe a value that is generated by a
            calculation and should not otherwise be used (e.g. with
            lv:sum/@generate)

            This is different from @label, which provides a high-level
            description of what the equation is doing. @desc describes what the
            generated value is.
          </xs:documentation>
        </xs:annotation>
      </xs:attribute>
      <xs:attribute name="index" type="indexNameType">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Allows for the definition of an index variable which will be
            defined for all children of the operation.
          </xs:documentation>
        </xs:annotation>
      </xs:attribute>
    </xs:complexType>


    <xs:element name="sum" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Represents a summation (addition) of a set of values.

          If @of is used, the equation defined by child elements will be
          iterated using an index on the set provided by @of. If no equation is
          given, all elements in the set identified by @of will be summed.

          If @of is omitted, the result of each child element will be summed.

          This operator should also be used for subtraction by summing negative
          values.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:attribute name="of" type="nameType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Iterate over all values of this set. Must be a set.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="generates" type="nameType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Optional name of a set to generate from this expressions.

                  Generators are compatible only with @of and a sub-expression.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="sym" type="symbolType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Symbol to use when typesetting the generator
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="precision" type="constValueType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Yield precision
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="dim" type="xs:string">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Specify the dimension of each index of the generator result.
                  Disables casting and truncating with @precision if greater
                  than 0 or 'scaler'.  This expands into c:sum/@dim.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="product" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Represents the product (multiplication) of a set of values.

          If @of is used, the equation defined by child elements will be
          iterated using an index on the set provided by @of. If no equation is
          given, all elements in the set identified by @of will be multiplied.

          If @of is omitted, the result of each child element will be
          multiplied.

          While this operator may also be used for division by multiplying by
          the inverse of a number (n^-1), a limited quotient operator is
          provided for clarity and convenience.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:attribute name="of" type="nameType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Iterate over all values of this set. Must be a set.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="generates" type="nameType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Optional name of a set to generate from this expressions.

                  Generators are compatible only with @of and a sub-expression.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="sym" type="symbolType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Symbol to use when typesetting the generator
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="dot" type="xs:boolean">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Dot product of any number of vectors
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>

            <xs:attribute name="precision" type="constValueType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Yield precision
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="quotient" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Represents the quotient (division) of two values.

          This operator is to be thought of as a fraction: the numerator is
          identified by the first child element and the denominator the second.

          While the summation operator may also be used for division by
          multiplying by the inverse of a number (n^-1), this limited operator
          is provided for clarity and convenience.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType" />
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <!-- named after Scheme's expt; same arg order -->
    <xs:element name="expt" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Exponent; the first child node is the base, the second is the order.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType" />
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="cons" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Construct a list using the given element and an existing list

          This is analogous to lisp's cons; the first argument is the car and
          the second is the cdr.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:sequence>
              <!-- both car and cdr required -->
              <xs:group ref="calculation" minOccurs="2" maxOccurs="2" />
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="car" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Retrieve the first element of a list

          Analogous to lisp's car.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:sequence>
              <!-- we accept only a set -->
              <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="cdr" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Return the list without its first element

          If the list contains only one element, then an empty list will be
          returned. Analogous to lisp's cdr.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:sequence>
              <!-- we accept only a set -->
              <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="length-of" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Retrieves the length of a vector
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:sequence>
              <!-- we accept only a set -->
              <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <!--apply-->
      <xs:element name="apply" substitutionGroup="operator">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Denotes a function application.

            The result of the function identified by @name will be used in
            place of the call. The application may optionally accept an
            argument list (if the function accepts arguments).
          </xs:documentation>
        </xs:annotation>

        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="operatorBaseType">
              <xs:sequence>
                <xs:group ref="applyArgs" minOccurs="0" maxOccurs="unbounded" />
              </xs:sequence>

              <xs:attribute name="name" type="nameType" use="required">
                <xs:annotation>
                  <xs:documentation xml:lang="en">
                    Name of the function to apply
                  </xs:documentation>
                </xs:annotation>
              </xs:attribute>

              <!-- argument shorthand -->
              <xs:anyAttribute namespace="##any" processContents="lax" />
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>

      <xs:group name="applyArgs">
        <xs:choice>
          <xs:element name="arg" type="applyArgumentType" minOccurs="0" maxOccurs="unbounded" />
          <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
        </xs:choice>
      </xs:group>

      <xs:complexType name="applyArgumentType">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Represents an argument to be applied to a function.
          </xs:documentation>
        </xs:annotation>

        <xs:sequence>
          <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
        </xs:sequence>

        <xs:attribute name="name" type="nameType" use="required">
          <xs:annotation>
            <xs:documentation xml:lang="en">
              Name of the parameter to apply to the function
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
      </xs:complexType>


      <xs:element name="recurse" substitutionGroup="operator">
        <xs:annotation>
          <xs:documentation xml:lang="en">
            Recursively applies the current function.

            All arguments are copied to the argument list of the function application unless overridden.
          </xs:documentation>
        </xs:annotation>

        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="operatorBaseType">
              <xs:sequence>
                <xs:group ref="applyArgs" minOccurs="0" maxOccurs="unbounded" />
              </xs:sequence>

              <!-- argument shorthand -->
              <xs:anyAttribute namespace="##any" processContents="lax" />
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>
    <!--/apply-->


    <xs:element name="ceil" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Converts the given value to an integer, rounding up if necessary (e.g. 0.1 => 1)
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:attribute name="precision" type="constValueType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Value precision to consider for rounding.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <xs:element name="floor" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Converts the given value to an integer, rounding down if necessary (e.g. 0.9 => 0)
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType">
            <xs:attribute name="precision" type="constValueType">
              <xs:annotation>
                <xs:documentation xml:lang="en">
                  Value precision to consider for rounding.
                </xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>

    <xs:element name="set" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Creates a set out of its siblings (deprecated in favor of
          c:vector)
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType" />
        </xs:complexContent>
      </xs:complexType>
    </xs:element>

    <xs:element name="vector" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Creates a vector out of its siblings
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType" />
        </xs:complexContent>
      </xs:complexType>
    </xs:element>


    <!--
      Debug
    -->
    <xs:element name="debug-to-console" substitutionGroup="operator">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Outputs the result of the contained expression to the console and
          returns its value.
        </xs:documentation>
      </xs:annotation>

      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="operatorBaseType" />
        </xs:complexContent>
      </xs:complexType>
    </xs:element>
  <!--/operators-->


  <!--when-->
    <xs:complexType name="whenType">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Defines a condition under which the expression will yield one if
          true, otherwise will be <em>strongly</em> zero (zero even if
          undefined)
        </xs:documentation>
      </xs:annotation>

      <xs:sequence>
        <xs:group ref="conditions" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>

      <xs:attribute name="name" type="nameType" use="required" />
      <xs:attribute name="index" type="nameType" />
      <xs:attribute name="label" type="xs:string" />
    </xs:complexType>


    <xs:group name="conditions">
      <xs:choice>
        <xs:element name="eq" type="conditionType" />
        <xs:element name="ne" type="conditionType" />
        <xs:element name="lt" type="conditionType" />
        <xs:element name="gt" type="conditionType" />
        <xs:element name="lte" type="conditionType" />
        <xs:element name="gte" type="conditionType" />

        <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      </xs:choice>
    </xs:group>


    <xs:complexType name="conditionType">
      <xs:sequence>
        <xs:group ref="calculation" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  <!--/when-->


  <xs:complexType name="indexType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        More flexible alternative to the @index attribute on elements; supports
        calculations for determining the index
      </xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
    </xs:sequence>
  </xs:complexType>


  <xs:complexType name="valueType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Returns the value associated with the given identifier.
      </xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:element name="when" type="whenType" minOccurs="0" maxOccurs="unbounded" />
      <xs:element name="index" type="indexType" minOccurs="0" maxOccurs="2" />
      <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>

    <xs:attribute name="name" type="nameType" use="required">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          An identifier for which the value should be retrieved
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="index" type="nameType">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Allows for the definition of an index variable which will be
          defined for all children of the operation.
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="label" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Optional description of a calculation. @label is used in place of
          @desc to ensure that it is not confused with the otherwise required
          @desc attribute.
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>


  <xs:complexType name="constType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Returns @value. This element simply enforces documentation and prevents
        the use of magic values.
      </xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:element name="when" type="whenType" minOccurs="0" maxOccurs="unbounded" />
      <xs:element name="index" type="indexType" minOccurs="0" maxOccurs="2" />
      <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>

    <xs:attribute name="value" type="constValueType" use="required">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Value of constant (must be within the domain of its @type)
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="type" type="nameType">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Type (domain) of the constant (inferred when not provided)
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="desc" type="descType" use="required">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Description of the value explaining its intent
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="label" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Optional description of a calculation. @label is used in place of
          @desc to ensure that it is not confused with the otherwise required
          @desc attribute.
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>


  <xs:complexType name="casesType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Represents a list of cases for a calculation.
      </xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:element name="case" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />

            <xs:element name="when" type="whenType" minOccurs="0" maxOccurs="unbounded" />
            <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
          </xs:sequence>

          <xs:attribute name="label" type="xs:string">
            <xs:annotation>
              <xs:documentation xml:lang="en">
                Optional description of the case
              </xs:documentation>
            </xs:annotation>
          </xs:attribute>
        </xs:complexType>
      </xs:element>

      <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />

      <xs:element name="otherwise" minOccurs="0" maxOccurs="1">
        <xs:complexType>
          <xs:sequence>
            <xs:group ref="calculation" />
          </xs:sequence>

          <xs:attribute name="label" type="xs:string">
            <xs:annotation>
              <xs:documentation xml:lang="en">
                Optional description of the case
              </xs:documentation>
            </xs:annotation>
          </xs:attribute>
        </xs:complexType>
      </xs:element>
    </xs:sequence>

    <xs:attribute name="label" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          Optional description of the case set
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>


  <xs:complexType name="letType">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Declares variables visible within the let block.

        This exists as a means of assignment for re-using values.
      </xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:element name="values" minOccurs="1" maxOccurs="1">
        <xs:complexType>
          <xs:annotation>
            <xs:documentation xml:lang="en">
              Declares a list of values to define for this block
            </xs:documentation>
          </xs:annotation>

          <xs:sequence>
            <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
            <xs:element name="value" minOccurs="0" maxOccurs="unbounded">
              <xs:complexType>
                <xs:annotation>
                  <xs:documentation xml:lang="en">
                    Declares a value that will remain in scope for the let block
                  </xs:documentation>
                </xs:annotation>

                <xs:sequence>
                  <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
                </xs:sequence>

                <xs:attribute name="name" type="nameType" use="required">
                  <xs:annotation>
                    <xs:documentation xml:lang="en">
                      Variable name
                    </xs:documentation>
                  </xs:annotation>
                </xs:attribute>

                <xs:attribute name="type" type="nameType" use="required">
                  <xs:annotation>
                    <xs:documentation xml:lang="en">
                      Variable datatype
                    </xs:documentation>
                  </xs:annotation>
                </xs:attribute>

                <!-- TODO: enum -->
                <xs:attribute name="set" type="xs:string">
                  <xs:annotation>
                    <xs:documentation xml:lang="en">
                      Vector/matrix; if omitted, implicitly scalar.
                    </xs:documentation>
                  </xs:annotation>
                </xs:attribute>

                <xs:attribute name="desc" type="xs:string" use="required">
                  <xs:annotation>
                    <xs:documentation xml:lang="en">
                      Describe the purpose of the value
                    </xs:documentation>
                  </xs:annotation>
                </xs:attribute>
              </xs:complexType>
            </xs:element>

            <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>

      <xs:group ref="calculation" minOccurs="1" maxOccurs="1" />
    </xs:sequence>
  </xs:complexType>


  <xs:group name="calculation">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Represents every element that can be used to perform a calculation.
        Implementors may use this group to accept any type of calculation.
      </xs:documentation>
    </xs:annotation>

    <xs:choice>
      <xs:element ref="operator" />
      <xs:element name="value-of" type="valueType" />
      <xs:element name="const" type="constType" />
      <xs:element name="cases" type="casesType" />
      <xs:element name="let" type="letType" />
      <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
    </xs:choice>
  </xs:group>


  <xs:group name="calculationRoot">
    <xs:annotation>
      <xs:documentation xml:lang="en">
        Root calculation node; this should be the entry point for any type of
        calculation. This helps to ensure that certain nodes are only used at
        the beginning of a calculation (such as cases).
      </xs:documentation>
    </xs:annotation>

    <xs:choice>
      <xs:group ref="calculation" />
    </xs:choice>
  </xs:group>
<!--/calculations-->

</xs:schema>
