Break some lines to make the code more readable
[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]
192 return $fst/@kind = 'symbol' and
193 $fst/@value = 'unquote'">
194 <xsl:sequence select="$ast/lvalue/malval[2]"/>
195 </xsl:when>
196 <xsl:when test="let $fst := $ast/lvalue/malval[1]
197 return fn:is-pair($fst) and
198 (let $fstfst := $fst/lvalue/malval[1]
199 return $fstfst/@kind = 'symbol' and
200 $fstfst/@value = 'splice-unquote')">
201 <malval kind="list">
202 <lvalue>
203 <malval kind="symbol" value="concat"/>
204 <xsl:sequence select="$ast/lvalue/malval[1]/lvalue/malval[2]"/>
205 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
206 <xsl:variable name="rest-">
207 <malval kind="list">
208 <lvalue>
209 <xsl:sequence select="$rest"/>
210 </lvalue>
211 </malval>
212 </xsl:variable>
213 <xsl:call-template name="quasiquote">
214 <xsl:with-param name="ast" select="$rest-"/>
215 </xsl:call-template>
216 </lvalue>
217 </malval>
218 </xsl:when>
219 <xsl:otherwise>
220 <malval kind="list">
221 <lvalue>
222 <malval kind="symbol" value="cons"/>
223 <xsl:variable name="first" select="$ast/lvalue/malval[1]"/>
224 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
225 <xsl:variable name="rest-">
226 <malval kind="list">
227 <lvalue>
228 <xsl:sequence select="$rest"/>
229 </lvalue>
230 </malval>
231 </xsl:variable>
232 <xsl:call-template name="quasiquote">
233 <xsl:with-param name="ast" select="$first"/>
234 </xsl:call-template>
235 <xsl:call-template name="quasiquote">
236 <xsl:with-param name="ast" select="$rest-/malval"/>
237 </xsl:call-template>
238 </lvalue>
239 </malval>
240 </xsl:otherwise>
241 </xsl:choose>
242 </xsl:when>
243 <xsl:otherwise>
244 <malval kind="list">
245 <lvalue>
246 <malval kind="symbol" value="quote"/>
247 <xsl:sequence select="$ast"/>
248 </lvalue>
249 </malval>
250 </xsl:otherwise>
251 </xsl:choose>
252 </xsl:variable>
253 <xsl:sequence select="$result"/>
254 </xsl:template>
255 <xsl:template name="macroexpand">
256 <xsl:param name="ast"/>
257 <xsl:param name="env"/>
258 <xsl:param name="encode-env"/>
259 <xsl:choose>
260 <xsl:when test="fn:is-macro-call($ast, $env)">
261 <xsl:variable name="fn" select="env:get($env, $ast/lvalue/malval[1]/@value)"/>
262 <xsl:variable name="args">
263 <value>
264 <malval kind="list">
265 <lvalue>
266 <xsl:sequence select="$ast/lvalue/malval[position() &gt; 1]"/>
267 </lvalue>
268 </malval>
269 </value>
270 </xsl:variable>
271 <xsl:variable name="new">
272 <xsl:call-template name="uapply">
273 <xsl:with-param name="func" select="$fn"/>
274 <xsl:with-param name="args" select="$args"/>
275 <xsl:with-param name="env" select="$env"/>
276 </xsl:call-template>
277 </xsl:variable>
278 <xsl:call-template name="macroexpand">
279 <xsl:with-param name="ast" select="$new/value/malval"/>
280 <xsl:with-param name="env" select="$env"/>
281 <xsl:with-param name="encode-env" select="$encode-env"/>
282 </xsl:call-template>
283 </xsl:when>
284 <xsl:otherwise>
285 <value>
286 <xsl:sequence select="$ast"/>
287 </value>
288 <xsl:sequence select="atoms[1]"/>
289 <xsl:if test="$encode-env">
290 <env data="{$env =&gt; env:serialise()}"/>
291 </xsl:if>
292 </xsl:otherwise>
293 </xsl:choose>
294 </xsl:template>
295 <xsl:template name="EVAL">
296 <xsl:param name="env"/>
297 <xsl:param name="encode-env" select="true()"/>
298 <xsl:variable name="atoms" select="atoms[1]"/>
299 <xsl:variable name="data">
300 <xsl:choose>
301 <xsl:when test="value/malval/@kind = 'list'">
302 <xsl:choose>
303 <xsl:when test="count(value/malval/lvalue/malval) = 0">
304 <xsl:sequence select="."/>
305 <xsl:if test="$encode-env">
306 <env data="{env:serialise($env)}"/>
307 </xsl:if>
308 <xsl:sequence select="$atoms"/>
309 </xsl:when>
310 <xsl:otherwise>
311 <xsl:variable name="mexp">
312 <xsl:call-template name="macroexpand">
313 <xsl:with-param name="ast" select="value/malval"/>
314 <xsl:with-param name="env" select="$env"/>
315 <xsl:with-param name="encode-env" select="$encode-env"/>
316 </xsl:call-template>
317 </xsl:variable>
318 <xsl:for-each select="$mexp">
319 <xsl:choose>
320 <xsl:when test="value/malval/@kind != 'list'">
321 <xsl:variable name="ctx">
322 <xsl:sequence select="value"/>
323 </xsl:variable>
324 <xsl:for-each select="$ctx">
325 <xsl:call-template name="eval_ast">
326 <xsl:with-param name="atoms" select="$atoms"/>
327 <xsl:with-param name="env" select="$env"/>
328 </xsl:call-template>
329 <xsl:if test="$encode-env">
330 <env data="{env:serialise($env)}"/>
331 </xsl:if>
332 <!-- <xsl:sequence select="$atoms"/> -->
333 </xsl:for-each>
334 </xsl:when>
335 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
336 return $fn/@kind = 'symbol' and
337 $fn/@value = 'def!'">
338 <xsl:variable name="name">
339 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
340 </xsl:variable>
341 <xsl:variable name="xvalue">
342 <value>
343 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
344 </value>
345 <xsl:sequence select="$atoms"/>
346 </xsl:variable>
347 <xsl:variable name="value">
348 <xsl:for-each select="$xvalue">
349 <xsl:call-template name="EVAL">
350 <xsl:with-param name="env" select="$env"/>
351 <xsl:with-param name="encode-env" select="false()"/>
352 </xsl:call-template>
353 </xsl:for-each>
354 </xsl:variable>
355 <xsl:sequence select="$value/data/value"/>
356 <xsl:if test="$encode-env">
357 <env data="{env:serialise(env:set($env, $name, $value/data/value/malval))}"/>
358 </xsl:if>
359 <xsl:sequence select="$value/atoms[1]"/>
360 </xsl:when>
361 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
362 return $fn/@kind = 'symbol' and
363 $fn/@value = 'defmacro!'">
364 <xsl:variable name="name">
365 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
366 </xsl:variable>
367 <xsl:variable name="xvalue">
368 <value>
369 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
370 </value>
371 <xsl:sequence select="$atoms"/>
372 </xsl:variable>
373 <xsl:variable name="value">
374 <xsl:for-each select="$xvalue">
375 <xsl:call-template name="EVAL">
376 <xsl:with-param name="env" select="$env"/>
377 <xsl:with-param name="encode-env" select="false()"/>
378 </xsl:call-template>
379 </xsl:for-each>
380 </xsl:variable>
381 <xsl:variable name="resv">
382 <value>
383 <malval kind="{$value/data/value/malval/@kind}" value="{$value/data/value/malval/@value}">
384 <xsl:sequence select="$value/data/value/malval/*[name() != 'is_macro']"/>
385 <is_macro>true</is_macro>
386 </malval>
387 </value>
388 </xsl:variable>
389 <xsl:sequence select="$resv"/>
390 <xsl:if test="$encode-env">
391 <env data="{env:serialise(env:set($env, $name, $resv/value/malval))}"/>
392 </xsl:if>
393 <xsl:sequence select="$resv/atoms[1]"/>
394 </xsl:when>
395 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
396 return $fn/@kind = 'symbol' and
397 $fn/@value = 'let*'">
398 <xsl:variable name="xvalue">
399 <value>
400 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
401 </value>
402 <xsl:sequence select="$atoms"/>
403 </xsl:variable>
404 <xsl:iterate select="fn:group_consec(value/malval/lvalue/malval[2]/lvalue/malval)">
405 <xsl:param name="new_env" select="env:close($env)"/>
406 <xsl:param name="new_atoms" select="$atoms"/>
407 <xsl:on-completion>
408 <xsl:variable name="xvalue">
409 <xsl:sequence select="$xvalue/value"/>
410 <xsl:sequence select="$new_atoms"/>
411 </xsl:variable>
412 <xsl:variable name="value">
413 <xsl:for-each select="$xvalue">
414 <xsl:call-template name="EVAL">
415 <xsl:with-param name="env" select="$new_env"/>
416 <xsl:with-param name="encode-env" select="$encode-env"/>
417 </xsl:call-template>
418 </xsl:for-each>
419 </xsl:variable>
420 <xsl:sequence select="$value/data/value"/>
421 <xsl:if test="$encode-env">
422 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) =&gt; env:replEnv()))}"/>
423 </xsl:if>
424 <xsl:sequence select="$value/atoms[1]"/>
425 </xsl:on-completion>
426 <xsl:variable name="name">
427 <xsl:value-of select="node()[name() = 'first']/malval/@value"/>
428 </xsl:variable>
429 <xsl:variable name="xvalue">
430 <value>
431 <xsl:sequence select="node()[name() = 'second']/malval"/>
432 </value>
433 <xsl:sequence select="$new_atoms"/>
434 </xsl:variable>
435 <xsl:variable name="value">
436 <xsl:for-each select="$xvalue">
437 <xsl:call-template name="EVAL">
438 <xsl:with-param name="env" select="$new_env"/>
439 <xsl:with-param name="encode-env" select="false()"/>
440 </xsl:call-template>
441 </xsl:for-each>
442 </xsl:variable>
443 <xsl:next-iteration>
444 <xsl:with-param name="new_env" select="env:set($new_env, $name, $value/data/value/malval)"/>
445 <xsl:with-param name="new_atoms" select="$value/atoms[1]"/>
446 </xsl:next-iteration>
447 </xsl:iterate>
448 </xsl:when>
449 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
450 return $fn/@kind = 'symbol' and
451 $fn/@value = 'do'">
452 <xsl:iterate select="value/malval/lvalue/malval[position() &gt; 1]">
453 <xsl:param name="new_env" select="$env"/>
454 <xsl:param name="atoms" select="$atoms"/>
455 <xsl:param name="previous_res" select="()"/>
456 <xsl:on-completion>
457 <xsl:sequence select="$previous_res"/>
458 <xsl:if test="$encode-env">
459 <env data="{env:serialise($new_env)}"/>
460 </xsl:if>
461 <xsl:sequence select="$atoms"/>
462 </xsl:on-completion>
463 <xsl:variable name="xvalue">
464 <value>
465 <xsl:sequence select="."/>
466 </value>
467 <xsl:sequence select="$atoms"/>
468 </xsl:variable>
469 <xsl:variable name="value">
470 <xsl:for-each select="$xvalue">
471 <xsl:call-template name="EVAL">
472 <xsl:with-param name="env" select="$new_env"/>
473 </xsl:call-template>
474 </xsl:for-each>
475 </xsl:variable>
476 <xsl:next-iteration>
477 <xsl:with-param name="new_env" select="env:deserialise($value/env/@data)"/>
478 <xsl:with-param name="previous_res" select="$value/data/value"/>
479 <xsl:with-param name="atoms" select="$value/atoms[1]"/>
480 </xsl:next-iteration>
481 </xsl:iterate>
482 </xsl:when>
483 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
484 return $fn/@kind = 'symbol' and
485 $fn/@value = 'if'">
486 <xsl:variable name="cond">
487 <xsl:for-each select="value/malval/lvalue/malval[2]">
488 <xsl:variable name="context">
489 <value>
490 <xsl:sequence select="."/>
491 </value>
492 <xsl:sequence select="$atoms"/>
493 </xsl:variable>
494 <xsl:for-each select="$context">
495 <xsl:call-template name="EVAL">
496 <xsl:with-param name="env" select="$env"/>
497 <xsl:with-param name="encode-env" select="false()"/>
498 </xsl:call-template>
499 </xsl:for-each>
500 </xsl:for-each>
501 </xsl:variable>
502 <xsl:variable name="ptrue">
503 <xsl:for-each select="value/malval/lvalue/malval[3]">
504 <value>
505 <xsl:sequence select="."/>
506 </value>
507 <xsl:sequence select="$cond/atoms[1]"/>
508 </xsl:for-each>
509 </xsl:variable>
510 <xsl:variable name="pfalse">
511 <xsl:for-each select="value/malval/lvalue/malval[4]">
512 <value>
513 <xsl:sequence select="."/>
514 </value>
515 <xsl:sequence select="$cond/atoms[1]"/>
516 </xsl:for-each>
517 </xsl:variable>
518 <xsl:variable name="xfalse">
519 <xsl:choose>
520 <xsl:when test="empty($pfalse/value)">
521 <value>
522 <malval kind="nil"/>
523 </value>
524 <xsl:sequence select="$cond/atoms[1]"/>
525 </xsl:when>
526 <xsl:otherwise>
527 <xsl:sequence select="$pfalse/value"/>
528 <xsl:sequence select="$pfalse/atoms[1]"/>
529 </xsl:otherwise>
530 </xsl:choose>
531 </xsl:variable>
532 <xsl:variable name="res">
533 <xsl:choose>
534 <xsl:when test="let $kind := $cond/data/value/malval/@kind
535 return $kind = 'nil' or
536 $kind = 'false'">
537 <xsl:for-each select="$xfalse">
538 <xsl:call-template name="EVAL">
539 <xsl:with-param name="env" select="$env"/>
540 <xsl:with-param name="encode-env" select="$encode-env"/>
541 </xsl:call-template>
542 </xsl:for-each>
543 </xsl:when>
544 <xsl:otherwise>
545 <xsl:for-each select="$ptrue">
546 <xsl:call-template name="EVAL">
547 <xsl:with-param name="env" select="$env"/>
548 <xsl:with-param name="encode-env" select="$encode-env"/>
549 </xsl:call-template>
550 </xsl:for-each>
551 </xsl:otherwise>
552 </xsl:choose>
553 </xsl:variable>
554 <xsl:sequence select="$res/data/value"/>
555 <xsl:if test="$encode-env">
556 <env data="{env:serialise($env)}"/>
557 </xsl:if>
558 <xsl:sequence select="$res/atoms[1]"/>
559 </xsl:when>
560 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
561 return $fn/@kind = 'symbol' and
562 $fn/@value = 'fn*'">
563 <value>
564 <malval kind="userfunction">
565 <is_macro>false</is_macro>
566 <binds>
567 <xsl:sequence select="value/malval/lvalue/malval[2]/lvalue/malval"/>
568 </binds>
569 <body>
570 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
571 </body>
572 <env data="{env:serialise(env:noReplEnv($env))}"/>
573 <!-- capture current env -->
574 </malval>
575 </value>
576 <xsl:if test="$encode-env">
577 <env data="{env:serialise($env)}"/>
578 </xsl:if>
579 <xsl:sequence select="$atoms"/>
580 </xsl:when>
581 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
582 return $fn/@kind = 'symbol' and
583 $fn/@value = 'quote'">
584 <value>
585 <xsl:sequence select="value/malval/lvalue/malval[2]"/>
586 </value>
587 <xsl:if test="$encode-env">
588 <env data="{env:serialise($env)}"/>
589 </xsl:if>
590 <xsl:sequence select="$atoms"/>
591 </xsl:when>
592 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
593 return $fn/@kind = 'symbol' and
594 $fn/@value = 'quasiquote'">
595 <xsl:variable name="exp">
596 <value>
597 <xsl:call-template name="quasiquote">
598 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
599 </xsl:call-template>
600 </value>
601 <xsl:sequence select="$atoms"/>
602 </xsl:variable>
603 <xsl:variable name="res">
604 <xsl:for-each select="$exp">
605 <xsl:call-template name="EVAL">
606 <xsl:with-param name="env" select="$env"/>
607 <xsl:with-param name="encode-env" select="$encode-env"/>
608 </xsl:call-template>
609 </xsl:for-each>
610 </xsl:variable>
611 <xsl:sequence select="$res/data/value"/>
612 <xsl:if test="$encode-env">
613 <xsl:sequence select="$res/env"/>
614 </xsl:if>
615 <xsl:sequence select="$res/atoms[1]"/>
616 </xsl:when>
617 <xsl:when test="let $fn := value/malval/lvalue/malval[1]
618 return $fn/@kind = 'symbol' and
619 $fn/@value = 'macroexpand'">
620 <xsl:variable name="exp">
621 <xsl:call-template name="macroexpand">
622 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
623 <xsl:with-param name="env" select="$env"/>
624 <xsl:with-param name="encode-env" select="false()"/>
625 </xsl:call-template>
626 <xsl:sequence select="$atoms"/>
627 </xsl:variable>
628 <xsl:sequence select="$exp/value"/>
629 <xsl:if test="$encode-env">
630 <env data="{env:serialise($env)}"/>
631 </xsl:if>
632 <xsl:sequence select="$atoms"/>
633 </xsl:when>
634 <xsl:otherwise>
635 <xsl:variable name="new_list">
636 <xsl:call-template name="eval_ast">
637 <xsl:with-param name="atoms" select="$atoms"/>
638 <xsl:with-param name="env" select="$env"/>
639 </xsl:call-template>
640 </xsl:variable>
641 <xsl:variable name="func">
642 <xsl:for-each select="$new_list">
643 <xsl:sequence select="value/malval/lvalue/malval[1]"/>
644 </xsl:for-each>
645 </xsl:variable>
646 <xsl:variable name="args">
647 <xsl:for-each select="$new_list">
648 <value>
649 <malval kind="list">
650 <lvalue>
651 <xsl:for-each select="value/malval/lvalue/node()[position() != 1]">
652 <xsl:sequence select="."/>
653 </xsl:for-each>
654 </lvalue>
655 </malval>
656 </value>
657 <xsl:sequence select="$new_list/atoms"/>
658 </xsl:for-each>
659 </xsl:variable>
660 <xsl:variable name="resultv">
661 <xsl:choose>
662 <xsl:when test="$func/malval/@kind = 'userfunction'">
663 <xsl:call-template name="uapply">
664 <xsl:with-param name="env" select="$env"/>
665 <xsl:with-param name="func" select="$func"/>
666 <xsl:with-param name="args" select="$args"/>
667 </xsl:call-template>
668 </xsl:when>
669 <xsl:otherwise>
670 <xsl:choose>
671 <xsl:when test="$func/malval/@name = 'env??'">
672 <!-- needs access to env -->
673 <xsl:variable name="nev" select="env:dump($env)"/>
674 <xsl:variable name="value">
675 <malval kind="string" value="{$env =&gt; serialize(map{'method':'json'})}"/>
676 </xsl:variable>
677 <value>
678 <xsl:sequence select="$value"/>
679 </value>
680 <xsl:if test="$encode-env">
681 <env data="{env:serialise($env)}"/>
682 </xsl:if>
683 <xsl:sequence select="$value/atoms[1]"/>
684 </xsl:when>
685 <xsl:when test="$func/malval/@name = 'eval'">
686 <!-- needs access to env -->
687 <xsl:variable name="venv" select="env:replEnv($env)"/>
688 <xsl:variable name="form">
689 <value>
690 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
691 </value>
692 <xsl:sequence select="$atoms"/>
693 </xsl:variable>
694 <xsl:variable name="value">
695 <xsl:for-each select="$form">
696 <xsl:call-template name="EVAL">
697 <xsl:with-param name="env" select="$venv"/>
698 <xsl:with-param name="encode-env" select="$encode-env"/>
699 </xsl:call-template>
700 </xsl:for-each>
701 </xsl:variable>
702 <xsl:sequence select="$value/data/value"/>
703 <xsl:if test="$encode-env">
704 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data)))}"/>
705 </xsl:if>
706 <xsl:sequence select="$value/atoms[1]"/>
707 </xsl:when>
708 <xsl:when test="$func/malval/@name = 'atom'">
709 <!-- needs access to atoms -->
710 <xsl:variable name="atom-ident" select="count($atoms/atom)"/>
711 <value>
712 <malval kind="atom" value="{$atom-ident}"/>
713 </value>
714 <atoms>
715 <xsl:for-each select="$atoms/atom">
716 <xsl:sequence select="."/>
717 </xsl:for-each>
718 <atom identity="{$atom-ident}">
719 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
720 </atom>
721 </atoms>
722 </xsl:when>
723 <xsl:when test="$func/malval/@name = 'deref'">
724 <!-- needs access to atoms -->
725 <value>
726 <xsl:sequence select="$atoms/atom[@identity = $args/value/malval/lvalue/malval[1]/@value]/malval"/>
727 </value>
728 <xsl:sequence select="$atoms"/>
729 </xsl:when>
730 <xsl:when test="$func/malval/@name = 'reset!'">
731 <!-- needs access to atoms -->
732 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
733 <xsl:variable name="newv" select="$args/value/malval/lvalue/malval[2]"/>
734 <value>
735 <xsl:sequence select="$newv"/>
736 </value>
737 <atoms>
738 <xsl:for-each select="$atoms/atom[@identity != $atom-ident]">
739 <xsl:sequence select="."/>
740 </xsl:for-each>
741 <atom identity="{$atom-ident}">
742 <xsl:sequence select="$newv"/>
743 </atom>
744 </atoms>
745 </xsl:when>
746 <xsl:when test="$func/malval/@name = 'swap!'">
747 <!-- needs access to atoms -->
748 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
749 <xsl:variable name="atom-value" select="$atoms/atom[@identity = $atom-ident]/malval"/>
750 <xsl:variable name="fn" select="$args/value/malval/lvalue/malval[2]"/>
751 <xsl:variable name="newlist">
752 <value>
753 <malval kind="list">
754 <lvalue>
755 <xsl:sequence select="$fn"/>
756 <xsl:sequence select="$atom-value"/>
757 <xsl:sequence select="$args/value/malval/lvalue/malval[position() &gt; 2]"/>
758 </lvalue>
759 </malval>
760 </value>
761 <xsl:sequence select="$atoms"/>
762 </xsl:variable>
763 <xsl:variable name="newv">
764 <xsl:for-each select="$newlist">
765 <xsl:call-template name="EVAL">
766 <xsl:with-param name="env" select="$env"/>
767 <xsl:with-param name="encode-env" select="false()"/>
768 </xsl:call-template>
769 </xsl:for-each>
770 </xsl:variable>
771 <xsl:sequence select="$newv/data/value"/>
772 <atoms>
773 <xsl:for-each select="$newv/atoms[1]/atom[@identity != $atom-ident]">
774 <xsl:sequence select="."/>
775 </xsl:for-each>
776 <atom identity="{$atom-ident}">
777 <xsl:sequence select="$newv/data/value/malval"/>
778 </atom>
779 </atoms>
780 <xsl:sequence select="$newv/env"/>
781 </xsl:when>
782 <xsl:otherwise>
783 <xsl:call-template name="core-apply">
784 <xsl:with-param name="func" select="$func"/>
785 <xsl:with-param name="args" select="$args"/>
786 </xsl:call-template>
787 <xsl:sequence select="$atoms"/>
788 </xsl:otherwise>
789 </xsl:choose>
790 </xsl:otherwise>
791 </xsl:choose>
792 </xsl:variable>
793 <xsl:for-each select="$resultv">
794 <xsl:choose>
795 <xsl:when test="empty(env)">
796 <xsl:if test="$encode-env">
797 <env data="{env:serialise($env)}"/>
798 </xsl:if>
799 </xsl:when>
800 <xsl:otherwise>
801 <xsl:sequence select="env"/>
802 </xsl:otherwise>
803 </xsl:choose>
804 <xsl:sequence select="atoms[1]"/>
805 <xsl:sequence select="value"/>
806 </xsl:for-each>
807 </xsl:otherwise>
808 </xsl:choose>
809 </xsl:for-each>
810 </xsl:otherwise>
811 </xsl:choose>
812 </xsl:when>
813 <xsl:otherwise>
814 <xsl:call-template name="eval_ast">
815 <xsl:with-param name="atoms" select="$atoms"/>
816 <xsl:with-param name="env" select="$env"/>
817 </xsl:call-template>
818 <xsl:if test="$encode-env">
819 <env data="{env:serialise($env)}"/>
820 </xsl:if>
821 <!-- <xsl:sequence select="$atoms"/> -->
822 </xsl:otherwise>
823 </xsl:choose>
824 </xsl:variable>
825 <data>
826 <xsl:sequence select="$data/value"/>
827 </data>
828 <xsl:if test="$encode-env">
829 <env data="{$data/env/@data}"/>
830 </xsl:if>
831 <xsl:sequence select="$data/atoms[1]"/>
832 </xsl:template>
833 <xsl:template name="READ">
834 <xsl:variable name="context">
835 <str>
836 <xsl:copy-of select="stdin/text()"/>
837 </str>
838 </xsl:variable>
839 <xsl:variable name="form">
840 <xsl:sequence select="state/atoms[1]"/>
841 <xsl:for-each select="$context">
842 <xsl:call-template name="malreader-read_str"/>
843 </xsl:for-each>
844 </xsl:variable>
845 <xsl:for-each select="$form">
846 <xsl:if test="error">
847 <xsl:value-of select="error(QName('MAL', 'Error'), string(error))"/>
848 </xsl:if>
849 <xsl:sequence select="."/>
850 </xsl:for-each>
851 </xsl:template>
852 <xsl:function name="fn:group_consec">
853 <xsl:param name="nodes"/>
854 <xsl:variable name="groups">
855 <xsl:for-each-group select="$nodes" group-by="position() mod 2">
856 <xsl:choose>
857 <xsl:when test="position() = 1">
858 <first>
859 <xsl:sequence select="current-group()"/>
860 </first>
861 </xsl:when>
862 <xsl:otherwise>
863 <second>
864 <xsl:sequence select="current-group()"/>
865 </second>
866 </xsl:otherwise>
867 </xsl:choose>
868 </xsl:for-each-group>
869 </xsl:variable>
870 <xsl:iterate select="1 to count($groups/first/*)">
871 <element>
872 <xsl:variable name="idx" select="number(.)"/>
873 <first>
874 <xsl:sequence select="$groups/first/node()[position() = $idx]"/>
875 </first>
876 <second>
877 <xsl:sequence select="$groups/second/node()[position() = $idx]"/>
878 </second>
879 </element>
880 </xsl:iterate>
881 </xsl:function>
882 <xsl:function name="fn:is-pair">
883 <xsl:param name="list"/>
884 <xsl:sequence select="($list/@kind = 'list' or $list/@kind = 'vector') and
885 count($list/lvalue/malval) != 0"/>
886 </xsl:function>
887 <xsl:function name="fn:is-macro-call">
888 <xsl:param name="ast"/>
889 <xsl:param name="env"/>
890 <xsl:variable
891 name="res"
892 select="$ast/@kind = 'list' and
893 $ast/lvalue/malval[1]/@kind = 'symbol' and
894 (let $fn := env:get-noerror($env, $ast/lvalue/malval[1]/@value)
895 return not(empty($fn)) and
896 $fn/malval/is_macro/text() = 'true')"/>
897 <xsl:sequence select="$res"/>
898 </xsl:function>
899 </xsl:stylesheet>