diff options
-rw-r--r-- | doc/tame.texi | 2 | ||||
-rw-r--r-- | src/symtable.xsl | 101 | ||||
-rw-r--r-- | test/symtable.xspec | 146 |
3 files changed, 249 insertions, 0 deletions
diff --git a/doc/tame.texi b/doc/tame.texi index bd7f18e..ea3d9e1 100644 --- a/doc/tame.texi +++ b/doc/tame.texi @@ -53,6 +53,7 @@ Free Documentation License". @menu * Preprocessor:: Metaprogramming system * Dependency Graph:: Dependency processing and flow analysis +* Symbol Table:: Lookup table for all objects * License:: Document License @end menu @@ -109,6 +110,7 @@ Free Documentation License". @c chapter @raisesections @include ../src/graph.texi +@include ../src/symtable.texi @lowersections @include license.texi diff --git a/src/symtable.xsl b/src/symtable.xsl new file mode 100644 index 0000000..93a9923 --- /dev/null +++ b/src/symtable.xsl @@ -0,0 +1,101 @@ +<?xml version="1.0"?> +<!-- + Symbol table + + Copyright (C) 2016 LoVullo Associates, Inc. + + 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/>. +--> +<stylesheet version="2.0" + xmlns="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:f="http://mikegerwitz.com/hoxsl/apply" + xmlns:symtable="http://www.lovullo.com/tame/symtable" + xmlns:preproc="http://www.lovullo.com/rater/preproc"> + +<import href="symtable.xsl.apply" /> + + +<!-- + @node Symbol Table + @section Symbol Table + + The @dfn{symbol table} holds declarations for each symbol known to + a@tie{}particular package. + Symbol tables are represented by @code{preproc:syms} + elements.@footnote{ + The @code{preproc} namespace exists for legacy reasons; + it will change in the future.} + + A @dfn{symbol} is an abstract representation of some object@mdash{ + }a calculation, classification, typedef, etc.@mdash{ + }containing the source location and useful metadata. + @todo{Document symbol format and metadata.} + Symbols are represented by @code{preproc:sym} elements. +--> + + +<!-- + Produce a list of duplicate symbols in@tie{}@var{$symtable}, + grouped by @code{@@name}. + All duplicates will be returned@mdash{ + }that is, if @math{S_1} appears before duplicate @math{S_2} + in the symbol table, both@tie{}@math{S_1} and@tie{}@math{S_2} + will be returned. + + If two symbols have duplicate @code{@@name}s but the same + @code{@@src}, + then they are not considered to be duplicates, + @emph{unless} another duplicate symbol of the + same@tie{}@code{@@name} is found with a different @code{@@src}, + in which case all symbols will be returned. + This allows sloppy comparison on concatenated symbol tables before + tidying it up. + + Externs are ignored, since they represent symbols that need to be + satisfied at some point@mdash{ + }this will be checked during linking. + + Symbols (@code{preproc:sym} nodes) are returned by reference. + + This method name is ``find'' duplicates rather than ``get'' to + emphasize that processing is performed, which is potentially + intensive given a large symbol table@tie{}@var{$symtable}. +--> +<function name="symtable:find-duplicates" as="element( preproc:sym )*"> + <param name="symtable" as="element( preproc:syms )" /> + + <for-each-group select="$symtable/preproc:sym[ + not( @extern = 'true' ) ]" + group-by="@name"> + <!-- @src may be omitted to convey a local symbol --> + <variable name="srcs" as="xs:string*" + select="distinct-values( + for $sym in current-group() + return if ( exists( $sym/@src ) ) then + $sym/@src + else + '.' )" /> + + <sequence select="if ( count( $srcs ) gt 1 ) then + current-group() + else + ()" /> + </for-each-group> +</function> + +</stylesheet> diff --git a/test/symtable.xspec b/test/symtable.xspec new file mode 100644 index 0000000..c684cc4 --- /dev/null +++ b/test/symtable.xspec @@ -0,0 +1,146 @@ +<?xml version="1.0"?> +<!-- + Tests dependency graph + + Copyright (C) 2016 LoVullo Associates, Inc. + + 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/>. +--> +<description xmlns="http://www.jenitennison.com/xslt/xspec" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:x="http://www.jenitennison.com/xslt/xspec" + xmlns:symtable="http://www.lovullo.com/tame/symtable" + xmlns:preproc="http://www.lovullo.com/rater/preproc" + xmlns:foo="http://www.lovullo.com/_junk" + stylesheet="../src/symtable.xsl"> + + <variable name="table" as="element( preproc:syms )"> + <preproc:syms> + <preproc:sym name="dup-a" + src="dup-a-first" + foo:dup="true" /> + <preproc:sym name="dup-b" + src="dup-b-first" + foo:dup="true" /> + + <preproc:sym name="dup-a" + src="dup-a-second" + foo:dup="true" /> + <preproc:sym name="dup-b" + src="dup-b-second" + foo:dup="true" /> + <preproc:sym name="dup-b" + src="dup-b-third" + foo:dup="true" /> + + <!-- one of them is the same package as another; all three + should be recognized as duplicates so that the caller can + resolve or report intelligently --> + <preproc:sym name="dup-c-somesame" + src="dup-c-first" + foo:dup="true" /> + <preproc:sym name="dup-c-somesame" + src="dup-c-same" + foo:unique="first" + foo:dup="true" /> + <preproc:sym name="dup-c-somesame" + src="dup-c-same" + foo:unique="second" + foo:dup="true" /> + + <preproc:sym name="non-dup" + src="ok" /> + + <preproc:sym name="non-dup-samepkg" + src="same" /> + <preproc:sym name="non-dup-samepkg" + src="same" /> + + <!-- some symbols may be missing @src entirely to denote a local + symbol --> + <preproc:sym name="no-src" /> + + <!-- same package, no @src --> + <preproc:sym name="no-src-local" + foo:uniq="a" /> + <preproc:sym name="no-src-local" + foo:uniq="b" /> + + <!-- so it should be considered in determining a duplicate --> + <preproc:sym name="no-src-dup" + foo:uniq="a" + foo:dup="true" /> + <preproc:sym name="no-src-dup" + foo:uniq="b" + foo:dup="true" /> + <preproc:sym name="no-src-dup" + src="no-src" + foo:dup="true" /> + + <!-- ignore externs (one) --> + <preproc:sym name="extern-dup-one" + src="extern-a" /> + <preproc:sym name="extern-dup-one" + extern="true" + src="extern-b" /> + + <!-- ignore externs (both) --> + <preproc:sym name="extern-dup-both" + extern="true" + src="extern-a" /> + <preproc:sym name="extern-dup-both" + extern="true" + src="extern-b" /> + + <!-- ignore externs (combo) --> + <preproc:sym name="extern-dup-bothish" + src="extern-a" /> + <preproc:sym name="extern-dup-bothish" + extern="true" + src="extern-b" /> + <preproc:sym name="extern-dup-bothish" + extern="true" + src="extern-c" /> + </preproc:syms> + </variable> + + <variable name="dupes" as="element( preproc:sym )+" + select="$table/preproc:sym[ @foo:dup = 'true' ]" /> + + <variable name="distinct-dupes" as="xs:string+" + select="distinct-values( + $table/preproc:sym[ + @foo:dup = 'true' ]/@name )" /> + + + <scenario label="symtable:find-duplicates"> + <call function="symtable:find-duplicates"> + <param name="symtable" + select="$table" /> + </call> + + <expect label="finds all duplicates" + test="empty( $dupes except $x:result )" /> + + <expect label="does not find any non-duplicates" + test="empty( $x:result except $dupes )" /> + + <expect label="returns all duplicates by reference" + test="every $sym in $x:result + satisfies $sym/parent::* is $table" /> + </scenario> +</description> |