m0v*s0 single-distinct-@on optimization

I have been wanting to do this for many years.  This is quite
gratifying.  Here is some example output:

  c['foo']=E(A['fooState']=A['state'].map(s => +[2,7,8,9,10,11,19,20,21,22,26,28,31,32,35,39,40,41,46,47,44].includes(s)));

Previously, it looked like this:

  classes['foo'] = (function(){var result,tmp;  tmp = anyValue(
  args['state'], 2, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1924'] || ( debug['d1124644e1924'] = [] ) ).push( tmp
  );/*!-*/ result = tmp; tmp = anyValue( args['state'], 7, args['fooState'],
  false, false ) ;/*!+*/( debug['d1124644e1925'] || ( debug['d1124644e1925'] =
  [] ) ).push( tmp );/*!-*/ result = result || tmp; tmp = anyValue(
  args['state'], 8, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1926'] || ( debug['d1124644e1926'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 9,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1927'] || (
  debug['d1124644e1927'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 10, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1928'] || ( debug['d1124644e1928'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 11,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1929'] || (
  debug['d1124644e1929'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 19, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1930'] || ( debug['d1124644e1930'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 20,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1931'] || (
  debug['d1124644e1931'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 21, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1932'] || ( debug['d1124644e1932'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 22,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1933'] || (
  debug['d1124644e1933'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 26, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1934'] || ( debug['d1124644e1934'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 28,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1936'] || (
  debug['d1124644e1936'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 31, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1937'] || ( debug['d1124644e1937'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 32,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1938'] || (
  debug['d1124644e1938'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 35, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1939'] || ( debug['d1124644e1939'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 40,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1940'] || (
  debug['d1124644e1940'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 41, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1941'] || ( debug['d1124644e1941'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; tmp = anyValue( args['state'], 46,
  args['fooState'], false, false ) ;/*!+*/( debug['d1124644e1942'] || (
  debug['d1124644e1942'] = [] ) ).push( tmp );/*!-*/ result = result || tmp;
  tmp = anyValue( args['state'], 44, args['fooState'], false, false ) ;/*!+*/(
  debug['d1124644e1943'] || ( debug['d1124644e1943'] = [] ) ).push( tmp
  );/*!-*/ result = result || tmp; return tmp;})();

The source XML is:

  <classify as="foo" yields="fooState"
            desc="Foo">
    <any>
      <match on="state" value="STATE_AL" />
      <match on="state" value="STATE_CT" />
      <match on="state" value="STATE_DC" />
      <match on="state" value="STATE_DE" />
      <match on="state" value="STATE_FL" />
      <match on="state" value="STATE_GA" />
      <match on="state" value="STATE_LA" />
      <match on="state" value="STATE_MA" />
      <match on="state" value="STATE_MD" />
      <match on="state" value="STATE_ME" />
      <match on="state" value="STATE_MS" />
      <match on="state" value="STATE_NC" />
      <match on="state" value="STATE_NH" />
      <match on="state" value="STATE_NJ" />
      <match on="state" value="STATE_NY" />
      <match on="state" value="STATE_PA" />
      <match on="state" value="STATE_RI" />
      <match on="state" value="STATE_SC" />
      <match on="state" value="STATE_VA" />
      <match on="state" value="STATE_VT" />
      <match on="state" value="STATE_TX" />
    </any>
  </classify>
master
Mike Gerwitz 2021-01-20 15:21:44 -05:00
parent a2f846f9c4
commit cfbdc35a55
1 changed files with 45 additions and 13 deletions

View File

@ -690,6 +690,9 @@
<!-- existential, universal -->
<variable name="ctype" as="xs:string"
select="if ( @any='true' ) then 'e' else 'u'" />
<variable name="cop" as="xs:string"
select="if ( @any = 'true' ) then '||' else '&amp;&amp;'" />
<!-- optimize for very specific, common cases -->
<choose>
@ -709,23 +712,45 @@
<!-- all vectors with @value -->
<when test="$nm = 0 and $nv > 0 and $ns = 0 and empty( $vectors[not(@value)] )">
<sequence select="concat( '[', $yield-to, ',', $var, ']=v', $ctype, '([',
string-join(
for $v in $vectors
return compiler:match-name-on( $symtable-map, $v ),
','), '], [',
string-join(
for $v in $vectors
return compiler:match-value( $symtable-map, $v ),
','),
']);' )" />
<choose>
<!-- if all the matches are on the same @on, we can optimize even
further (unless it's a single match, in which case the fallback
is the optimal way to proceed) -->
<when test="$nv > 1 and count( distinct-values( $vectors/@on ) ) = 1">
<!-- if this is not @any, then it's nonsense -->
<if test="not( @any = 'true' )">
<message terminate="yes"
select="concat( 'error: ', @as, ' match ', $vectors[0]/@on,
'will never succeed' )" />
</if>
<sequence select="concat( $var, '=E(', $yield-to, '=',
compiler:match-name-on( $symtable-map, $vectors[1] ),
'.map(s => +[',
string-join(
for $v in $vectors
return compiler:match-value( $symtable-map, $v ),
','),
'].includes(s)));' )" />
</when>
<otherwise>
<sequence select="concat( '[', $yield-to, ',', $var, ']=v', $ctype, '([',
string-join(
for $v in $vectors
return compiler:match-name-on( $symtable-map, $v ),
','), '], [',
string-join(
for $v in $vectors
return compiler:match-value( $symtable-map, $v ),
','),
']);' )" />
</otherwise>
</choose>
</when>
<!-- all scalars with @value -->
<when test="$nm = 0 and $nv = 0 and $ns > 0 and empty( $scalars[not(@value)] )">
<variable name="cop" as="xs:string"
select="if ( @any = 'true' ) then '||' else '&amp;&amp;'" />
<choose>
<!-- if all the matches are on the same @on, we can optimize even
further (unless it's a single match, in which case the fallback
@ -1580,6 +1605,13 @@
}
// existential (any)
function E(v)
{
return v.some(s => s === 1);
}
/**
* Checks for matches against values for any param value
*