Break some lines to make the code more readable
[jackhill/mal.git] / impls / xslt / step3_env.inc.xslt
CommitLineData
e4882d7d
A
1<?xml version="1.0" encoding="UTF-8"?>
2<!-- Step 3: Environment -->
3<!-- input document must be in the following format -->
4<!--
5<mal>
6 <stdin>...stdin text...</stdin>
7 <stdout> ... ignored, omitted ... </stdout>
8 <state> contains env </state>
9</mal>
10-->
11<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:env="ENV" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" version="3.0" exclude-result-prefixes="fn xs map env">
12 <xsl:import href="reader.xslt"/>
13 <xsl:import href="printer.xslt"/>
14 <xsl:import href="env.xslt"/>
15 <xsl:output method="xml" encoding="utf-8" indent="yes"/>
16 <xsl:template match="mal" name="rep">
fd99084c 17 <xsl:param name="display" select="false()" />
e4882d7d
A
18 <mal>
19 <xsl:variable name="env" as="map(*)">
20 <xsl:sequence select="env:deserialise((state/env/@data, env:base())[1])"/>
21 </xsl:variable>
22 <xsl:sequence select="stdin"/>
23 <xsl:variable name="_read">
24 <xsl:call-template name="READ"/>
25 </xsl:variable>
26 <xsl:variable name="_eval">
27 <xsl:for-each select="$_read">
28 <xsl:call-template name="EVAL">
29 <xsl:with-param name="env" select="$env"/>
30 </xsl:call-template>
31 </xsl:for-each>
32 </xsl:variable>
33 <xsl:for-each select="$_eval">
fd99084c 34 <xsl:variable name="_print">
e4882d7d
A
35 <xsl:for-each select="data">
36 <xsl:call-template name="PRINT"/>
37 </xsl:for-each>
fd99084c
A
38 </xsl:variable>
39 <xsl:message>
40 <request kind="display" value="{$_print}"/>
41 </xsl:message>
e4882d7d
A
42 <state>
43 <env data="{env/@data}"/>
44 </state>
45 </xsl:for-each>
46 </mal>
47 </xsl:template>
48 <xsl:template name="PRINT">
49 <xsl:variable name="str">
50 <xsl:call-template name="malprinter-pr_str">
51 <xsl:with-param name="readably" select="true()"/>
52 </xsl:call-template>
53 </xsl:variable>
54 <xsl:value-of select="$str"/>
55 </xsl:template>
56 <xsl:template name="eval_ast">
57 <xsl:param name="env"/>
58 <xsl:choose>
59 <xsl:when test="value/malval/@kind = 'symbol'">
60 <xsl:variable name="val">
61 <xsl:sequence select="env:get($env, value/malval/@value)"/>
62 </xsl:variable>
63 <value>
64 <xsl:sequence select="$val"/>
65 </value>
66 </xsl:when>
67 <xsl:when test="value/malval/@kind = 'list'">
68 <value>
69 <malval kind="list">
70 <lvalue>
71 <xsl:for-each select="value/malval/lvalue/malval">
72 <xsl:variable name="ctx">
73 <value>
74 <xsl:sequence select="."/>
75 </value>
76 </xsl:variable>
77 <xsl:variable name="xctx">
78 <xsl:for-each select="$ctx">
79 <xsl:variable name="val">
80 <xsl:call-template name="EVAL">
81 <xsl:with-param name="env" select="$env"/>
82 <xsl:with-param name="encode-env" select="false()"/>
83 </xsl:call-template>
84 </xsl:variable>
85 <xsl:sequence select="$val/data/value"/>
86 </xsl:for-each>
87 </xsl:variable>
88 <xsl:sequence select="$xctx/value/malval"/>
89 </xsl:for-each>
90 </lvalue>
91 </malval>
92 </value>
93 </xsl:when>
94 <xsl:when test="value/malval/@kind = 'vector'">
95 <value>
96 <malval kind="vector">
97 <lvalue>
98 <xsl:for-each select="value/malval/lvalue/malval">
99 <xsl:variable name="ctx">
100 <value>
101 <xsl:sequence select="."/>
102 </value>
103 </xsl:variable>
104 <xsl:variable name="xctx">
105 <xsl:for-each select="$ctx">
106 <xsl:variable name="val">
107 <xsl:call-template name="EVAL">
108 <xsl:with-param name="env" select="$env"/>
109 <xsl:with-param name="encode-env" select="false()"/>
110 </xsl:call-template>
111 </xsl:variable>
112 <xsl:sequence select="$val/data/value"/>
113 </xsl:for-each>
114 </xsl:variable>
115 <xsl:sequence select="$xctx/value/malval"/>
116 </xsl:for-each>
117 </lvalue>
118 </malval>
119 </value>
120 </xsl:when>
121 <xsl:when test="value/malval/@kind = 'hash'">
122 <value>
123 <malval kind="hash">
124 <lvalue>
125 <xsl:for-each select="value/malval/lvalue/malval">
126 <xsl:variable name="ctx">
127 <value>
128 <xsl:sequence select="."/>
129 </value>
130 </xsl:variable>
131 <xsl:variable name="xctx">
132 <xsl:for-each select="$ctx">
133 <xsl:variable name="val">
134 <xsl:call-template name="EVAL">
135 <xsl:with-param name="env" select="$env"/>
136 <xsl:with-param name="encode-env" select="false()"/>
137 </xsl:call-template>
138 </xsl:variable>
139 <xsl:sequence select="$val/data/value"/>
140 </xsl:for-each>
141 </xsl:variable>
142 <xsl:sequence select="$xctx/value/malval"/>
143 </xsl:for-each>
144 </lvalue>
145 </malval>
146 </value>
147 </xsl:when>
148 <xsl:otherwise>
149 <xsl:sequence select="."/>
150 </xsl:otherwise>
151 </xsl:choose>
152 </xsl:template>
153 <!-- vapply[fn, args] :: fn/value/text() -->
154 <xsl:template name="vapply">
155 <xsl:param name="func"/>
156 <xsl:param name="args"/>
157 <xsl:choose>
158 <xsl:when test="$func/malval/@kind = 'function'">
159 <xsl:choose>
160 <xsl:when test="$func/malval/@name = '+'">
161 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) + number($args/value/malval/lvalue/malval[2]/@value)"/>
162 <xsl:sequence select="fn:makeMALType($result, 'number')"/>
163 </xsl:when>
164 <xsl:when test="$func/malval/@name = '-'">
165 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) - number($args/value/malval/lvalue/malval[2]/@value)"/>
166 <xsl:sequence select="fn:makeMALType($result, 'number')"/>
167 </xsl:when>
168 <xsl:when test="$func/malval/@name = '*'">
169 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) * number($args/value/malval/lvalue/malval[2]/@value)"/>
170 <xsl:sequence select="fn:makeMALType($result, 'number')"/>
171 </xsl:when>
172 <xsl:when test="$func/malval/@name = '/'">
173 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) div number($args/value/malval/lvalue/malval[2]/@value)"/>
174 <xsl:sequence select="fn:makeMALType($result, 'number')"/>
175 </xsl:when>
176 <xsl:otherwise>
177 <xsl:value-of select="error(QName('MAL', 'Error'), concat('Invalid function ', $func))"/>
178 </xsl:otherwise>
179 </xsl:choose>
180 </xsl:when>
181 <xsl:otherwise/>
182 </xsl:choose>
183 </xsl:template>
184 <xsl:template name="EVAL">
185 <xsl:param name="env"/>
186 <xsl:param name="encode-env" select="true()"/>
187 <xsl:variable name="data">
188 <xsl:choose>
189 <xsl:when test="value/malval/@kind = 'list'">
190 <xsl:choose>
191 <xsl:when test="count(value/malval/lvalue/malval) = 0">
192 <xsl:sequence select="."/>
193 <xsl:if test="$encode-env">
194 <env data="{env:serialise($env)}"/>
195 </xsl:if>
196 </xsl:when>
197 <xsl:otherwise>
198 <xsl:choose>
80e3d5eb
A
199 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
200 return $fn/@kind = 'symbol' and
201 $fn/@value = 'def!'">
e4882d7d
A
202 <xsl:variable name="name">
203 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
204 </xsl:variable>
205 <xsl:variable name="xvalue">
206 <value>
207 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
208 </value>
209 </xsl:variable>
210 <xsl:variable name="value">
211 <xsl:for-each select="$xvalue">
212 <xsl:call-template name="EVAL">
213 <xsl:with-param name="env" select="$env"/>
214 <xsl:with-param name="encode-env" select="false()"/>
215 </xsl:call-template>
216 </xsl:for-each>
217 </xsl:variable>
218 <xsl:sequence select="$value/data/value"/>
219 <xsl:if test="$encode-env">
220 <env data="{env:serialise(env:set($env, $name, $value/data/value/malval))}"/>
221 </xsl:if>
222 </xsl:when>
80e3d5eb
A
223 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
224 return $fn/@kind = 'symbol' and
225 $fn/@value = 'let*'">
e4882d7d
A
226 <xsl:variable name="xvalue">
227 <value>
228 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
229 </value>
230 </xsl:variable>
231 <xsl:variable name="new_env" select="env:close($env)"/>
232 <xsl:iterate select="fn:group_consec(value/malval/lvalue/malval[2]/lvalue/malval)">
233 <xsl:param name="new_env" select="$env"/>
234 <xsl:on-completion>
235 <xsl:variable name="value">
236 <xsl:for-each select="$xvalue">
237 <xsl:call-template name="EVAL">
238 <xsl:with-param name="env" select="$new_env"/>
239 <xsl:with-param name="encode-env" select="false()"/>
240 </xsl:call-template>
241 </xsl:for-each>
242 </xsl:variable>
243 <xsl:sequence select="$value/data/value"/>
244 <xsl:if test="$encode-env">
245 <env data="{env:serialise($env)}"/>
246 </xsl:if>
247 </xsl:on-completion>
248 <xsl:variable name="name">
249 <xsl:value-of select="node()[name() = 'first']/malval/@value"/>
250 </xsl:variable>
251 <xsl:variable name="xvalue">
252 <value>
253 <xsl:sequence select="node()[name() = 'second']/malval"/>
254 </value>
255 </xsl:variable>
256 <xsl:variable name="value">
257 <xsl:for-each select="$xvalue">
258 <xsl:call-template name="EVAL">
259 <xsl:with-param name="env" select="$new_env"/>
260 <xsl:with-param name="encode-env" select="false()"/>
261 </xsl:call-template>
262 </xsl:for-each>
263 </xsl:variable>
264 <xsl:next-iteration>
265 <xsl:with-param name="new_env" select="env:set($new_env, $name, $value/data/value/malval)"/>
266 </xsl:next-iteration>
267 </xsl:iterate>
268 </xsl:when>
269 <xsl:otherwise>
270 <xsl:variable name="new_list">
271 <xsl:call-template name="eval_ast">
272 <xsl:with-param name="env" select="$env"/>
273 </xsl:call-template>
274 </xsl:variable>
275 <xsl:variable name="func">
276 <xsl:for-each select="$new_list">
277 <xsl:sequence select="value/malval/lvalue/malval[1]"/>
278 </xsl:for-each>
279 </xsl:variable>
280 <xsl:variable name="args">
281 <xsl:for-each select="$new_list">
282 <value>
283 <malval kind="list">
284 <lvalue>
285 <xsl:for-each select="value/malval/lvalue/node()[position() != 1]">
286 <xsl:sequence select="."/>
287 </xsl:for-each>
288 </lvalue>
289 </malval>
290 </value>
291 </xsl:for-each>
292 </xsl:variable>
293 <xsl:call-template name="vapply">
294 <xsl:with-param name="func" select="$func"/>
295 <xsl:with-param name="args" select="$args"/>
296 </xsl:call-template>
297 <xsl:if test="$encode-env">
298 <env data="{env:serialise($env)}"/>
299 </xsl:if>
300 </xsl:otherwise>
301 </xsl:choose>
302 </xsl:otherwise>
303 </xsl:choose>
304 </xsl:when>
305 <xsl:otherwise>
306 <xsl:call-template name="eval_ast">
307 <xsl:with-param name="env" select="$env"/>
308 </xsl:call-template>
309 <xsl:if test="$encode-env">
310 <env data="{env:serialise($env)}"/>
311 </xsl:if>
312 </xsl:otherwise>
313 </xsl:choose>
314 </xsl:variable>
315 <data>
316 <xsl:sequence select="$data/value"/>
317 </data>
318 <xsl:if test="$encode-env">
319 <env data="{$data/env/@data}"/>
320 </xsl:if>
321 </xsl:template>
322 <xsl:template name="READ">
323 <xsl:variable name="context">
324 <str>
325 <xsl:copy-of select="stdin/text()"/>
326 </str>
327 </xsl:variable>
328 <xsl:variable name="form">
329 <xsl:for-each select="$context">
330 <xsl:call-template name="malreader-read_str"/>
331 </xsl:for-each>
332 </xsl:variable>
333 <xsl:for-each select="$form">
334 <xsl:if test="error">
335 <xsl:value-of select="error(QName('MAL', 'Error'), string(error))"/>
336 </xsl:if>
337 <xsl:copy-of select="."/>
338 </xsl:for-each>
339 </xsl:template>
340 <xsl:function name="fn:makeMALType">
341 <xsl:param name="value"/>
342 <xsl:param name="kind"/>
343 <value>
344 <malval kind="{$kind}" value="{$value}"/>
345 </value>
346 </xsl:function>
347 <xsl:function name="fn:group_consec">
348 <xsl:param name="nodes"/>
349 <xsl:variable name="groups">
350 <xsl:for-each-group select="$nodes" group-by="position() mod 2">
351 <xsl:choose>
352 <xsl:when test="position() = 1">
353 <first>
354 <xsl:sequence select="current-group()"/>
355 </first>
356 </xsl:when>
357 <xsl:otherwise>
358 <second>
359 <xsl:sequence select="current-group()"/>
360 </second>
361 </xsl:otherwise>
362 </xsl:choose>
363 </xsl:for-each-group>
364 </xsl:variable>
365 <xsl:iterate select="1 to count($groups/first/*)">
366 <element>
367 <xsl:variable name="idx" select="number(.)"/>
368 <first>
369 <xsl:sequence select="$groups/first/node()[position() = $idx]"/>
370 </first>
371 <second>
372 <xsl:sequence select="$groups/second/node()[position() = $idx]"/>
373 </second>
374 </element>
375 </xsl:iterate>
376 </xsl:function>
377</xsl:stylesheet>