Properly resolve paths of symbols of imports
This solves a long-standing problem whereby relative paths are not properly resolved, leading to incorrect symbol conflicts when relative paths to the same package vary between two imports. See doc/notes/path-processing for an illustration. * src/current/include/preproc/path.xsl (preproc:resolve-relative-import): Add function. (preproc:resolv-path, preproc:resolve-path, preproc:get-path): Add functions to invoke existing templates. * src/current/include/preproc/symtable.xsl (preproc:symimport): Use `preproc:resolve-relative-import'. * doc/notes/path-processing: Add notes.master
parent
7472cb882c
commit
52c1bb5ebe
|
@ -0,0 +1,65 @@
|
||||||
|
Path processing
|
||||||
|
---------------
|
||||||
|
Need rules that will work for both the existing scenario (B) and the new
|
||||||
|
scenario (A):
|
||||||
|
|
||||||
|
|
||||||
|
_
|
||||||
|
/ \
|
||||||
|
/ _ \
|
||||||
|
/ ___ \
|
||||||
|
/_/ \_\
|
||||||
|
---------
|
||||||
|
|
||||||
|
root = ../
|
||||||
|
package = suppliers/colony <--- /suppliers/colony
|
||||||
|
import = ../map/return/colony <--- /map/return/colony
|
||||||
|
|
||||||
|
mapimport = ../../suppliers/colony/gl <-- /suppliers/colony/gl
|
||||||
|
|
||||||
|
|
||||||
|
this is the root
|
||||||
|
/ \
|
||||||
|
v v
|
||||||
|
1) <..>/map/return/ | <..>/../suppliers/colony/gl
|
||||||
|
= ../suppliers/colony/gl
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
\ /
|
||||||
|
package name
|
||||||
|
|
||||||
|
2) strip root||(package base) from package import
|
||||||
|
= ../map/return | <../suppliers/>colony/gl
|
||||||
|
= colony/gl
|
||||||
|
^^^^^^^^^
|
||||||
|
` The relative path from package
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
____
|
||||||
|
| __ )
|
||||||
|
| _ \
|
||||||
|
| |_) |
|
||||||
|
|____/
|
||||||
|
-------
|
||||||
|
|
||||||
|
what about normal includes?
|
||||||
|
|
||||||
|
|
||||||
|
root = ../
|
||||||
|
package = suppliers/colony <--- /suppliers/colony
|
||||||
|
import = ../common/foo <--- /common/foo
|
||||||
|
|
||||||
|
subimport = bar/baz <--- /common/foo/bar/baz
|
||||||
|
|
||||||
|
|
||||||
|
one has root, other does not
|
||||||
|
/
|
||||||
|
v
|
||||||
|
1) <..>/common/ | bar/baz
|
||||||
|
= ../common/bar/baz
|
||||||
|
|
||||||
|
2) strip root||(package base) from package import
|
||||||
|
= ../common/bar/baz
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
` no such prefix,
|
||||||
|
so this is the relative path
|
|
@ -22,6 +22,7 @@
|
||||||
-->
|
-->
|
||||||
<stylesheet version="2.0"
|
<stylesheet version="2.0"
|
||||||
xmlns="http://www.w3.org/1999/XSL/Transform"
|
xmlns="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
xmlns:preproc="http://www.lovullo.com/rater/preproc">
|
xmlns:preproc="http://www.lovullo.com/rater/preproc">
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +60,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="preproc:get-path" as="xs:string">
|
||||||
|
<param name="path" />
|
||||||
|
|
||||||
|
<call-template name="preproc:get-path">
|
||||||
|
<with-param name="path" select="$path" />
|
||||||
|
</call-template>
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
<!-- FIXME: duplicate code with above -->
|
<!-- FIXME: duplicate code with above -->
|
||||||
<template name="preproc:get-basename">
|
<template name="preproc:get-basename">
|
||||||
<param name="path" />
|
<param name="path" />
|
||||||
|
@ -94,6 +104,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TODO: rename to preproc:resolve-path -->
|
||||||
<template name="preproc:resolv-path">
|
<template name="preproc:resolv-path">
|
||||||
<param name="path" />
|
<param name="path" />
|
||||||
|
|
||||||
|
@ -112,6 +123,26 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<function name="preproc:resolv-path" as="xs:string">
|
||||||
|
<param name="path" />
|
||||||
|
|
||||||
|
<variable name="result" as="xs:string*">
|
||||||
|
<call-template name="preproc:resolv-path">
|
||||||
|
<with-param name="path" select="$path" />
|
||||||
|
</call-template>
|
||||||
|
</variable>
|
||||||
|
|
||||||
|
<sequence select="string-join( $result, '' )" />
|
||||||
|
</function>
|
||||||
|
|
||||||
|
<!-- alias to the above -->
|
||||||
|
<function name="preproc:resolve-path" as="xs:string">
|
||||||
|
<param name="path" />
|
||||||
|
|
||||||
|
<sequence select="preproc:resolv-path( $path )" />
|
||||||
|
</function>
|
||||||
|
|
||||||
|
|
||||||
<!-- XXX: warning, this won't like 'foo../' -->
|
<!-- XXX: warning, this won't like 'foo../' -->
|
||||||
<template name="preproc:resolv-rel-path">
|
<template name="preproc:resolv-rel-path">
|
||||||
<param name="path" />
|
<param name="path" />
|
||||||
|
@ -244,4 +275,44 @@
|
||||||
</choose>
|
</choose>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Resolve relative package imports
|
||||||
|
|
||||||
|
This situation arises when a source package (src) imports another
|
||||||
|
package (src-import) that has a reference to an external symbol
|
||||||
|
(sub-import).
|
||||||
|
|
||||||
|
See /doc/notes/path-processing for an illustration.
|
||||||
|
-->
|
||||||
|
<function name="preproc:resolve-relative-import" as="xs:string">
|
||||||
|
<param name="src-root" as="xs:string" />
|
||||||
|
<param name="src-name" as="xs:string" />
|
||||||
|
<param name="src-import" as="xs:string" />
|
||||||
|
<param name="sub-import" as="xs:string" />
|
||||||
|
|
||||||
|
<variable name="src-prefix" as="xs:string"
|
||||||
|
select="concat( $src-root, '/', $src-name )" />
|
||||||
|
|
||||||
|
<!-- Step 1: resolve relative paths from sub-import -->
|
||||||
|
<variable name="src-import-dir" as="xs:string"
|
||||||
|
select="preproc:get-path( $src-import )" />
|
||||||
|
<variable name="sub-concat" as="xs:string"
|
||||||
|
select="if ( $src-import-dir ) then
|
||||||
|
preproc:resolve-path(
|
||||||
|
concat( $src-import-dir, '/', $sub-import ) )
|
||||||
|
else
|
||||||
|
$sub-import" />
|
||||||
|
|
||||||
|
<!-- Step 2: remove package name prefix, if present -->
|
||||||
|
<variable name="src-name-base" as="xs:string"
|
||||||
|
select="preproc:get-path( $src-name )" />
|
||||||
|
<variable name="src-prefix" as="xs:string"
|
||||||
|
select="concat( $src-root, $src-name-base, '/' )" />
|
||||||
|
<variable name="suffix" as="xs:string"
|
||||||
|
select="substring-after( $sub-concat, $src-prefix )" />
|
||||||
|
|
||||||
|
<sequence select="if ( $suffix ) then $suffix else $sub-concat" />
|
||||||
|
</function>
|
||||||
|
|
||||||
</stylesheet>
|
</stylesheet>
|
||||||
|
|
|
@ -521,12 +521,18 @@
|
||||||
<xsl:param name="no-extclass" select="@no-extclass" />
|
<xsl:param name="no-extclass" select="@no-extclass" />
|
||||||
<xsl:param name="keep-classes" select="@keep-classes" />
|
<xsl:param name="keep-classes" select="@keep-classes" />
|
||||||
|
|
||||||
<xsl:variable name="path" select="concat( $package, '.xmlo' )" />
|
<xsl:variable name="path" as="xs:string"
|
||||||
|
select="concat( $package, '.xmlo' )" />
|
||||||
<xsl:variable name="syms"
|
<xsl:variable name="syms"
|
||||||
select="document( $path, $orig-root )/lv:*/preproc:symtable" />
|
select="document( $path, $orig-root )/lv:*/preproc:symtable" />
|
||||||
|
|
||||||
<xsl:variable name="import-path" select="$package" />
|
<xsl:variable name="import-path" select="$package" />
|
||||||
|
|
||||||
|
<xsl:variable name="src-root" as="xs:string"
|
||||||
|
select="ancestor::lv:package/@__rootpath" />
|
||||||
|
<xsl:variable name="src-name" as="xs:string"
|
||||||
|
select="ancestor::lv:package/@name" />
|
||||||
|
|
||||||
<!-- if they're including a program package, do they realize what they're
|
<!-- if they're including a program package, do they realize what they're
|
||||||
doing!? -->
|
doing!? -->
|
||||||
<!-- FIXME: @allow-nonpkg is no longer accurate terminology; change to
|
<!-- FIXME: @allow-nonpkg is no longer accurate terminology; change to
|
||||||
|
@ -542,14 +548,6 @@
|
||||||
</xsl:message>
|
</xsl:message>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
|
||||||
<!-- determine our path from our name -->
|
|
||||||
<xsl:variable name="our-path">
|
|
||||||
<xsl:call-template name="preproc:get-path">
|
|
||||||
<xsl:with-param name="path"
|
|
||||||
select="ancestor::lv:package/@name" />
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
|
|
||||||
<!-- to keep everything consistent and to simplify package equality
|
<!-- to keep everything consistent and to simplify package equality
|
||||||
assertions, resolve relative paths -->
|
assertions, resolve relative paths -->
|
||||||
<xsl:variable name="import-default-path" select="$import-path" />
|
<xsl:variable name="import-default-path" select="$import-path" />
|
||||||
|
@ -626,23 +624,11 @@
|
||||||
itself) onto the existing relative path and resolving relative
|
itself) onto the existing relative path and resolving relative
|
||||||
paths -->
|
paths -->
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:call-template name="preproc:resolv-path">
|
<xsl:sequence select="preproc:resolve-relative-import(
|
||||||
<xsl:with-param name="path">
|
$src-root,
|
||||||
<!-- get the path of the import, sans package name -->
|
$src-name,
|
||||||
<xsl:variable name="path">
|
$import-path,
|
||||||
<xsl:call-template name="preproc:get-path">
|
@src )" />
|
||||||
<xsl:with-param name="path" select="$import-path" />
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
|
|
||||||
<!-- concatenate it with the existing relative path -->
|
|
||||||
<xsl:if test="not( $path = '' )">
|
|
||||||
<xsl:value-of select="concat( $path, '/' )" />
|
|
||||||
</xsl:if>
|
|
||||||
|
|
||||||
<xsl:value-of select="@src" />
|
|
||||||
</xsl:with-param>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:attribute>
|
</xsl:attribute>
|
||||||
|
|
Loading…
Reference in New Issue