compiler: Correct handling of TRUE matches

There was a bug whereby TRUE matches would keep whatever value was being
matched on, even if it was not a boolean.  That was an oversight from the
proof-of-concept code, and this fixes it; that's why this is behind a flag!

This also adjusts the class aliasing optimization so that it doesn't check
for a `TRUE` symbol name, which was a bad idea to begin with.

This change also ends up expanding `lv:match[@value="TRUE"]` into the long
form, where it didn't previously; this will result in slightly larger xmlo
files in some cases, but it's nothing significant, and it does not impact
compilation times.
main
Mike Gerwitz 2021-07-15 14:55:32 -04:00
parent 37977a8816
commit 2ad0d1425a
3 changed files with 44 additions and 14 deletions

View File

@ -20,6 +20,14 @@ Compiler
-------- --------
- Make Summary Page less chatty. - Make Summary Page less chatty.
- Fix incorrect package name for generated worksheet packages. - Fix incorrect package name for generated worksheet packages.
- Restrict `TRUE`-match optimization to classification matches (class
composition).
- This was mistakenly not considering the domain of the match, and
therefore was applying the optimization in situations where it should
not. Results of previous classifications are currently the only place
we guarantee a boolean value.
- Apply classification alias optimization to any `1`-valued constant match.
- Previously applied only to `TRUE`.
Summary Page Summary Page
------------ ------------

View File

@ -541,7 +541,6 @@
--> -->
<template mode="compile" priority="7" <template mode="compile" priority="7"
match="lv:classify[ count( lv:match ) = 1 match="lv:classify[ count( lv:match ) = 1
and lv:match/@value='TRUE'
and not( lv:match/@preproc:inline ) ]"> and not( lv:match/@preproc:inline ) ]">
<param name="symtable-map" as="map(*)" tunnel="yes" /> <param name="symtable-map" as="map(*)" tunnel="yes" />
@ -550,9 +549,18 @@
<variable name="src-sym" as="element( preproc:sym )" <variable name="src-sym" as="element( preproc:sym )"
select="$symtable-map( $src )" /> select="$symtable-map( $src )" />
<variable name="c" as="element()?"
select="lv:match/c:*" />
<variable name="cmpval" as="xs:float?"
select="if ( exists( $c/c:value-of ) ) then
$symtable-map( $c/c:value-of/@name )/@value
else
$c/c:const/@value" />
<choose> <choose>
<!-- we only handle aliasing of other classifications --> <!-- we only handle aliasing of other classifications -->
<when test="$src-sym/@type = 'cgen'"> <when test="$src-sym/@type = 'cgen' and $cmpval = 1">
<sequence select="$compiler:nl" /> <sequence select="$compiler:nl" />
<!-- simply alias the @yields --> <!-- simply alias the @yields -->
@ -850,8 +858,10 @@
<param name="symtable-map" as="map(*)" /> <param name="symtable-map" as="map(*)" />
<param name="match" as="element( lv:match )" /> <param name="match" as="element( lv:match )" />
<variable name="dim" as="xs:integer" <variable name="sym" as="element( preproc:sym )"
select="$symtable-map( $match/@on )/@dim" /> select="$symtable-map( $match/@on )" />
<variable name="dim" as="xs:integer" select="$sym/@dim" />
<variable name="type" as="xs:string" select="$sym/@type" />
<variable name="inner" as="xs:string" <variable name="inner" as="xs:string"
select="compiler:match-name-on( $symtable-map, $match )" /> select="compiler:match-name-on( $symtable-map, $match )" />
@ -862,11 +872,6 @@
select="if ( $dim = 2 ) then 'NN' else 'N'" /> select="if ( $dim = 2 ) then 'NN' else 'N'" />
<choose> <choose>
<!-- only basic TRUE equality can be used verbatim -->
<when test="$match/@value = 'TRUE'">
<sequence select="$inner" />
</when>
<when test="$match/@anyOf"> <when test="$match/@anyOf">
<variable name="anyof" as="xs:string" <variable name="anyof" as="xs:string"
select="compiler:compile-anyof( $symtable-map, $match )" /> select="compiler:compile-anyof( $symtable-map, $match )" />
@ -924,11 +929,28 @@
$match/parent::lv/classify/@as, '''' )" /> $match/parent::lv/classify/@as, '''' )" />
</if> </if>
<!-- Note: we currently only check for cgen, that's that's the only
type we can guarantee to be boolean; params can have any value
passed in and we are not necessarily validating the
domain. Until that is in place, it's too dangerous. We also
need more information in the symbol table. -->
<variable name="boolmatch" as="xs:boolean"
select="$type = 'cgen'" />
<choose> <choose>
<!-- Boolean-TRUE matches need no translation; their values can be
used without modification. This allows primarily for
lower-cost class composition However, it's important that we do
this only when working with a boolean domain, otherwise we may
yield a value that is not in the domain {0,1}. -->
<when test="$boolmatch and $match/c:eq and $cval = 1">
<sequence select="$inner" />
</when>
<when test="$dim > 0"> <when test="$dim > 0">
<choose> <choose>
<!-- negation, very common, so save some bytes --> <!-- negation, very common, so save some bytes -->
<when test="$match/c:eq and $cval = 0"> <when test="$boolmatch and $match/c:eq and $cval = 0">
<sequence select="concat( $nf, '(', $inner, ')' )" /> <sequence select="concat( $nf, '(', $inner, ')' )" />
</when> </when>
@ -942,7 +964,7 @@
<otherwise> <otherwise>
<choose> <choose>
<!-- negation, very common, so save some bytes --> <!-- negation, very common, so save some bytes -->
<when test="$match/c:eq and $cval = 0"> <when test="$boolmatch and $match/c:eq and $cval = 0">
<sequence select="concat( 'n(', $inner, ')' )" /> <sequence select="concat( 'n(', $inner, ')' )" />
</when> </when>

View File

@ -596,9 +596,9 @@
</template> </template>
<!-- expand lv:match/@value != 'TRUE' into a c:* expression to simpliy <!-- expand lv:match/@value into a c:* expression to simplify static
optimizations --> analysis -->
<template match="lv:match[ @value and @value != 'TRUE' ]" <template match="lv:match[ @value ]"
mode="preproc:expand" priority="7"> mode="preproc:expand" priority="7">
<copy> <copy>