lv:match/c:* optimizations for v* and s*

This will make m1v*s0 worth doing now.
master
Mike Gerwitz 2021-01-25 12:11:08 -05:00
parent db88f6aba5
commit 5ae5c226f9
3 changed files with 102 additions and 17 deletions

View File

@ -477,13 +477,16 @@
<!-- TODO: this should really be decoupled -->
<!-- TODO: does not properly support matrices -->
<template match="c:value-of[ ancestor::lv:match ]" mode="compile-calc" priority="5">
<param name="noindex" as="xs:boolean" tunnel="yes"
select="false()" />
<variable name="name" select="@name" />
<choose>
<!-- scalar -->
<when test="
root(.)/preproc:symtable/preproc:sym[ @name=$name ]
/@dim = '0'
$noindex
or root(.)/preproc:symtable/preproc:sym[ @name=$name ]/@dim = '0'
">
<apply-templates select="." mode="compile-calc-value" />
</when>

View File

@ -813,30 +813,43 @@
</choose>
</when>
<!-- TODO: this would be better handled in a validation phase -->
<when test="$match[count(c:*) gt 1]">
<message terminate="yes"
select="concat( 'error: multi-c:* expression not supported: ',
$match/parent::lv:classify/@as)" />
</when>
<when test="$match[c:eq|c:ne|c:gt|c:lt|c:gte|c:lte]">
<variable name="c" as="element()"
select="$match/c:*" />
<variable name="name" as="xs:string"
select="$c/local-name()" />
<variable name="f" as="xs:string"
select="concat( 'c', $name )" />
<!-- should only be _one_ -->
<!-- should only be _one_ (@as validates this) -->
<variable name="expr" as="element()" select="$c/c:*" />
<!-- if it's not c:value-of, it must be scalar c:const (see lv:match
in validator) -->
<variable name="cdim" as="xs:integer"
select="if ( $c/c:value-of ) then
$symtable-map( $c/c:value-of/@name )/@dim
else
0" />
<variable name="indexed" as="xs:boolean" select="$cdim gt 0" />
<variable name="f" as="xs:string"
select="concat( 'c', $name,
( if ( $indexed ) then 'i' else '' ) )" />
<!-- TODO: remove generation of useless debug output! -->
<variable name="exprjs" as="xs:string"
select="compiler:compile( $symtable-map, $expr )" />
<variable name="transform" as="xs:string"
select="concat( $f, '(', $exprjs, ')' )" />
<message select="concat( 'notice: c:* ', $match/parent::lv:classify/@as )" />
<!-- scalars should have already been caught during validation, but we
do not support matrices -->
<if test="$indexed and $dim = 2">
<message terminate="yes"
select="concat( 'error: lv:match/c:*/c:index unsupported ',
'for matrix `',
$match/parent::lv/classify/@as, '''' )" />
</if>
<choose>
<!-- vector, so map -->
@ -866,6 +879,11 @@
<apply-templates select="$element" mode="compile">
<with-param name="symtable-map" select="$symtable-map"
tunnel="true" />
<!-- suppress match index generation, since we handle it ourselves now
(in a different way) -->
<with-param name="noindex" select="true()"
tunnel="true" />
</apply-templates>
</variable>
@ -1757,13 +1775,20 @@
function M(xs, f) { return xs.map(f); }
function ceq(y) { return function(x) { return +(x === y); }; }
function cne(y) { return function (x) { return +(x !== y); }; }
function cgt(y) { return function (x) { return +(x > y); }; }
function clt(y) { return function (x) { return +(x < y); }; }
function ceq(y) { return function (x) { return +(x === y); }; }
function cne(y) { return function (x) { return +(x !== y); }; }
function cgt(y) { return function (x) { return +(x > y); }; }
function clt(y) { return function (x) { return +(x < y); }; }
function cgte(y) { return function (x) { return +(x >= y); }; }
function clte(y) { return function (x) { return +(x <= y); }; }
function ceqi(y) { return function (x, i) { return +(x === (y[i]||0)); }; }
function cnei(y) { return function (x, i) { return +(x !== (y[i]||0)); }; }
function cgti(y) { return function (x, i) { return +(x > (y[i]||0)); }; }
function clti(y) { return function (x, i) { return +(x < (y[i]||0)); }; }
function cgtei(y) { return function (x, i) { return +(x >= (y[i]||0)); }; }
function cltei(y) { return function (x, i) { return +(x <= (y[i]||0)); }; }
/**
* Checks for matches against values for any param value
*

View File

@ -300,11 +300,68 @@
<apply-templates mode="lvv:validate-match" />
</template>
<!-- simplify optimizations -->
<template match="lv:match[ count(c:*) gt 1 ]" mode="lvv:validate-match" priority="4">
<call-template name="lvv:error">
<with-param name="desc" select="'Multi-c:* match expression'" />
<with-param name="refnode" select="." />
<with-param name="content">
<text>`</text>
<value-of select="@on" />
<text>' must include separate matches for each c:* in `</text>
<value-of select="parent::lv:classify/@as" />
<text>'</text>
</with-param>
</call-template>
<apply-templates mode="lvv:validate-match" />
</template>
<template match="lv:match" mode="lvv:validate-match" priority="2">
<apply-templates mode="lvv:validate-match" />
</template>
<!-- simplify optimizations -->
<template mode="lvv:validate-match" priority="5"
match="c:*[ not( c:value-of or c:const ) ]">
<call-template name="lvv:error">
<with-param name="desc" select="'invalid lv:match/c:*/c:*'" />
<with-param name="refnode" select="." />
<with-param name="content">
<text>`</text>
<value-of select="@on" />
<text>' must contain only c:value of or c:const in `</text>
<value-of select="parent::lv:classify/@as" />
<text>'</text>
</with-param>
</call-template>
<apply-templates mode="lvv:validate-match" />
</template>
<!-- simplify optimizations -->
<template mode="lvv:validate-match" priority="4"
match="c:*[ c:const[ c:* ] ]">
<call-template name="lvv:error">
<with-param name="desc" select="'non-scalar lv:match/c:*/c:*'" />
<with-param name="refnode" select="." />
<with-param name="content">
<text>`</text>
<value-of select="@on" />
<text>' must contain only scalar c:const in `</text>
<value-of select="parent::lv:classify/@as" />
<text>'</text>
</with-param>
</call-template>
<apply-templates mode="lvv:validate-match" />
</template>
<template match="c:*" mode="lvv:validate-match" priority="2">
<apply-templates select="." mode="lvv:validate" />
</template>