Add c:sum/@dim

This allows the result of a rate block to be a matrix; there was previously
no way for a named value to be assigned a matrix unless it was a parameter.

This is a bit of a kluge---the compiler won't discover the proper type
information and won't perform the proper safeguards.

* src/current/calc.xsd (sum)[@dim]: Add attribute.
* src/current/compiler/js-calc.xsl: Add xs namespace.
  (compile-calc): Do not perform casting when @dim > 1.
* src/current/include/preproc/expand.xsl
  (lv:rate-each): Include @dim in c:sum expansion.
* src/current/include/preproc/macros.xsl:
  (c:*/@generates): Use @dim to determine symbol dimensions.
* src/current/include/preproc/expand.xsl: Parse @dim aliases (e.g. "vector",
  "matrix").
master
Mike Gerwitz 2017-11-30 13:51:37 -05:00
parent 6fa6b03dde
commit 0fb1bae487
5 changed files with 75 additions and 6 deletions

View File

@ -235,6 +235,16 @@
</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>

View File

@ -36,6 +36,7 @@
-->
<stylesheet version="2.0"
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:c="http://www.lovullo.com/calc"
xmlns:lv="http://www.lovullo.com/rater"
xmlns:preproc="http://www.lovullo.com/rater/preproc"
@ -187,6 +188,9 @@
</choose>
</variable>
<variable name="dim" as="xs:integer"
select="if ( @dim ) then @dim else 0" />
<!-- introduce scope both to encapsulate values and so we can insert this as
part of a larger expression (will return a value) -->
<text>( function() {</text>
@ -245,7 +249,12 @@
<value-of select="$value" />
<text> ) {</text>
<text>var result = +(+( </text>
<text>var result = </text>
<!-- if caller wants to yield a vector, don't cast -->
<sequence select="if ( not( $dim gt 0 ) ) then
'+(+( '
else
'(( '" />
<choose>
<!-- if there are child nodes, use that as the summand/expression -->
<when test="./c:*">
@ -260,9 +269,16 @@
<text>]</text>
</otherwise>
</choose>
<text> )).toFixed(</text>
<value-of select="$precision" />
<text>);</text>
<text> ))</text>
<!-- if caller wants to yield a vector, don't truncate -->
<if test="not( $dim gt 0 )">
<text>.toFixed(</text>
<value-of select="$precision" />
<text>)</text>
</if>
<text>;</text>
<!-- if generating a set, store this result -->
<if test="@generates">

View File

@ -122,6 +122,46 @@
</xsl:template>
<!--
Translate dimension aliases (e.g. scaler, vector, matrix) into respective
numeric representations.
-->
<xsl:template mode="preproc:expand" priority="8"
match="c:*[ @dim
and not( string( @dim ) castable as xs:integer ) ]">
<xsl:copy>
<xsl:sequence select="@*" />
<!-- replace dim with numeric -->
<xsl:attribute name="dim">
<xsl:choose>
<xsl:when test="@dim = 'scaler' or @dim = ''">
<xsl:sequence select="0" />
</xsl:when>
<xsl:when test="@dim = 'vector'">
<xsl:sequence select="1" />
</xsl:when>
<xsl:when test="@dim = 'matrix'">
<xsl:sequence select="2" />
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes"
select="concat(
'!!! [preproc] error: ',
'unknown dimension alias ''',
@dim, '''' )" />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:sequence select="node()" />
</xsl:copy>
</xsl:template>
<!--
Give let's a name so that they may be easily referenced uniquely
-->

View File

@ -402,7 +402,7 @@
<xsl:sequence select="./lv:class" />
<c:sum of="_CMATCH_" index="{@index}" sym="{@gensym}">
<c:sum of="_CMATCH_" index="{@index}" sym="{@gensym}" dim="{@dim}">
<!-- copy @generates, if it exists (has the benefit of copying nothing
if it does not exist) -->
<xsl:sequence select="@generates" />

View File

@ -688,9 +688,12 @@
<xsl:template match="c:*[ @generates ]" mode="preproc:symtable" priority="5">
<xsl:variable name="parent" select="ancestor::lv:rate" />
<xsl:variable name="dim" as="xs:integer"
select="if ( @dim ) then @dim else 1" />
<preproc:sym name="{@generates}"
parent="{$parent/@yields}"
type="gen" dtype="float" dim="1" desc="{@desc}" tex="{@sym}" />
type="gen" dtype="float" dim="{$dim}" desc="{@desc}" tex="{@sym}" />
<xsl:apply-templates mode="preproc:symtable" />
</xsl:template>