no more infinite boot times!
[jackhill/mal.git] / impls / xslt / step8_macros.inc.xslt
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Step 8: Macros -->
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 and atoms </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:core="CORE" 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 core">
12 <xsl:import href="reader.xslt"/>
13 <xsl:import href="printer.xslt"/>
14 <xsl:import href="env.xslt"/>
15 <xsl:import href="core.xslt"/>
16 <xsl:output method="xml" encoding="utf-8" indent="yes"/>
17 <xsl:template match="mal" name="rep">
18 <xsl:param name="display" select="false()" />
19 <xsl:choose>
20 <xsl:when test="string(state/env/@data) = ''">
21 <xsl:variable name="argv">
22 <malval kind="list">
23 <lvalue>
24 <xsl:for-each select="argv/arg/text()">
25 <malval kind="string" value="{.}"/>
26 </xsl:for-each>
27 </lvalue>
28 </malval>
29 </xsl:variable>
30 <xsl:variable name="vstate">
31 <mal>
32 <state>
33 <env data="{env:serialise(env:empty() =&gt; env:bind-all(core:ns()/@name, core:ns()) =&gt; env:set('*ARGV*', $argv) =&gt; env:toReplEnv())}"/>
34 <atoms/>
35 </state>
36 <stdin>(do (def! not (fn* (a) (if a false true))) (def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) "\nnil)"))))) (defmacro! cond (fn* (&amp; xs) (if (&gt; (count xs) 0) (list 'if (first xs) (if (&gt; (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond (rest (rest xs))))))))</stdin>
37 </mal>
38 </xsl:variable>
39 <xsl:variable name="new-state">
40 <xsl:for-each select="$vstate/mal">
41 <xsl:call-template name="rep"/>
42 </xsl:for-each>
43 </xsl:variable>
44 <xsl:variable name="state-v">
45 <xsl:sequence select="$new-state/mal/state"/>
46 <xsl:sequence select="stdin"/>
47 </xsl:variable>
48 <xsl:for-each select="$state-v">
49 <xsl:call-template name="rep">
50 <xsl:with-param name="display" select="$display"/>
51 </xsl:call-template>
52 </xsl:for-each>
53 </xsl:when>
54 <xsl:otherwise>
55 <mal>
56 <xsl:variable name="env" as="map(*)">
57 <xsl:sequence select="env:deserialise(state/env/@data)"/>
58 </xsl:variable>
59 <xsl:sequence select="stdin"/>
60 <xsl:variable name="_read">
61 <xsl:call-template name="READ"/>
62 </xsl:variable>
63 <xsl:variable name="_eval">
64 <xsl:for-each select="$_read">
65 <xsl:call-template name="EVAL">
66 <xsl:with-param name="env" select="$env"/>
67 </xsl:call-template>
68 </xsl:for-each>
69 </xsl:variable>
70 <xsl:for-each select="$_eval">
71 <xsl:variable name="_print">
72 <xsl:variable name="data">
73 <xsl:sequence select="data/value"/>
74 <xsl:sequence select="atoms[1]"/>
75 </xsl:variable>
76 <xsl:for-each select="$data">
77 <xsl:call-template name="PRINT"/>
78 </xsl:for-each>
79 </xsl:variable>
80 <xsl:if test="$display">
81 <xsl:message>
82 <request kind="display" value="{$_print}"/>
83 </xsl:message>
84 </xsl:if>
85 <state>
86 <env data="{env/@data}"/>
87 <xsl:sequence select="atoms[1]"/>
88 </state>
89 </xsl:for-each>
90 </mal>
91 </xsl:otherwise>
92 </xsl:choose>
93 </xsl:template>
94 <xsl:template name="PRINT">
95 <xsl:variable name="str">
96 <xsl:call-template name="malprinter-pr_str">
97 <xsl:with-param name="readably" select="true()"/>
98 </xsl:call-template>
99 </xsl:variable>
100 <xsl:value-of select="$str"/>
101 </xsl:template>
102 <xsl:template name="eval_ast">
103 <xsl:param name="env"/>
104 <xsl:param name="atoms"/>
105 <xsl:choose>
106 <xsl:when test="value/malval/@kind = 'symbol'">
107 <xsl:variable name="val">
108 <xsl:sequence select="env:get($env, value/malval/@value)"/>
109 </xsl:variable>
110 <value>
111 <xsl:sequence select="$val"/>
112 </value>
113 </xsl:when>
114 <xsl:when test="value/malval/@kind = 'list' or value/malval/@kind = 'vector' or value/malval/@kind = 'hash'">
115 <xsl:variable name="myctx">
116 <xsl:iterate select="value/malval/lvalue/malval">
117 <xsl:param name="atoms" select="$atoms"/>
118 <xsl:param name="xctx" select="()"/>
119 <xsl:on-completion>
120 <xsl:sequence select="$xctx/value/malval"/>
121 <xsl:sequence select="$atoms"/>
122 </xsl:on-completion>
123 <xsl:variable name="ctx">
124 <value>
125 <xsl:sequence select="."/>
126 </value>
127 <xsl:sequence select="$atoms"/>
128 </xsl:variable>
129 <xsl:variable name="xctxy">
130 <xsl:for-each select="$ctx">
131 <xsl:variable name="val">
132 <xsl:call-template name="EVAL">
133 <xsl:with-param name="env" select="$env"/>
134 <xsl:with-param name="encode-env" select="false()"/>
135 </xsl:call-template>
136 </xsl:variable>
137 <xsl:sequence select="$val/data/value"/>
138 <xsl:sequence select="$val/atoms"/>
139 </xsl:for-each>
140 </xsl:variable>
141 <xsl:next-iteration>
142 <xsl:with-param name="atoms" select="$xctxy/atoms"/>
143 <xsl:with-param name="xctx" select="$xctx, $xctxy"/>
144 </xsl:next-iteration>
145 </xsl:iterate>
146 </xsl:variable>
147 <value>
148 <malval kind="{value/malval/@kind}">
149 <lvalue>
150 <xsl:sequence select="$myctx/malval"/>
151 </lvalue>
152 </malval>
153 </value>
154 <xsl:sequence select="$myctx/atoms"/>
155 </xsl:when>
156 <xsl:otherwise>
157 <xsl:sequence select="."/>
158 <xsl:sequence select="$atoms"/>
159 </xsl:otherwise>
160 </xsl:choose>
161 </xsl:template>
162 <!-- uapply[env, fn, args] -->
163 <xsl:template name="uapply">
164 <xsl:param name="func"/>
165 <xsl:param name="args"/>
166 <xsl:param name="env"/>
167 <xsl:variable name="nenv" select="$env =&gt; env:hier(env:deserialise($func/malval/env/@data)) =&gt; env:close-with-binds($func/malval/binds/malval/@value, $args/value/malval/lvalue/malval)"/>
168 <xsl:variable name="body">
169 <value>
170 <xsl:sequence select="$func/malval/body/malval"/>
171 </value>
172 <xsl:sequence select="atoms[1]"/>
173 </xsl:variable>
174 <xsl:variable name="result">
175 <xsl:for-each select="$body">
176 <xsl:call-template name="EVAL">
177 <xsl:with-param name="env" select="$nenv"/>
178 </xsl:call-template>
179 </xsl:for-each>
180 </xsl:variable>
181 <xsl:sequence select="$result/data/value"/>
182 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($result/env/@data) =&gt; env:replEnv()))}"/>
183 <xsl:sequence select="$result/atoms[1]"/>
184 </xsl:template>
185 <xsl:template name="quasiquote">
186 <xsl:param name="ast"/>
187 <xsl:variable name="result">
188 <xsl:choose>
189 <xsl:when test="fn:is-pair($ast)">
190 <xsl:choose>
191 <xsl:when test="let $fst := $ast/lvalue/malval[1] return $fst/@kind = 'symbol' and $fst/@value = 'unquote'">
192 <xsl:sequence select="$ast/lvalue/malval[2]"/>
193 </xsl:when>
194 <xsl:when test="let $fst := $ast/lvalue/malval[1] return fn:is-pair($fst) and (let $fstfst := $fst/lvalue/malval[1] return $fstfst/@kind = 'symbol' and $fstfst/@value = 'splice-unquote')">
195 <malval kind="list">
196 <lvalue>
197 <malval kind="symbol" value="concat"/>
198 <xsl:sequence select="$ast/lvalue/malval[1]/lvalue/malval[2]"/>
199 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
200 <xsl:variable name="rest-">
201 <malval kind="list">
202 <lvalue>
203 <xsl:sequence select="$rest"/>
204 </lvalue>
205 </malval>
206 </xsl:variable>
207 <xsl:call-template name="quasiquote">
208 <xsl:with-param name="ast" select="$rest-"/>
209 </xsl:call-template>
210 </lvalue>
211 </malval>
212 </xsl:when>
213 <xsl:otherwise>
214 <malval kind="list">
215 <lvalue>
216 <malval kind="symbol" value="cons"/>
217 <xsl:variable name="first" select="$ast/lvalue/malval[1]"/>
218 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
219 <xsl:variable name="rest-">
220 <malval kind="list">
221 <lvalue>
222 <xsl:sequence select="$rest"/>
223 </lvalue>
224 </malval>
225 </xsl:variable>
226 <xsl:call-template name="quasiquote">
227 <xsl:with-param name="ast" select="$first"/>
228 </xsl:call-template>
229 <xsl:call-template name="quasiquote">
230 <xsl:with-param name="ast" select="$rest-/malval"/>
231 </xsl:call-template>
232 </lvalue>
233 </malval>
234 </xsl:otherwise>
235 </xsl:choose>
236 </xsl:when>
237 <xsl:otherwise>
238 <malval kind="list">
239 <lvalue>
240 <malval kind="symbol" value="quote"/>
241 <xsl:sequence select="$ast"/>
242 </lvalue>
243 </malval>
244 </xsl:otherwise>
245 </xsl:choose>
246 </xsl:variable>
247 <xsl:sequence select="$result"/>
248 </xsl:template>
249 <xsl:template name="macroexpand">
250 <xsl:param name="ast"/>
251 <xsl:param name="env"/>
252 <xsl:param name="encode-env"/>
253 <xsl:choose>
254 <xsl:when test="fn:is-macro-call($ast, $env)">
255 <xsl:variable name="fn" select="env:get($env, $ast/lvalue/malval[1]/@value)"/>
256 <xsl:variable name="args">
257 <value>
258 <malval kind="list">
259 <lvalue>
260 <xsl:sequence select="$ast/lvalue/malval[position() &gt; 1]"/>
261 </lvalue>
262 </malval>
263 </value>
264 </xsl:variable>
265 <xsl:variable name="new">
266 <xsl:call-template name="uapply">
267 <xsl:with-param name="func" select="$fn"/>
268 <xsl:with-param name="args" select="$args"/>
269 <xsl:with-param name="env" select="$env"/>
270 </xsl:call-template>
271 </xsl:variable>
272 <xsl:call-template name="macroexpand">
273 <xsl:with-param name="ast" select="$new/value/malval"/>
274 <xsl:with-param name="env" select="$env"/>
275 <xsl:with-param name="encode-env" select="$encode-env"/>
276 </xsl:call-template>
277 </xsl:when>
278 <xsl:otherwise>
279 <value>
280 <xsl:sequence select="$ast"/>
281 </value>
282 <xsl:sequence select="atoms[1]"/>
283 <xsl:if test="$encode-env">
284 <env data="{$env =&gt; env:serialise()}"/>
285 </xsl:if>
286 </xsl:otherwise>
287 </xsl:choose>
288 </xsl:template>
289 <xsl:template name="EVAL">
290 <xsl:param name="env"/>
291 <xsl:param name="encode-env" select="true()"/>
292 <xsl:variable name="atoms" select="atoms[1]"/>
293 <xsl:variable name="data">
294 <xsl:choose>
295 <xsl:when test="value/malval/@kind = 'list'">
296 <xsl:choose>
297 <xsl:when test="count(value/malval/lvalue/malval) = 0">
298 <xsl:sequence select="."/>
299 <xsl:if test="$encode-env">
300 <env data="{env:serialise($env)}"/>
301 </xsl:if>
302 <xsl:sequence select="$atoms"/>
303 </xsl:when>
304 <xsl:otherwise>
305 <xsl:variable name="mexp">
306 <xsl:call-template name="macroexpand">
307 <xsl:with-param name="ast" select="value/malval"/>
308 <xsl:with-param name="env" select="$env"/>
309 <xsl:with-param name="encode-env" select="$encode-env"/>
310 </xsl:call-template>
311 </xsl:variable>
312 <xsl:for-each select="$mexp">
313 <xsl:choose>
314 <xsl:when test="value/malval/@kind != 'list'">
315 <xsl:variable name="ctx">
316 <xsl:sequence select="value"/>
317 </xsl:variable>
318 <xsl:for-each select="$ctx">
319 <xsl:call-template name="eval_ast">
320 <xsl:with-param name="atoms" select="$atoms"/>
321 <xsl:with-param name="env" select="$env"/>
322 </xsl:call-template>
323 <xsl:if test="$encode-env">
324 <env data="{env:serialise($env)}"/>
325 </xsl:if>
326 <!-- <xsl:sequence select="$atoms"/> -->
327 </xsl:for-each>
328 </xsl:when>
329 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'def!'">
330 <xsl:variable name="name">
331 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
332 </xsl:variable>
333 <xsl:variable name="xvalue">
334 <value>
335 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
336 </value>
337 <xsl:sequence select="$atoms"/>
338 </xsl:variable>
339 <xsl:variable name="value">
340 <xsl:for-each select="$xvalue">
341 <xsl:call-template name="EVAL">
342 <xsl:with-param name="env" select="$env"/>
343 <xsl:with-param name="encode-env" select="false()"/>
344 </xsl:call-template>
345 </xsl:for-each>
346 </xsl:variable>
347 <xsl:sequence select="$value/data/value"/>
348 <xsl:if test="$encode-env">
349 <env data="{env:serialise(env:set($env, $name, $value/data/value/malval))}"/>
350 </xsl:if>
351 <xsl:sequence select="$value/atoms[1]"/>
352 </xsl:when>
353 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'defmacro!'">
354 <xsl:variable name="name">
355 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
356 </xsl:variable>
357 <xsl:variable name="xvalue">
358 <value>
359 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
360 </value>
361 <xsl:sequence select="$atoms"/>
362 </xsl:variable>
363 <xsl:variable name="value">
364 <xsl:for-each select="$xvalue">
365 <xsl:call-template name="EVAL">
366 <xsl:with-param name="env" select="$env"/>
367 <xsl:with-param name="encode-env" select="false()"/>
368 </xsl:call-template>
369 </xsl:for-each>
370 </xsl:variable>
371 <xsl:variable name="resv">
372 <value>
373 <malval kind="{$value/data/value/malval/@kind}" value="{$value/data/value/malval/@value}">
374 <xsl:sequence select="$value/data/value/malval/*[name() != 'is_macro']"/>
375 <is_macro>true</is_macro>
376 </malval>
377 </value>
378 </xsl:variable>
379 <xsl:sequence select="$resv"/>
380 <xsl:if test="$encode-env">
381 <env data="{env:serialise(env:set($env, $name, $resv/value/malval))}"/>
382 </xsl:if>
383 <xsl:sequence select="$resv/atoms[1]"/>
384 </xsl:when>
385 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'let*'">
386 <xsl:variable name="xvalue">
387 <value>
388 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
389 </value>
390 <xsl:sequence select="$atoms"/>
391 </xsl:variable>
392 <xsl:iterate select="fn:group_consec(value/malval/lvalue/malval[2]/lvalue/malval)">
393 <xsl:param name="new_env" select="env:close($env)"/>
394 <xsl:param name="new_atoms" select="$atoms"/>
395 <xsl:on-completion>
396 <xsl:variable name="xvalue">
397 <xsl:sequence select="$xvalue/value"/>
398 <xsl:sequence select="$new_atoms"/>
399 </xsl:variable>
400 <xsl:variable name="value">
401 <xsl:for-each select="$xvalue">
402 <xsl:call-template name="EVAL">
403 <xsl:with-param name="env" select="$new_env"/>
404 <xsl:with-param name="encode-env" select="$encode-env"/>
405 </xsl:call-template>
406 </xsl:for-each>
407 </xsl:variable>
408 <xsl:sequence select="$value/data/value"/>
409 <xsl:if test="$encode-env">
410 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) =&gt; env:replEnv()))}"/>
411 </xsl:if>
412 <xsl:sequence select="$value/atoms[1]"/>
413 </xsl:on-completion>
414 <xsl:variable name="name">
415 <xsl:value-of select="node()[name() = 'first']/malval/@value"/>
416 </xsl:variable>
417 <xsl:variable name="xvalue">
418 <value>
419 <xsl:sequence select="node()[name() = 'second']/malval"/>
420 </value>
421 <xsl:sequence select="$new_atoms"/>
422 </xsl:variable>
423 <xsl:variable name="value">
424 <xsl:for-each select="$xvalue">
425 <xsl:call-template name="EVAL">
426 <xsl:with-param name="env" select="$new_env"/>
427 <xsl:with-param name="encode-env" select="false()"/>
428 </xsl:call-template>
429 </xsl:for-each>
430 </xsl:variable>
431 <xsl:next-iteration>
432 <xsl:with-param name="new_env" select="env:set($new_env, $name, $value/data/value/malval)"/>
433 <xsl:with-param name="new_atoms" select="$value/atoms[1]"/>
434 </xsl:next-iteration>
435 </xsl:iterate>
436 </xsl:when>
437 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'do'">
438 <xsl:iterate select="value/malval/lvalue/malval[position() &gt; 1]">
439 <xsl:param name="new_env" select="$env"/>
440 <xsl:param name="atoms" select="$atoms"/>
441 <xsl:param name="previous_res" select="()"/>
442 <xsl:on-completion>
443 <xsl:sequence select="$previous_res"/>
444 <xsl:if test="$encode-env">
445 <env data="{env:serialise($new_env)}"/>
446 </xsl:if>
447 <xsl:sequence select="$atoms"/>
448 </xsl:on-completion>
449 <xsl:variable name="xvalue">
450 <value>
451 <xsl:sequence select="."/>
452 </value>
453 <xsl:sequence select="$atoms"/>
454 </xsl:variable>
455 <xsl:variable name="value">
456 <xsl:for-each select="$xvalue">
457 <xsl:call-template name="EVAL">
458 <xsl:with-param name="env" select="$new_env"/>
459 </xsl:call-template>
460 </xsl:for-each>
461 </xsl:variable>
462 <xsl:next-iteration>
463 <xsl:with-param name="new_env" select="env:deserialise($value/env/@data)"/>
464 <xsl:with-param name="previous_res" select="$value/data/value"/>
465 <xsl:with-param name="atoms" select="$value/atoms[1]"/>
466 </xsl:next-iteration>
467 </xsl:iterate>
468 </xsl:when>
469 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'if'">
470 <xsl:variable name="cond">
471 <xsl:for-each select="value/malval/lvalue/malval[2]">
472 <xsl:variable name="context">
473 <value>
474 <xsl:sequence select="."/>
475 </value>
476 <xsl:sequence select="$atoms"/>
477 </xsl:variable>
478 <xsl:for-each select="$context">
479 <xsl:call-template name="EVAL">
480 <xsl:with-param name="env" select="$env"/>
481 <xsl:with-param name="encode-env" select="false()"/>
482 </xsl:call-template>
483 </xsl:for-each>
484 </xsl:for-each>
485 </xsl:variable>
486 <xsl:variable name="ptrue">
487 <xsl:for-each select="value/malval/lvalue/malval[3]">
488 <value>
489 <xsl:sequence select="."/>
490 </value>
491 <xsl:sequence select="$cond/atoms[1]"/>
492 </xsl:for-each>
493 </xsl:variable>
494 <xsl:variable name="pfalse">
495 <xsl:for-each select="value/malval/lvalue/malval[4]">
496 <value>
497 <xsl:sequence select="."/>
498 </value>
499 <xsl:sequence select="$cond/atoms[1]"/>
500 </xsl:for-each>
501 </xsl:variable>
502 <xsl:variable name="xfalse">
503 <xsl:choose>
504 <xsl:when test="empty($pfalse/value)">
505 <value>
506 <malval kind="nil"/>
507 </value>
508 <xsl:sequence select="$cond/atoms[1]"/>
509 </xsl:when>
510 <xsl:otherwise>
511 <xsl:sequence select="$pfalse/value"/>
512 <xsl:sequence select="$pfalse/atoms[1]"/>
513 </xsl:otherwise>
514 </xsl:choose>
515 </xsl:variable>
516 <xsl:variable name="res">
517 <xsl:choose>
518 <xsl:when test="let $kind := $cond/data/value/malval/@kind return $kind = 'nil' or $kind = 'false'">
519 <xsl:for-each select="$xfalse">
520 <xsl:call-template name="EVAL">
521 <xsl:with-param name="env" select="$env"/>
522 <xsl:with-param name="encode-env" select="$encode-env"/>
523 </xsl:call-template>
524 </xsl:for-each>
525 </xsl:when>
526 <xsl:otherwise>
527 <xsl:for-each select="$ptrue">
528 <xsl:call-template name="EVAL">
529 <xsl:with-param name="env" select="$env"/>
530 <xsl:with-param name="encode-env" select="$encode-env"/>
531 </xsl:call-template>
532 </xsl:for-each>
533 </xsl:otherwise>
534 </xsl:choose>
535 </xsl:variable>
536 <xsl:sequence select="$res/data/value"/>
537 <xsl:if test="$encode-env">
538 <env data="{env:serialise($env)}"/>
539 </xsl:if>
540 <xsl:sequence select="$res/atoms[1]"/>
541 </xsl:when>
542 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'fn*'">
543 <value>
544 <malval kind="userfunction">
545 <is_macro>false</is_macro>
546 <binds>
547 <xsl:sequence select="value/malval/lvalue/malval[2]/lvalue/malval"/>
548 </binds>
549 <body>
550 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
551 </body>
552 <env data="{env:serialise(env:noReplEnv($env))}"/>
553 <!-- capture current env -->
554 </malval>
555 </value>
556 <xsl:if test="$encode-env">
557 <env data="{env:serialise($env)}"/>
558 </xsl:if>
559 <xsl:sequence select="$atoms"/>
560 </xsl:when>
561 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quote'">
562 <value>
563 <xsl:sequence select="value/malval/lvalue/malval[2]"/>
564 </value>
565 <xsl:if test="$encode-env">
566 <env data="{env:serialise($env)}"/>
567 </xsl:if>
568 <xsl:sequence select="$atoms"/>
569 </xsl:when>
570 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quasiquote'">
571 <xsl:variable name="exp">
572 <value>
573 <xsl:call-template name="quasiquote">
574 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
575 </xsl:call-template>
576 </value>
577 <xsl:sequence select="$atoms"/>
578 </xsl:variable>
579 <xsl:variable name="res">
580 <xsl:for-each select="$exp">
581 <xsl:call-template name="EVAL">
582 <xsl:with-param name="env" select="$env"/>
583 <xsl:with-param name="encode-env" select="$encode-env"/>
584 </xsl:call-template>
585 </xsl:for-each>
586 </xsl:variable>
587 <xsl:sequence select="$res/data/value"/>
588 <xsl:if test="$encode-env">
589 <xsl:sequence select="$res/env"/>
590 </xsl:if>
591 <xsl:sequence select="$res/atoms[1]"/>
592 </xsl:when>
593 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'macroexpand'">
594 <xsl:variable name="exp">
595 <xsl:call-template name="macroexpand">
596 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
597 <xsl:with-param name="env" select="$env"/>
598 <xsl:with-param name="encode-env" select="false()"/>
599 </xsl:call-template>
600 <xsl:sequence select="$atoms"/>
601 </xsl:variable>
602 <xsl:sequence select="$exp/value"/>
603 <xsl:if test="$encode-env">
604 <env data="{env:serialise($env)}"/>
605 </xsl:if>
606 <xsl:sequence select="$atoms"/>
607 </xsl:when>
608 <xsl:otherwise>
609 <xsl:variable name="new_list">
610 <xsl:call-template name="eval_ast">
611 <xsl:with-param name="atoms" select="$atoms"/>
612 <xsl:with-param name="env" select="$env"/>
613 </xsl:call-template>
614 </xsl:variable>
615 <xsl:variable name="func">
616 <xsl:for-each select="$new_list">
617 <xsl:sequence select="value/malval/lvalue/malval[1]"/>
618 </xsl:for-each>
619 </xsl:variable>
620 <xsl:variable name="args">
621 <xsl:for-each select="$new_list">
622 <value>
623 <malval kind="list">
624 <lvalue>
625 <xsl:for-each select="value/malval/lvalue/node()[position() != 1]">
626 <xsl:sequence select="."/>
627 </xsl:for-each>
628 </lvalue>
629 </malval>
630 </value>
631 <xsl:sequence select="$new_list/atoms"/>
632 </xsl:for-each>
633 </xsl:variable>
634 <xsl:variable name="resultv">
635 <xsl:choose>
636 <xsl:when test="$func/malval/@kind = 'userfunction'">
637 <xsl:call-template name="uapply">
638 <xsl:with-param name="env" select="$env"/>
639 <xsl:with-param name="func" select="$func"/>
640 <xsl:with-param name="args" select="$args"/>
641 </xsl:call-template>
642 </xsl:when>
643 <xsl:otherwise>
644 <xsl:choose>
645 <xsl:when test="$func/malval/@name = 'env??'">
646 <!-- needs access to env -->
647 <xsl:variable name="nev" select="env:dump($env)"/>
648 <xsl:variable name="value">
649 <malval kind="string" value="{$env =&gt; serialize(map{'method':'json'})}"/>
650 </xsl:variable>
651 <value>
652 <xsl:sequence select="$value"/>
653 </value>
654 <xsl:if test="$encode-env">
655 <env data="{env:serialise($env)}"/>
656 </xsl:if>
657 <xsl:sequence select="$value/atoms[1]"/>
658 </xsl:when>
659 <xsl:when test="$func/malval/@name = 'eval'">
660 <!-- needs access to env -->
661 <xsl:variable name="venv" select="env:replEnv($env)"/>
662 <xsl:variable name="form">
663 <value>
664 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
665 </value>
666 <xsl:sequence select="$atoms"/>
667 </xsl:variable>
668 <xsl:variable name="value">
669 <xsl:for-each select="$form">
670 <xsl:call-template name="EVAL">
671 <xsl:with-param name="env" select="$venv"/>
672 <xsl:with-param name="encode-env" select="$encode-env"/>
673 </xsl:call-template>
674 </xsl:for-each>
675 </xsl:variable>
676 <xsl:sequence select="$value/data/value"/>
677 <xsl:if test="$encode-env">
678 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data)))}"/>
679 </xsl:if>
680 <xsl:sequence select="$value/atoms[1]"/>
681 </xsl:when>
682 <xsl:when test="$func/malval/@name = 'atom'">
683 <!-- needs access to atoms -->
684 <xsl:variable name="atom-ident" select="count($atoms/atom)"/>
685 <value>
686 <malval kind="atom" value="{$atom-ident}"/>
687 </value>
688 <atoms>
689 <xsl:for-each select="$atoms/atom">
690 <xsl:sequence select="."/>
691 </xsl:for-each>
692 <atom identity="{$atom-ident}">
693 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
694 </atom>
695 </atoms>
696 </xsl:when>
697 <xsl:when test="$func/malval/@name = 'deref'">
698 <!-- needs access to atoms -->
699 <value>
700 <xsl:sequence select="$atoms/atom[@identity = $args/value/malval/lvalue/malval[1]/@value]/malval"/>
701 </value>
702 <xsl:sequence select="$atoms"/>
703 </xsl:when>
704 <xsl:when test="$func/malval/@name = 'reset!'">
705 <!-- needs access to atoms -->
706 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
707 <xsl:variable name="newv" select="$args/value/malval/lvalue/malval[2]"/>
708 <value>
709 <xsl:sequence select="$newv"/>
710 </value>
711 <atoms>
712 <xsl:for-each select="$atoms/atom[@identity != $atom-ident]">
713 <xsl:sequence select="."/>
714 </xsl:for-each>
715 <atom identity="{$atom-ident}">
716 <xsl:sequence select="$newv"/>
717 </atom>
718 </atoms>
719 </xsl:when>
720 <xsl:when test="$func/malval/@name = 'swap!'">
721 <!-- needs access to atoms -->
722 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
723 <xsl:variable name="atom-value" select="$atoms/atom[@identity = $atom-ident]/malval"/>
724 <xsl:variable name="fn" select="$args/value/malval/lvalue/malval[2]"/>
725 <xsl:variable name="newlist">
726 <value>
727 <malval kind="list">
728 <lvalue>
729 <xsl:sequence select="$fn"/>
730 <xsl:sequence select="$atom-value"/>
731 <xsl:sequence select="$args/value/malval/lvalue/malval[position() &gt; 2]"/>
732 </lvalue>
733 </malval>
734 </value>
735 <xsl:sequence select="$atoms"/>
736 </xsl:variable>
737 <xsl:variable name="newv">
738 <xsl:for-each select="$newlist">
739 <xsl:call-template name="EVAL">
740 <xsl:with-param name="env" select="$env"/>
741 <xsl:with-param name="encode-env" select="false()"/>
742 </xsl:call-template>
743 </xsl:for-each>
744 </xsl:variable>
745 <xsl:sequence select="$newv/data/value"/>
746 <atoms>
747 <xsl:for-each select="$newv/atoms[1]/atom[@identity != $atom-ident]">
748 <xsl:sequence select="."/>
749 </xsl:for-each>
750 <atom identity="{$atom-ident}">
751 <xsl:sequence select="$newv/data/value/malval"/>
752 </atom>
753 </atoms>
754 <xsl:sequence select="$newv/env"/>
755 </xsl:when>
756 <xsl:otherwise>
757 <xsl:call-template name="core-apply">
758 <xsl:with-param name="func" select="$func"/>
759 <xsl:with-param name="args" select="$args"/>
760 </xsl:call-template>
761 <xsl:sequence select="$atoms"/>
762 </xsl:otherwise>
763 </xsl:choose>
764 </xsl:otherwise>
765 </xsl:choose>
766 </xsl:variable>
767 <xsl:for-each select="$resultv">
768 <xsl:choose>
769 <xsl:when test="empty(env)">
770 <xsl:if test="$encode-env">
771 <env data="{env:serialise($env)}"/>
772 </xsl:if>
773 </xsl:when>
774 <xsl:otherwise>
775 <xsl:sequence select="env"/>
776 </xsl:otherwise>
777 </xsl:choose>
778 <xsl:sequence select="atoms[1]"/>
779 <xsl:sequence select="value"/>
780 </xsl:for-each>
781 </xsl:otherwise>
782 </xsl:choose>
783 </xsl:for-each>
784 </xsl:otherwise>
785 </xsl:choose>
786 </xsl:when>
787 <xsl:otherwise>
788 <xsl:call-template name="eval_ast">
789 <xsl:with-param name="atoms" select="$atoms"/>
790 <xsl:with-param name="env" select="$env"/>
791 </xsl:call-template>
792 <xsl:if test="$encode-env">
793 <env data="{env:serialise($env)}"/>
794 </xsl:if>
795 <!-- <xsl:sequence select="$atoms"/> -->
796 </xsl:otherwise>
797 </xsl:choose>
798 </xsl:variable>
799 <data>
800 <xsl:sequence select="$data/value"/>
801 </data>
802 <xsl:if test="$encode-env">
803 <env data="{$data/env/@data}"/>
804 </xsl:if>
805 <xsl:sequence select="$data/atoms[1]"/>
806 </xsl:template>
807 <xsl:template name="READ">
808 <xsl:variable name="context">
809 <str>
810 <xsl:copy-of select="stdin/text()"/>
811 </str>
812 </xsl:variable>
813 <xsl:variable name="form">
814 <xsl:sequence select="state/atoms[1]"/>
815 <xsl:for-each select="$context">
816 <xsl:call-template name="malreader-read_str"/>
817 </xsl:for-each>
818 </xsl:variable>
819 <xsl:for-each select="$form">
820 <xsl:if test="error">
821 <xsl:value-of select="error(QName('MAL', 'Error'), string(error))"/>
822 </xsl:if>
823 <xsl:sequence select="."/>
824 </xsl:for-each>
825 </xsl:template>
826 <xsl:function name="fn:group_consec">
827 <xsl:param name="nodes"/>
828 <xsl:variable name="groups">
829 <xsl:for-each-group select="$nodes" group-by="position() mod 2">
830 <xsl:choose>
831 <xsl:when test="position() = 1">
832 <first>
833 <xsl:sequence select="current-group()"/>
834 </first>
835 </xsl:when>
836 <xsl:otherwise>
837 <second>
838 <xsl:sequence select="current-group()"/>
839 </second>
840 </xsl:otherwise>
841 </xsl:choose>
842 </xsl:for-each-group>
843 </xsl:variable>
844 <xsl:iterate select="1 to count($groups/first/*)">
845 <element>
846 <xsl:variable name="idx" select="number(.)"/>
847 <first>
848 <xsl:sequence select="$groups/first/node()[position() = $idx]"/>
849 </first>
850 <second>
851 <xsl:sequence select="$groups/second/node()[position() = $idx]"/>
852 </second>
853 </element>
854 </xsl:iterate>
855 </xsl:function>
856 <xsl:function name="fn:is-pair">
857 <xsl:param name="list"/>
858 <xsl:sequence select="($list/@kind = 'list' or $list/@kind = 'vector') and count($list/lvalue/malval) != 0"/>
859 </xsl:function>
860 <xsl:function name="fn:is-macro-call">
861 <xsl:param name="ast"/>
862 <xsl:param name="env"/>
863 <xsl:variable name="res" select="$ast/@kind = 'list' and $ast/lvalue/malval[1]/@kind = 'symbol' and (let $fn := env:get-noerror($env, $ast/lvalue/malval[1]/@value) return not(empty($fn)) and $fn/malval/is_macro/text() = 'true')"/>
864 <xsl:sequence select="$res"/>
865 </xsl:function>
866 </xsl:stylesheet>