Change quasiquote algorithm
[jackhill/mal.git] / impls / xslt / printer.xslt
1 <?xml version="1.0" encoding="UTF-8"?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" version="3.0" exclude-result-prefixes="xsl xs fn">
3 <!-- expects input as a single <value><malval .../></value> -->
4 <!-- output of form <value>literal string</value> -->
5 <xsl:template name="malprinter-pr_str">
6 <xsl:param name="readably" as="xs:boolean"/>
7 <xsl:variable name="value">
8 <xsl:sequence select="value/malval"/>
9 <xsl:sequence select="atoms"/>
10 </xsl:variable>
11 <xsl:for-each select="$value">
12 <xsl:choose>
13 <xsl:when test="malval/@kind = 'true'">
14 <value>true</value>
15 </xsl:when>
16 <xsl:when test="malval/@kind = 'false'">
17 <value>false</value>
18 </xsl:when>
19 <xsl:when test="malval/@kind = 'nil'">
20 <value>nil</value>
21 </xsl:when>
22 <xsl:when test="malval/@kind = 'string'">
23 <value>
24 <xsl:value-of select="concat(
25 if ($readably) then
26 '&quot;'
27 else
28 '',
29
30 fn:desc_string(malval/@value, $readably),
31
32 if ($readably) then
33 '&quot;'
34 else
35 '')"/>
36 </value>
37 </xsl:when>
38 <xsl:when test="malval/@kind = 'keyword'">
39 <value>
40 <xsl:value-of select="concat(':', malval/@value)"/>
41 </value>
42 </xsl:when>
43 <xsl:when test="malval/@kind = 'symbol'">
44 <value>
45 <xsl:value-of select="malval/@value"/>
46 </value>
47 </xsl:when>
48 <xsl:when test="malval/@kind = 'number'">
49 <value>
50 <xsl:value-of select="malval/@value"/>
51 </value>
52 </xsl:when>
53 <xsl:when test="malval/@kind = 'list'">
54 <xsl:variable name="val">
55 <xsl:for-each select="malval/lvalue/malval">
56 <xsl:variable name="ctx">
57 <value>
58 <xsl:copy-of select="."/>
59 </value>
60 </xsl:variable>
61 <xsl:for-each select="$ctx">
62 <xsl:call-template name="malprinter-pr_str">
63 <xsl:with-param name="readably" select="$readably"/>
64 </xsl:call-template>
65 </xsl:for-each>
66 </xsl:for-each>
67 </xsl:variable>
68 <xsl:for-each select="$val">
69 <value>
70 <xsl:value-of select="concat('(', string-join(/value, ' '), ')')"/>
71 </value>
72 </xsl:for-each>
73 </xsl:when>
74 <xsl:when test="malval/@kind = 'vector'">
75 <xsl:variable name="val">
76 <xsl:for-each select="malval/lvalue/malval">
77 <xsl:variable name="ctx">
78 <value>
79 <xsl:copy-of select="."/>
80 </value>
81 </xsl:variable>
82 <xsl:for-each select="$ctx">
83 <xsl:call-template name="malprinter-pr_str">
84 <xsl:with-param name="readably" select="$readably"/>
85 </xsl:call-template>
86 </xsl:for-each>
87 </xsl:for-each>
88 </xsl:variable>
89 <xsl:for-each select="$val">
90 <value>
91 <xsl:value-of select="concat('[', string-join(/value, ' '), ']')"/>
92 </value>
93 </xsl:for-each>
94 </xsl:when>
95 <xsl:when test="malval/@kind = 'hash'">
96 <xsl:variable name="val">
97 <xsl:for-each select="malval/lvalue/malval">
98 <xsl:variable name="ctx">
99 <value>
100 <xsl:copy-of select="."/>
101 </value>
102 </xsl:variable>
103 <xsl:for-each select="$ctx">
104 <xsl:call-template name="malprinter-pr_str">
105 <xsl:with-param name="readably" select="$readably"/>
106 </xsl:call-template>
107 </xsl:for-each>
108 </xsl:for-each>
109 </xsl:variable>
110 <xsl:for-each select="$val">
111 <value>
112 <xsl:value-of select="concat('{', string-join(/value, ' '), '}')"/>
113 </value>
114 </xsl:for-each>
115 </xsl:when>
116 <xsl:when test="malval/@kind = 'function'">
117 <value>
118 <xsl:variable name="gt">?</xsl:variable>
119 <xsl:variable name="lt">?</xsl:variable>
120 <xsl:value-of select="concat('#', $lt, 'fn ', malval/@name, $gt)"/>
121 </value>
122 </xsl:when>
123 <xsl:when test="malval/@kind = 'userfunction'">
124 <value>
125 <xsl:variable name="gt">?</xsl:variable>
126 <xsl:variable name="lt">?</xsl:variable>
127 <xsl:value-of select="concat('#', $lt, 'function', $gt)"/>
128 </value>
129 </xsl:when>
130 <xsl:when test="malval/@kind = 'atom'">
131 <xsl:variable name="val" select="malval"/>
132 <xsl:variable name="inner">
133 <xsl:variable name="ctx">
134 <value>
135 <xsl:sequence select="atoms/atom[@identity = $val/@value]/malval"/>
136 </value>
137 </xsl:variable>
138 <xsl:for-each select="$ctx">
139 <xsl:call-template name="malprinter-pr_str">
140 <xsl:with-param name="readably" select="$readably"/>
141 </xsl:call-template>
142 </xsl:for-each>
143 </xsl:variable>
144 <value>
145 <xsl:value-of select="concat(
146 '(atom ',
147 (let $v := $inner/value
148 return if ($v = 'Unknown') then
149 concat('id=', string($val/@value), ' existing=', string-join(atoms/atom/@identity, ','))
150 else
151 $v),
152 ')')"/>
153 </value>
154 </xsl:when>
155 <xsl:otherwise>
156 <value>Unknown</value>
157 </xsl:otherwise>
158 </xsl:choose>
159 </xsl:for-each>
160 </xsl:template>
161 <xsl:function name="fn:desc_string" as="xs:string">
162 <xsl:param name="str" as="xs:string"/>
163 <xsl:param name="readable" as="xs:boolean"/>
164 <xsl:choose>
165 <xsl:when test="($readable)">
166 <xsl:variable name="sx">
167 <xsl:analyze-string select="$str" regex="(\\|&quot;|&#10;)">
168 <xsl:matching-substring>
169 <x>
170 <xsl:choose>
171 <xsl:when test="regex-group(1) = '\'">
172 <xsl:value-of select="'\\'"/>
173 </xsl:when>
174 <xsl:when test="regex-group(1) = '&quot;'">
175 <xsl:value-of select="'\&quot;'"/>
176 </xsl:when>
177 <xsl:otherwise>
178 <xsl:value-of select="'\n'"/>
179 </xsl:otherwise>
180 </xsl:choose>
181 </x>
182 </xsl:matching-substring>
183 <xsl:non-matching-substring>
184 <x>
185 <xsl:value-of select="."/>
186 </x>
187 </xsl:non-matching-substring>
188 </xsl:analyze-string>
189 </xsl:variable>
190 <xsl:value-of select="string-join($sx/x, '')"/>
191 </xsl:when>
192 <xsl:otherwise>
193 <xsl:value-of select="$str"/>
194 </xsl:otherwise>
195 </xsl:choose>
196 </xsl:function>
197 </xsl:stylesheet>