diff options
author | Mike Gerwitz <gerwitzm@lovullo.com> | 2017-07-12 14:23:26 -0400 |
---|---|---|
committer | Mike Gerwitz <gerwitzm@lovullo.com> | 2017-07-12 14:23:26 -0400 |
commit | 7472cb882c0b2d13d7d8304b805e0a19c7cc38e4 (patch) | |
tree | 5626e9818edf36c31ccc10b00840552402512620 | |
parent | 5b9cfaec31431e1518ccc086b6c30102d0047135 (diff) | |
download | tame-7472cb882c0b2d13d7d8304b805e0a19c7cc38e4.tar.gz tame-7472cb882c0b2d13d7d8304b805e0a19c7cc38e4.tar.bz2 tame-7472cb882c0b2d13d7d8304b805e0a19c7cc38e4.zip |
Return map symbol support
This is a backwards-incompatible change that, like the input map,
requires the use of symbols in the return map. This will allow us to
forego the use of @keep and will have the return map be the authority
of what gets linked (all of its dependencies).
* src/current/compiler/map.xsl: Add symbol support to return-map.
-rw-r--r-- | src/current/compiler/map.xsl | 179 |
1 files changed, 120 insertions, 59 deletions
diff --git a/src/current/compiler/map.xsl b/src/current/compiler/map.xsl index 039400d..b4ec574 100644 --- a/src/current/compiler/map.xsl +++ b/src/current/compiler/map.xsl @@ -27,6 +27,9 @@ When linking, the special head and tail fragments of the topmost map should be used (that is, if A includes B and C, use A). + TODO: Just generate a normal package and use the package system; + this duplicates a lot of logic, and does so piecemeal and poorly. + XXX: This is tightly coupled with the Program UI; refactor to support any type of source. --> @@ -91,10 +94,15 @@ consistently with the rest of the system --> <variable name="pkg"> <lv:package name="{$__srcpkg}" lvmc:type="map"> + <!-- XXX: copied from expand.xsl! --> + <attribute name="name" select="$__srcpkg" /> + <attribute name="__rootpath" select="$__relroot" /> + <attribute name="preproc:name" select="$__srcpkg" /> + <!-- initial symbol table; full table will be generated below --> - <call-template name="lvmc:stub-symtable"> - <with-param name="type-prefix" select="'map'" /> - </call-template> + <call-template name="lvmc:stub-symtable"> + <with-param name="type-prefix" select="'map'" /> + </call-template> <!-- copy all source nodes --> <sequence select="node()" /> @@ -145,6 +153,8 @@ <!-- Generate a function that maps a set of rater outputs + + TODO: This is essentailly the same as the input map; refactor. --> <template match="lvm:return-map" mode="lvmc:compile" priority="8"> <param name="rater" /> @@ -157,46 +167,60 @@ <variable name="pkg"> <lv:package name="{$__srcpkg}" lvmc:type="retmap"> + <!-- XXX: copied from expand.xsl! --> + <attribute name="name" select="$__srcpkg" /> + <attribute name="__rootpath" select="$__relroot" /> + <attribute name="preproc:name" select="$__srcpkg" /> + <!-- initial symbol table; full table will be generated below --> <call-template name="lvmc:stub-symtable"> <with-param name="type-prefix" select="'retmap'" /> </call-template> - <!-- copy source data --> - <copy-of select="*" /> - - <preproc:fragments> - <!-- special fragment to be output as the head --> - <preproc:fragment id=":retmap:___head"> - <!-- use a callback just in case we need to make portions of this async in the - future --> - <text>function ( input, callback ) {</text> - <text>var output = {};</text> - </preproc:fragment> - - <apply-templates select="./lvm:*" mode="lvmc:compile"> - <with-param name="symtable" select="$dummy-symtable" /> - <with-param name="rater" select="$rater" /> - <with-param name="type" select="'retmap'" /> - </apply-templates> - - <!-- special fragment to be output as the foot --> - <preproc:fragment id=":retmap:___tail"> - <text>callback(output);</text> - <text>}</text> - </preproc:fragment> - </preproc:fragments> + <!-- copy source nodes --> + <apply-templates mode="preproc:expand" select="node()" /> </lv:package> </variable> - <!-- output the result after symbol processing --> - <call-template name="preproc:gen-deps"> - <with-param name="pkg" as="element( lv:package )"> - <apply-templates select="$pkg" mode="preproc:sym-discover"> - <with-param name="orig-root" select="." /> + <!-- process symbol table --> + <variable name="pkg-with-symtable" as="element( lv:package )"> + <call-template name="preproc:gen-deps"> + <with-param name="pkg" as="element( lv:package )"> + <apply-templates select="$pkg" mode="preproc:sym-discover"> + <with-param name="orig-root" select="." /> + </apply-templates> + </with-param> + </call-template> + </variable> + + <!-- final result with compiled fragments --> + <lv:package> + <sequence select="$pkg-with-symtable/@*, + $pkg-with-symtable/node()" /> + + <preproc:fragments> + <!-- special fragment to be output as the head --> + <preproc:fragment id=":retmap:___head"> + <!-- use a callback just in case we need to make portions of this async in the + future --> + <text>function( input, callback ) {</text> + <text>var output = {};</text> + </preproc:fragment> + + <!-- compile mapped --> + <apply-templates select="./lvm:*" mode="lvmc:compile"> + <with-param name="symtable" select="$pkg-with-symtable/preproc:symtable" /> + <with-param name="rater" select="$rater" /> + <with-param name="type" select="'retmap'" /> </apply-templates> - </with-param> - </call-template> + + <!-- special fragment to be output as the foot --> + <preproc:fragment id=":retmap:___tail"> + <text>callback(output);</text> + <text>};</text> + </preproc:fragment> + </preproc:fragments> + </lv:package> </template> @@ -210,6 +234,7 @@ same (future bug pending!) --> <preproc:sym name=":{$type-prefix}:___head" type="{$type-prefix}:head" + pollute="true" ignore-dup="true" /> <preproc:sym name=":{$type-prefix}:___tail" type="{$type-prefix}:tail" @@ -248,15 +273,15 @@ --> <template match="lvm:pass" mode="lvmc:compile" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> - <param name="type" /> + <param name="type" as="xs:string" /> <preproc:fragment id=":{$type}:{@name}"> <text>output['</text> <value-of select="@name" /> <text>']=</text> <call-template name="lvmc:gen-input-default"> - <with-param name="symtable" select="$symtable" /> - <with-param name="to" select="@name" /> + <with-param name="sym" + select="lvmc:get-symbol( $symtable, $type, @name, @name )" /> <with-param name="from" select="@name" /> </call-template> <text>;</text> @@ -303,8 +328,8 @@ <value-of select="@to" /> <text>']=</text> <call-template name="lvmc:gen-input-default"> - <with-param name="symtable" select="$symtable" /> - <with-param name="to" select="@to" /> + <with-param name="sym" + select="lvmc:get-symbol( $symtable, $type, @to, @from )" /> <with-param name="from" select="@from" /> </call-template> <text>;</text> @@ -324,14 +349,14 @@ </template> <template match="lvm:map[ @from - and root(.)/@lvmc:type = 'map' ]" + and root(.)/@lvmc:type = 'map' ]" mode="preproc:depgen" priority="5"> <!-- to the DSL --> <preproc:sym-ref name="{@to}" lax="true" /> </template> <template match="lvm:map[ @from - and root(.)/@lvmc:type = 'retmap' ]" + and root(.)/@lvmc:type = 'retmap' ]" mode="preproc:depgen" priority="5"> <!-- from the DSL --> <preproc:sym-ref name="{@from}" lax="true" /> @@ -404,26 +429,46 @@ <!-- - Generate a direct input mapping or, if a default exists for the field, use the - default if the input is an empty string ---> -<template name="lvmc:gen-input-default"> + Attempt to locate the expected symbol, and blow up otherwise. + + TODO: The retmap distinction muddies this; refactor to be agnostic + (onus on caller perhaps). + --> +<function name="lvmc:get-symbol" as="element( preproc:sym )?"> <param name="symtable" as="element( preproc:symtable )" /> - <param name="to" /> - <!-- use one or the other; latter takes precedence --> - <param name="from" /> - <param name="from-str" /> + <param name="type" as="xs:string" /> + <param name="to" as="xs:string" /> + <param name="from" as="xs:string?" /> + + <variable name="symname" as="xs:string?" + select="if ( $type = 'retmap' ) then $from else $to" /> <variable name="sym" as="element( preproc:sym )?" - select="$symtable/preproc:sym[ @name=$to and @src ]" /> + select="$symtable/preproc:sym[ @name=$symname and @src ]" /> + + <!-- for error message display --> + <variable name="srcdest" as="xs:string" + select="if ( $type = 'retmap' ) then 'source' else 'destination'" /> - <if test="not( $sym ) and not( $symtable/@lvmc:sym-ignore )"> + <if test="$symname and not( $sym ) and not( $symtable/@lvmc:sym-ignore )"> <message terminate="yes" select="concat( - 'error: unknown destination identifier `', - string( $to ), + 'error: unknown ', $srcdest, ' identifier `', + string( $symname ), ''' (did you import the package?)' )" /> </if> +</function> + + +<!-- + Generate a direct input mapping or, if a default exists for the field, use the + default if the input is an empty string. +--> +<template name="lvmc:gen-input-default"> + <param name="sym" as="element( preproc:sym )?" /> + <!-- use one or the other; latter takes precedence --> + <param name="from" /> + <param name="from-str" /> <variable name="from-var"> <choose> @@ -459,7 +504,7 @@ Maps a static value to the output --> <template match="lvm:map[ @value ]" mode="lvmc:compile" priority="5"> - <param name="type" /> + <param name="type" as="xs:string" /> <preproc:fragment id=":{$type}:{@to}"> <text>output['</text> @@ -483,7 +528,7 @@ <template match="lvm:map[*]" mode="lvmc:compile" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> <param name="rater" /> - <param name="type" /> + <param name="type" as="xs:string"/> <preproc:fragment id=":{$type}:{@to}"> <text>output['</text> @@ -493,6 +538,7 @@ <apply-templates select="./lvm:*" mode="lvmc:compile"> <with-param name="symtable" select="$symtable" /> <with-param name="rater" select="$rater" /> + <with-param name="type" select="$type" /> </apply-templates> <text>;</text> @@ -606,12 +652,21 @@ <template match="lvm:map//lvm:from[*]" mode="lvmc:compile" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> + <param name="type" as="xs:string" /> <variable name="to" select="ancestor::lvm:map/@to" /> <variable name="nested" as="xs:boolean" select="exists( ancestor::lvm:from )" /> + <!-- XXX: we rely on the side-effect of this blowing up if the + symbol does not exist --> + <variable name="sym" as="element( preproc:sym )?" + select="lvmc:get-symbol( $symtable, $type, $to, @name )" /> + + <!-- kluge to force function call (it's lazy) --> + <if test="not( $sym )" /> + <!-- oval = orig val --> <text>(function(oval){</text> <text>var val = ( (oval||'').length ) ? oval : [oval]; </text> @@ -631,6 +686,7 @@ <text>switch(''+val[i]){</text> <apply-templates mode="lvmc:compile"> <with-param name="symtable" select="$symtable" /> + <with-param name="type" select="$type" /> </apply-templates> <if test="not( lvm:default )"> @@ -646,8 +702,7 @@ <!-- otherwise, generate one --> <otherwise> <call-template name="lvmc:gen-input-default"> - <with-param name="symtable" select="$symtable" /> - <with-param name="to" select="$to" /> + <with-param name="sym" select="$sym" /> <with-param name="from-str"> <text>''+val[i]</text> </with-param> @@ -706,11 +761,12 @@ <template match="lvm:from/lvm:default" mode="lvmc:compile" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> + <param name="type" as="xs:string" /> <sequence select="concat( 'default:ret.push(', string-join( - lvmc:concat-compile( element(), (), $symtable ), + lvmc:concat-compile( element(), (), $symtable, $type), '' ), ');' )" /> </template> @@ -724,12 +780,14 @@ <template match="lvm:map//lvm:from/lvm:translate" mode="lvmc:compile" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> + <param name="type" as="xs:string" /> <text>case '</text> <value-of select="@key" /> <text>':</text> <apply-templates select="." mode="lvmc:compile-translate"> <with-param name="symtable" select="$symtable" /> + <with-param name="type" select="$type" /> </apply-templates> <text> break;</text> </template> @@ -738,11 +796,12 @@ <template match="lvm:translate[ element() ]" mode="lvmc:compile-translate" priority="5"> <param name="symtable" as="element( preproc:symtable )" /> + <param name="type" as="xs:string" /> <sequence select="concat( 'ret.push(', string-join( - lvmc:concat-compile( element(), @empty, $symtable ), + lvmc:concat-compile( element(), @empty, $symtable, $type ), '' ), ');' )" /> </template> @@ -752,6 +811,7 @@ <param name="children" as="element()+" /> <param name="default" as="xs:string?" /> <param name="symtable" as="element( preproc:symtable )" /> + <param name="type" as="xs:string" /> <text>(function(){</text> <!-- end result should compile into a (dynamic) string --> @@ -763,6 +823,7 @@ <apply-templates mode="lvmc:compile" select="."> <with-param name="symtable" select="$symtable" /> + <with-param name="type" select="$type" /> </apply-templates> </for-each> <text>;</text> |