784 lines
24 KiB
XML
784 lines
24 KiB
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<!--
|
|
Compile package
|
|
|
|
Copyright (C) 2014-2019 Ryan Specialty Group, LLC.
|
|
|
|
This file is part of TAME.
|
|
|
|
TAME is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see
|
|
<http://www.gnu.org/licenses/>.
|
|
|
|
This will preprocess a package XML suitable for compilation into an object
|
|
file.
|
|
-->
|
|
<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:preproc="http://www.lovullo.com/rater/preproc"
|
|
xmlns:lv="http://www.lovullo.com/rater"
|
|
xmlns:t="http://www.lovullo.com/rater/apply-template"
|
|
xmlns:c="http://www.lovullo.com/calc"
|
|
xmlns:w="http://www.lovullo.com/rater/worksheet"
|
|
xmlns:lvv="http://www.lovullo.com/rater/validate"
|
|
xmlns:ext="http://www.lovullo.com/ext"
|
|
xmlns:util="http://www.lovullo.com/util">
|
|
|
|
|
|
<include href="../dslc-base.xsl" />
|
|
|
|
<!-- phases -->
|
|
<include href="macros.xsl" />
|
|
<include href="expand.xsl" />
|
|
<include href="symtable.xsl" />
|
|
|
|
<include href="../../compiler/fragments.xsl" />
|
|
|
|
|
|
<!-- begin preprocessing from an arbitrary node -->
|
|
<template name="preproc:pkg-compile" as="element( lv:package )"
|
|
match="*" mode="preproc:compile" priority="1">
|
|
<param name="orig-root" as="element()"
|
|
select="root(.)/lv:package" />
|
|
|
|
<param name="stopshort" />
|
|
|
|
<!-- should be provided externally -->
|
|
<if test="not( $__rseed ) or ( $__rseed = '' )">
|
|
<message terminate="yes">
|
|
<text>[preproc] error: missing random seed `__rseed'</text>
|
|
</message>
|
|
</if>
|
|
|
|
<message>
|
|
<text>[preproc] *beginning macro expansion...</text>
|
|
</message>
|
|
|
|
<!-- these can contain repass nodes, thus the element()+ -->
|
|
|
|
<!-- macro expansion -->
|
|
<variable name="stage1" as="element()+">
|
|
<apply-templates select="." mode="preproc:macropass" />
|
|
|
|
<message>
|
|
<text>[preproc] *macro pass complete; expanding...</text>
|
|
</message>
|
|
</variable>
|
|
|
|
<!-- expand shorthands, etc -->
|
|
<variable name="stage2" as="element()+">
|
|
<apply-templates select="$stage1"
|
|
mode="preproc:expand" />
|
|
|
|
<message>
|
|
<text>[preproc] *expansion complete; generating symbol table...</text>
|
|
</message>
|
|
</variable>
|
|
|
|
<variable name="stage3" as="element()+">
|
|
<apply-templates select="$stage2"
|
|
mode="preproc:sym-discover">
|
|
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
</apply-templates>
|
|
|
|
<message>
|
|
<text>[preproc] *symbol table generated; checking for </text>
|
|
<text>unprocessed templates...</text>
|
|
</message>
|
|
</variable>
|
|
|
|
|
|
<!-- TODO: resolve this mess -->
|
|
<variable name="stage3-pkg" as="element( lv:package )"
|
|
select="$stage3/preproc:symtable/parent::*" />
|
|
|
|
<!-- TODO: move me somewhere more appropriate and create an error
|
|
system that is _guaranteed_ to catch everything -->
|
|
<for-each select="$stage3-pkg/preproc:symtable/preproc:error">
|
|
<message terminate="yes">
|
|
<text>!!! [preproc] error: </text>
|
|
<value-of select="." />
|
|
</message>
|
|
</for-each>
|
|
|
|
|
|
<!-- determine if we should finish or simply return for further processing -->
|
|
<choose>
|
|
<when test="not( $stopshort )">
|
|
<!-- template expansions may have been deferred until their symbols were made
|
|
available -->
|
|
<variable name="final" as="element( lv:package )">
|
|
<call-template name="preproc:tpl-sym-recurse">
|
|
<with-param name="package" select="$stage3-pkg" />
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
</call-template>
|
|
</variable>
|
|
|
|
<variable name="extern-chk" as="element( preproc:error )*"
|
|
select="preproc:final-extern-check(
|
|
$final/preproc:symtable )" />
|
|
|
|
|
|
<if test="$extern-chk">
|
|
<for-each select="$extern-chk">
|
|
<message>
|
|
<text>!!! [preproc] error: </text>
|
|
<value-of select="." />
|
|
</message>
|
|
</for-each>
|
|
|
|
<message>~~~~[begin document dump]~~~~</message>
|
|
<message select="$final" />
|
|
<message>~~~~[end document dump]~~~~</message>
|
|
|
|
<message select="'Aborting due to unresolved externs'" />
|
|
|
|
<message terminate="yes"
|
|
select="'Document dumped.'" />
|
|
</if>
|
|
|
|
<!-- ensure that all template parameters have been expanded -->
|
|
<apply-templates select="$final" mode="preproc:tpl-check" />
|
|
|
|
<!-- perform validation before dependency generation to ensure that all
|
|
dependencies are available -->
|
|
<apply-templates select="$final" mode="preproc:pkg-validate" />
|
|
|
|
<!-- determine how many passes have been made -->
|
|
<!-- TODO: reintroduce
|
|
<variable name="repass-count"
|
|
select="count( $final//preproc:repass-record )" />
|
|
-->
|
|
|
|
<!-- assign unique ids to each node -->
|
|
<variable name="idized" as="element( lv:package )">
|
|
<apply-templates select="$final" mode="preproc:idize" />
|
|
</variable>
|
|
|
|
<!-- generate deps -->
|
|
<variable name="depd" as="element( lv:package )">
|
|
<apply-templates select="$idized" mode="preproc:gen-deps" />
|
|
</variable>
|
|
|
|
<!-- post-process symbol table to resolve any unknowns that require a
|
|
dependency graph -->
|
|
<variable name="resolvd" as="element( lv:package )">
|
|
<apply-templates select="$depd" mode="preproc:resolv-syms">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
</apply-templates>
|
|
</variable>
|
|
|
|
|
|
<!-- compile fragments -->
|
|
<message>
|
|
<text>[preproc] compiling fragments...</text>
|
|
</message>
|
|
|
|
|
|
<apply-templates select="$resolvd"
|
|
mode="preproc:compile-fragments" />
|
|
|
|
|
|
<!-- output a repass count, which could be a strong indicator of performance
|
|
issues -->
|
|
<!-- TODO: reintroduce
|
|
<message>
|
|
<text>[Preprocessor repass count: </text>
|
|
<value-of select="$repass-count" />
|
|
<text>] [Node count: </text>
|
|
<value-of select="count( $final//* )" />
|
|
<text>]</text>
|
|
</message>
|
|
-->
|
|
</when>
|
|
|
|
<!-- return for further processing -->
|
|
<otherwise>
|
|
<sequence select="$stage3" />
|
|
</otherwise>
|
|
</choose>
|
|
</template>
|
|
|
|
|
|
<!--
|
|
A very primitive guard against unexpanded template parameters.
|
|
-->
|
|
<template match="*[ starts-with( @*, '@' ) ]" mode="preproc:tpl-check" priority="5">
|
|
<message>
|
|
<text>[preproc] fatal: unexpanded template parameter: </text>
|
|
<sequence select="@*[ starts-with( ., '@' ) ]" />
|
|
</message>
|
|
|
|
<message>
|
|
<text>[preproc] fatal: reference node: </text>
|
|
<sequence select="." />
|
|
</message>
|
|
|
|
<message>~~~~[begin document dump]~~~~</message>
|
|
<message select="root(.)" />
|
|
<message>~~~~[end document dump]~~~~</message>
|
|
|
|
<message terminate="yes">[preproc] notice: Document dumped.</message>
|
|
</template>
|
|
|
|
|
|
<!-- this should never happen; but is has, so here's a failsafe -->
|
|
<template match="lv:apply-template" mode="preproc:tpl-check" priority="5">
|
|
<message>
|
|
<text>[preproc] fatal: unexpanded template: </text>
|
|
<sequence select="." />
|
|
</message>
|
|
|
|
<message>
|
|
<text>[preproc] fatal: reference node: </text>
|
|
<sequence select="." />
|
|
</message>
|
|
|
|
<message select="'[preproc] internal error: there is a bug in the',
|
|
'preprocessor; this should never happen!'" />
|
|
|
|
<message>~~~~[begin document dump]~~~~</message>
|
|
<message select="root(.)" />
|
|
<message>~~~~[end document dump]~~~~</message>
|
|
|
|
<message terminate="yes">[preproc] notice: Document dumped.</message>
|
|
</template>
|
|
|
|
|
|
<!-- skip things that cannot contain template applications -->
|
|
<template match="lv:template|lv:const|lv:typedef|lv:param-copy"
|
|
mode="preproc:tpl-check" priority="9">
|
|
</template>
|
|
|
|
<template match="*" mode="preproc:tpl-check" priority="1">
|
|
<apply-templates select="*" mode="preproc:tpl-check" />
|
|
</template>
|
|
|
|
|
|
|
|
<!--
|
|
TODO: This needs to go away in the form of a more performant system
|
|
that marks a repass as needed *without* scanning the entire tree.
|
|
-->
|
|
<template name="preproc:tpl-sym-recurse" as="element( lv:package )">
|
|
<param name="package" as="element( lv:package )" />
|
|
<param name="orig-root" as="element()" />
|
|
|
|
<!-- number of iterations where no template applications have
|
|
happened -->
|
|
<param name="tpl-stall-count"
|
|
tunnel="yes"
|
|
select="0" />
|
|
|
|
<!-- get a list of needed template applications (ignoring applications that
|
|
are within templates and nested applications) -->
|
|
<variable name="apply" as="element( lv:apply-template )*"
|
|
select="$package//lv:apply-template[
|
|
not(
|
|
@name=$package/lv:template/@name
|
|
or ancestor::lv:template
|
|
or ancestor::lv:apply-template
|
|
)
|
|
]" />
|
|
<variable name="napply" select="count( $apply )" />
|
|
|
|
<choose>
|
|
<when test="$apply">
|
|
<!-- get a list of required templates -->
|
|
<variable name="req">
|
|
<preproc:tpl>
|
|
<for-each select="$apply">
|
|
<copy>
|
|
<sequence select="@name" />
|
|
</copy>
|
|
</for-each>
|
|
</preproc:tpl>
|
|
</variable>
|
|
|
|
<variable name="requniq" as="element( lv:apply-template )*" select="
|
|
$req//lv:apply-template[
|
|
not( @name=preceding-sibling::lv:apply-template/@name
|
|
or @name=$package//lv:template/@name ) ]
|
|
" />
|
|
|
|
<message>
|
|
<text>[preproc] </text>
|
|
<value-of select="count( $apply )" />
|
|
<text> template(s) still need application: </text>
|
|
|
|
<for-each select="$apply">
|
|
<if test="position() gt 1">
|
|
<text>, </text>
|
|
</if>
|
|
|
|
<value-of select="@name" />
|
|
</for-each>
|
|
</message>
|
|
|
|
<!-- load each of the requested templates (but only once) -->
|
|
<variable name="tpls">
|
|
<!-- TODO: we no longer need to load the templates; the
|
|
template replacement looks up the template on-demand from
|
|
the symbol table; we're no longer injecting them -->
|
|
<apply-templates mode="preproc:tpl-from-sym" select="$requniq">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="symtable" select="$package/preproc:symtable" />
|
|
</apply-templates>
|
|
</variable>
|
|
|
|
<!-- if we have recursed and have not decreased the application count at all,
|
|
then we have a problem -->
|
|
<if test="$requniq
|
|
and ( $package//preproc:sym-available )
|
|
and not( $package//preproc:repass[ @tpl-applied ] )">
|
|
<message terminate="yes">
|
|
<text>!!! [preproc] fatal: unable to locate symbols for </text>
|
|
<text>remaining templates: </text>
|
|
|
|
<for-each select="$requniq">
|
|
<if test="position() > 1">
|
|
<text>; </text>
|
|
</if>
|
|
|
|
<value-of select="@name" />
|
|
</for-each>
|
|
</message>
|
|
</if>
|
|
|
|
<!-- if there was an error during this part of the process, halt -->
|
|
<if test="$tpls//preproc:error">
|
|
<message terminate="yes">
|
|
<text>!!! [preproc] fatal: terminating due to errors</text>
|
|
</message>
|
|
</if>
|
|
|
|
<!-- perform expansion on the new package with the needed templates -->
|
|
<variable name="result" as="element( lv:package )">
|
|
<apply-templates select="$package" mode="preproc:compile">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="stopshort" select="true()" />
|
|
</apply-templates>
|
|
|
|
<message>
|
|
<text>[preproc] *expansion complete (recursive)</text>
|
|
</message>
|
|
</variable>
|
|
|
|
<!-- failsafe to prevent infinite recursion (5 (0-indexed)
|
|
should be plenty, since everything in the system results in
|
|
a template application in fewer steps -->
|
|
<if test="$requniq and $tpl-stall-count eq 4">
|
|
<message select="'!!! [preproc] internal: expansion deadlock!'" />
|
|
<message
|
|
select="'!!! [preproc] internal: stalled for 5 iterations'" />
|
|
|
|
<sequence select="preproc:dump-document( $result )" />
|
|
|
|
<message terminate="yes">
|
|
<text></text>
|
|
<text>!!! [preproc] fatal: expansion of remaining </text>
|
|
<text>templates aborted (have all been imported?): </text>
|
|
|
|
<for-each select="$requniq">
|
|
<if test="position() > 1">
|
|
<text>; </text>
|
|
</if>
|
|
|
|
<value-of select="@name" />
|
|
</for-each>
|
|
</message>
|
|
</if>
|
|
|
|
<!-- recurse to continue expanding if need be -->
|
|
<call-template name="preproc:tpl-sym-recurse">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="package" select="$result" />
|
|
<with-param name="tpl-stall-count"
|
|
tunnel="yes"
|
|
select="if ( $package//preproc:tpl-step ) then
|
|
0
|
|
else
|
|
$tpl-stall-count + 1" />
|
|
</call-template>
|
|
</when>
|
|
|
|
|
|
<!-- expansion sequences and template short-hand expansions that
|
|
have not yet taken place, due to one reason or another (too
|
|
few passes: bug as far as I'm concerned) -->
|
|
<when test="$package//lv:expand-sequence[
|
|
not( ancestor::lv:template
|
|
or ancestor::lv:apply-template ) ]
|
|
|$package//t:*[
|
|
not( ancestor::lv:template
|
|
or ancestor::lv:apply-template ) ]">
|
|
<message select="'[preproc] pending expansions still present'" />
|
|
|
|
<variable name="result" as="element( lv:package )">
|
|
<apply-templates select="$package" mode="preproc:compile">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="stopshort" select="true()" />
|
|
</apply-templates>
|
|
</variable>
|
|
|
|
<call-template name="preproc:tpl-sym-recurse">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="package" select="$result" />
|
|
</call-template>
|
|
</when>
|
|
|
|
|
|
<!-- no further applications are necessary -->
|
|
<otherwise>
|
|
<!-- apply one final pass for the eligibility class generation -->
|
|
<call-template name="preproc:elig-class-pass">
|
|
<with-param name="package" select="$package" />
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
</call-template>
|
|
</otherwise>
|
|
</choose>
|
|
</template>
|
|
|
|
|
|
<template name="preproc:elig-class-pass" as="element( lv:package )">
|
|
<param name="package" as="element( lv:package )" />
|
|
<param name="orig-root" as="element()" />
|
|
|
|
<variable name="final-pkg" as="element( lv:package )">
|
|
<apply-templates select="$package" mode="preproc:expand-elig-class">
|
|
<with-param name="orig-root" select="$package" />
|
|
</apply-templates>
|
|
</variable>
|
|
|
|
<!-- yield the final pass against the elig-class-augmented package -->
|
|
<apply-templates select="$final-pkg" mode="preproc:compile">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="stopshort" select="true()" />
|
|
</apply-templates>
|
|
</template>
|
|
|
|
|
|
<!--
|
|
This is but a shell of its former self.
|
|
|
|
We are no longer injecting templates, so this can be removed or
|
|
adapted to do just enough to verify that the template symbols exist.
|
|
-->
|
|
<template match="lv:apply-template" mode="preproc:tpl-from-sym">
|
|
<param name="orig-root" as="element()" />
|
|
|
|
<param name="symtable" as="element( preproc:symtable )"
|
|
select="root(.)/preproc:symtable" />
|
|
|
|
<variable name="tplname" select="@name" />
|
|
|
|
<variable name="sym" as="element( preproc:sym )?" select="
|
|
$symtable/preproc:sym[
|
|
@name=$tplname
|
|
and @type='tpl'
|
|
]
|
|
" />
|
|
|
|
<!-- if we have a symbol table, then attempt to locate it -->
|
|
<choose>
|
|
<!-- if we have located the template, then we know its source (@src must be
|
|
set, otherwise the template is defined in this package and should have
|
|
been available to begin with) -->
|
|
<when test="$sym">
|
|
<preproc:sym-available for="{$tplname}" />
|
|
</when>
|
|
|
|
<!-- nothing we can do yet -->
|
|
<otherwise>
|
|
<message>
|
|
<text>[preproc] template symbol not yet available: </text>
|
|
<value-of select="$tplname" />
|
|
</message>
|
|
</otherwise>
|
|
</choose>
|
|
</template>
|
|
|
|
|
|
<!-- TODO: we should use an attr besides _id; one more definitive -->
|
|
<template match="*[ @_id ]" mode="preproc:macropass" priority="9">
|
|
<!-- already preprocessed -->
|
|
<sequence select="." />
|
|
</template>
|
|
<template match="*[ @_id ]" mode="preproc:idize" priority="9">
|
|
<!-- already preprocessed -->
|
|
<sequence select="." />
|
|
</template>
|
|
|
|
|
|
|
|
<template match="preproc:repass-record" mode="preproc:idize" priority="9">
|
|
<!-- no longer needed; remove -->
|
|
</template>
|
|
|
|
|
|
<!-- do not idize preproc nodes (unneeded waste of cycles) -->
|
|
<template match="preproc:*" mode="preproc:idize" priority="5">
|
|
<sequence select="." />
|
|
</template>
|
|
|
|
<!-- do not idize templates (will cause processing problems) -->
|
|
<template match="lv:template" mode="preproc:idize" priority="5">
|
|
<sequence select="." />
|
|
</template>
|
|
|
|
|
|
<!--
|
|
Generates a unique id for each element and stores it as @_id
|
|
|
|
This allows the node set to be copied and maintain its identity.
|
|
-->
|
|
<template match="*" mode="preproc:idize" priority="1">
|
|
<variable name="id">
|
|
<value-of select="generate-id(.)" />
|
|
</variable>
|
|
|
|
<copy>
|
|
<sequence select="@*" />
|
|
|
|
<attribute name="_id">
|
|
<value-of select="$id" />
|
|
</attribute>
|
|
|
|
<apply-templates mode="preproc:idize" />
|
|
</copy>
|
|
</template>
|
|
|
|
|
|
<template match="lv:package" mode="preproc:resolv-syms" as="element( lv:package )"
|
|
priority="9">
|
|
<param name="orig-root" as="element()" />
|
|
<param name="rpcount" select="0" />
|
|
|
|
<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 } )" />
|
|
|
|
<variable name="symdep-map" as="map( xs:string, element( preproc:sym-dep ) )"
|
|
select="map:merge(
|
|
for $sym-dep in preproc:sym-deps/preproc:sym-dep
|
|
return map{ string( $sym-dep/@name ) : $sym-dep } )" />
|
|
|
|
<!-- arbitrary; intended to prevent infinite recursion -->
|
|
<!-- TODO: same method as for templates; ensure changes, but do not create
|
|
arbitrary limit -->
|
|
<if test="$rpcount = 100">
|
|
<sequence select="preproc:dump-document( root() )" />
|
|
|
|
<message terminate="yes">
|
|
<text>[preproc] !!! recursion limit reached in resolving `</text>
|
|
<value-of select="@name" />
|
|
<text>' symbols</text>
|
|
</message>
|
|
</if>
|
|
|
|
<variable name="result" as="element( lv:package )">
|
|
<copy>
|
|
<sequence select="@*" />
|
|
|
|
<message>
|
|
<text>[preproc] *resolving symbol attributes...</text>
|
|
</message>
|
|
|
|
<apply-templates mode="preproc:resolv-syms">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="symtable-map" select="$symtable-map" tunnel="yes" />
|
|
<with-param name="symdep-map" select="$symdep-map" tunnel="yes" />
|
|
</apply-templates>
|
|
</copy>
|
|
</variable>
|
|
|
|
<variable name="repass"
|
|
select="$result//preproc:symtable/preproc:repass" />
|
|
|
|
<choose>
|
|
<!-- repass scheduled; go for it -->
|
|
<when test="$repass">
|
|
<message>[preproc] *SYM REPASS*</message>
|
|
<message>
|
|
<text>[preproc] The following </text>
|
|
<value-of select="count( $repass )" />
|
|
<text> symbol(s) are still unresolved:</text>
|
|
</message>
|
|
|
|
<for-each select="$repass">
|
|
<message>
|
|
<text>[preproc] - </text>
|
|
<value-of select="@ref" />
|
|
</message>
|
|
</for-each>
|
|
|
|
<apply-templates select="$result" mode="preproc:resolv-syms">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
<with-param name="rpcount" select="$rpcount + 1" />
|
|
</apply-templates>
|
|
</when>
|
|
|
|
<!-- no repass needed; done -->
|
|
<otherwise>
|
|
<sequence select="$result" />
|
|
</otherwise>
|
|
</choose>
|
|
</template>
|
|
|
|
|
|
<template match="preproc:symtable" mode="preproc:resolv-syms" priority="5">
|
|
<param name="orig-root" as="element()" />
|
|
|
|
<copy>
|
|
<apply-templates mode="preproc:resolv-syms">
|
|
<with-param name="orig-root" select="$orig-root" />
|
|
</apply-templates>
|
|
</copy>
|
|
</template>
|
|
|
|
|
|
<!--
|
|
Calculate symbol dimensions by taking the highest dimension of its
|
|
dependencies
|
|
|
|
If all dependencies are not yet resolved, then schedule a repass.
|
|
-->
|
|
<template match="preproc:sym[ not( @src ) and @dim='?' ]" mode="preproc:resolv-syms" priority="5">
|
|
<param name="orig-root" as="element()" />
|
|
<param name="symtable-map" as="map(*)" tunnel="yes" />
|
|
<param name="symdep-map" as="map(*)" tunnel="yes" />
|
|
|
|
<variable name="name" select="@name" />
|
|
<variable name="pkg" as="element( lv:package )"
|
|
select="root(.)" />
|
|
|
|
<variable name="deps" as="element( preproc:sym-dep )?"
|
|
select="$symdep-map( $name )" />
|
|
|
|
<!-- TODO: make this fatal -->
|
|
<if test="empty( $deps ) and not( @no-deps = 'true' )">
|
|
<message select="concat( 'internal: failed to located dependencies for `',
|
|
$name, '''' )" />
|
|
</if>
|
|
|
|
<variable name="depsyms" as="element( preproc:sym )*"
|
|
select="for $ref in $deps/preproc:sym-ref
|
|
return $symtable-map( $ref/@name )" />
|
|
|
|
<choose>
|
|
<!-- unresolved dependency dimensions; defer until next pass -->
|
|
<when test="
|
|
$depsyms/@dim = '?'
|
|
">
|
|
<!-- schedule repass :x -->
|
|
<sequence select="." />
|
|
<preproc:repass src="preproc:sym resolv-syms"
|
|
ref="{$name}" />
|
|
</when>
|
|
|
|
<!-- all dependencies are resolved; calculate dimensions -->
|
|
<otherwise>
|
|
<variable name="max" as="xs:double"
|
|
select="if ( empty( $depsyms ) ) then
|
|
0
|
|
else
|
|
max( $depsyms/@dim )" />
|
|
|
|
<copy>
|
|
<sequence select="@*" />
|
|
<attribute name="dim" select="$max" />
|
|
<sequence select="*" />
|
|
</copy>
|
|
</otherwise>
|
|
</choose>
|
|
</template>
|
|
|
|
|
|
<template match="preproc:repass" mode="preproc:resolv-syms" priority="9">
|
|
<!-- strip -->
|
|
</template>
|
|
|
|
|
|
<template match="*" mode="preproc:resolv-syms" priority="1">
|
|
<sequence select="." />
|
|
</template>
|
|
|
|
|
|
<template match="lv:package" mode="preproc:pkg-validate">
|
|
<variable name="symbol-map">
|
|
<call-template name="get-symbol-map" />
|
|
</variable>
|
|
|
|
<variable name="err">
|
|
<apply-templates select="." mode="lvv:validate">
|
|
<with-param name="symbol-map" select="$symbol-map" />
|
|
</apply-templates>
|
|
</variable>
|
|
|
|
<apply-templates select="$err//lvv:error" mode="preproc:handle-lvv-errors">
|
|
<with-param name="document" select="." />
|
|
</apply-templates>
|
|
</template>
|
|
|
|
|
|
<template match="*|text()" mode="preproc:pkg-validate">
|
|
</template>
|
|
|
|
|
|
<!-- errors should cause a failure -->
|
|
<template match="lvv:error" mode="preproc:handle-lvv-errors" priority="5">
|
|
<param name="document" />
|
|
|
|
<!-- output error -->
|
|
<message>
|
|
<text>!!! </text>
|
|
<value-of select="@desc" />
|
|
|
|
<if test="@path != ''">
|
|
<text> (</text>
|
|
<value-of select="@path" />
|
|
<text>)</text>
|
|
</if>
|
|
|
|
<text>: </text>
|
|
<value-of select="." />
|
|
</message>
|
|
|
|
<!-- terminate after we've output each error -->
|
|
<if test="not( following-sibling::lvv:error )">
|
|
<!-- dump document for debugging -->
|
|
<sequence select="preproc:dump-document( $document )" />
|
|
<message terminate="yes">Compilation failed due to validation errors.</message>
|
|
</if>
|
|
</template>
|
|
|
|
|
|
<function name="preproc:dump-document">
|
|
<param name="document" />
|
|
|
|
<message>~~~~[begin document dump]~~~~</message>
|
|
<message select="$document" />
|
|
<message>~~~~[end document dump]~~~~</message>
|
|
<message>internal: document dumped.</message>
|
|
</function>
|
|
|
|
|
|
<template match="node()|text()" mode="preproc:handle-lvv-errors" priority="1">
|
|
</template>
|
|
|
|
</stylesheet>
|