validate: Use map for symbol table

This is the first step to improving the map.  Note that this duplicates the
symbol table generation code that's used in a few other places
now---that'll be cleaned up in future commits once I have a better idea of
all the places this will be used and try to move it to a higher level.

* src/current/compiler/validate.xsl (@xmlns:xs, @xmlns:map): New namespace
    definitions.
  (lvv:validate)[lv:package]: Generate symbol table map.  Tunnel to
    templates.
    [c:apply[@name], lv:classify[@as]//lv:match, lv:match[@value]]
    [c:*[@name or @of], c:apply/c:arg[@name], lv:rate/lv:class]: Use it.
master
Mike Gerwitz 2019-02-18 15:36:05 -05:00
parent c077a71402
commit 063e68b3d0
1 changed files with 53 additions and 57 deletions

View File

@ -33,6 +33,8 @@
-->
<stylesheet version="1.0"
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:lv="http://www.lovullo.com/rater"
xmlns:ext="http://www.lovullo.com/ext"
xmlns:c="http://www.lovullo.com/calc"
@ -68,6 +70,11 @@
<template match="lv:package" mode="lvv:validate" priority="9">
<param name="symbol-map" />
<variable name="symtable-map" as="map( xs:string, element( preproc:sym ) )"
select="map:merge(
for $sym in preproc:symtable/preproc:sym
return map{ string( $sym/@name ) : $sym } )" />
<choose>
<when test="$prohibit-validation = 'true'">
<message>
@ -89,7 +96,10 @@
</message>
<!-- validate -->
<apply-templates mode="lvv:validate" />
<apply-templates mode="lvv:validate">
<with-param name="symtable-map" select="$symtable-map"
tunnel="yes" />
</apply-templates>
</otherwise>
</choose>
</template>
@ -119,6 +129,7 @@
</template>
<!-- XXX: Nothing is calling this! -->
<template name="lvv:symbol-chk">
<param name="root" />
<param name="symbol-map" />
@ -171,14 +182,13 @@
<template match="c:apply[@name]" mode="lvv:validate" priority="5">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<variable name="name" select="@name" />
<variable name="self" select="." />
<variable name="fsym" select="
root(.)/preproc:symtable/preproc:sym[
@type='func'
and @name=$name
]
" />
<variable name="fsym" as="element( preproc:sym )"
select="$symtable-map( $name )" />
<!-- ensure that a function is being applied -->
<if test="not( $fsym )">
@ -230,7 +240,12 @@
Validate that match @on's exist
-->
<template match="lv:classify[ @as ]//lv:match" mode="lvv:validate" priority="9">
<if test="not( @on=root(.)/preproc:symtable/preproc:sym[ @type ]/@name )">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<variable name="sym" as="element( preproc:sym )?"
select="$symtable-map( @on )" />
<if test="not( $sym )">
<call-template name="lvv:error">
<with-param name="desc" select="'Unknown match @on'" />
<with-param name="refnode" select="." />
@ -256,14 +271,13 @@
Validate that non-numeric value matches actually exist and are constants
-->
<template match="lv:match[@value]" mode="lvv:validate-match" priority="5">
<if test="
not( number( @value ) = @value )
and not(
@value=root(.)/preproc:symtable/preproc:sym[
@type='const'
]/@name
)
">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<variable name="sym" as="element( preproc:sym )?"
select="$symtable-map( @value )" />
<if test="not( number( @value ) = @value )
and not( $sym )">
<call-template name="lvv:error">
<with-param name="desc" select="'Unknown match value'" />
@ -338,6 +352,8 @@
</template>
<template match="c:*[@name or @of]" mode="lvv:validate" priority="2">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<variable name="name">
<choose>
<when test="@of">
@ -350,19 +366,6 @@
</choose>
</variable>
<!-- XXX: have to maintain this list! -->
<variable name="nodes" select="
root(.)//lv:*[
@name=$name
or @yields=$name
or @as=$name
]
, root(.)//c:*[
@generates=$name
]
, root(.)//c:values/c:value[ @name=$name ]
" />
<!-- locate function params/let vars -->
<variable name="fname" select="
ancestor::lv:function[
@ -385,16 +388,11 @@
<!-- if this name references a function parameter, then it takes
precedence (note that this consequently means that it masks any other
names that may be globally defined) -->
<variable name="sym" select="
if ( $fname ) then
root(.)/preproc:symtable/preproc:sym[
@name=concat( ':', $fname, ':', $name )
]
else
root(.)/preproc:symtable/preproc:sym[
@name=$name
]
" />
<variable name="sym" as="element( preproc:sym )?"
select="if ( $fname ) then
$symtable-map( concat( ':', $fname, ':', $name ) )
else
$symtable-map( $name )" />
<variable name="type" select="$sym/@dtype" />
@ -581,15 +579,12 @@
<template match="c:apply/c:arg[@name]" mode="lvv:validate" priority="5">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<!-- merely validate its existence -->
<variable name="fname" select="parent::c:apply/@name" />
<if test="not(
concat( ':', $fname, ':', @name ) = root(.)/preproc:symtable/preproc:sym[
@type='lparam'
and @parent=$fname
]/@name
)">
<if test="not( $symtable-map( concat( ':', $fname, ':', @name ) ) )">
<call-template name="lvv:error">
<with-param name="desc" select="'Unknown argument'" />
<with-param name="refnode" select="." />
@ -641,20 +636,21 @@
Checks for use of undefined classifications
-->
<template mode="lvv:validate" priority="2"
match="lv:rate/lv:class[
not( concat( ':class:', @ref ) = root(.)/preproc:symtable/preproc:sym[ @type='class' ]/@name )
]">
match="lv:rate/lv:class">
<param name="symtable-map" as="map(*)" tunnel="yes" />
<call-template name="lvv:error">
<with-param name="desc" select="'Unknown classification'" />
<with-param name="refnode" select="." />
<with-param name="content">
<text>unknown classification '</text>
<if test="not( $symtable-map( concat( ':class:', @ref ) ) )">
<call-template name="lvv:error">
<with-param name="desc" select="'Unknown classification'" />
<with-param name="refnode" select="." />
<with-param name="content">
<text>unknown classification '</text>
<value-of select="@ref" />
<text>' referenced by </text>
<value-of select="ancestor::lv:rate/@yields" />
</with-param>
</call-template>
<text>' referenced by </text>
<value-of select="ancestor::lv:rate/@yields" />
</with-param>
</call-template>
</if>
</template>