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