be more spec-compatible with readline
[jackhill/mal.git] / impls / xslt / stepA_mal.xslt
CommitLineData
d4798a57
A
1<?xml version="1.0" encoding="UTF-8"?>
2<!-- Step A: MAL -->
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>
d4798a57
A
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" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:MAL="MAL" exclude-result-prefixes="fn xs map env core err MAL">
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))))))) (def! *host-language* "XSLT"))</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:param name="atoms" />
98 <xsl:choose>
99 <xsl:when test="value/malval/@kind = 'symbol'">
100 <xsl:variable name="val">
101 <xsl:sequence select="env:get($env, value/malval/@value)" />
102 </xsl:variable>
103 <value>
104 <xsl:sequence select="$val"/>
105 </value>
106 </xsl:when>
107 <xsl:when test="value/malval/@kind = 'list'">
108 <value>
109 <malval kind="list">
110 <lvalue>
111 <xsl:for-each select="value/malval/lvalue/malval">
112 <xsl:variable name="ctx">
113 <value>
114 <xsl:sequence select="."/>
115 </value>
116 <xsl:sequence select="$atoms"/>
117 </xsl:variable>
118 <xsl:variable name="xctx">
119 <xsl:for-each select="$ctx">
120 <xsl:variable name="val">
121 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
122 </xsl:variable>
123 <xsl:sequence select="$val/data/value"/>
124 </xsl:for-each>
125 </xsl:variable>
126 <xsl:sequence select="$xctx/value/malval"/>
127 </xsl:for-each>
128 </lvalue>
129 </malval>
130 </value>
131 </xsl:when>
132 <xsl:when test="value/malval/@kind = 'vector'">
133 <value>
134 <malval kind="vector">
135 <lvalue>
136 <xsl:for-each select="value/malval/lvalue/malval">
137 <xsl:variable name="ctx">
138 <value>
139 <xsl:sequence select="."/>
140 </value>
141 <xsl:sequence select="$atoms"/>
142 </xsl:variable>
143 <xsl:variable name="xctx">
144 <xsl:for-each select="$ctx">
145 <xsl:variable name="val">
146 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
147 </xsl:variable>
148 <xsl:sequence select="$val/data/value"/>
149 </xsl:for-each>
150 </xsl:variable>
151 <xsl:sequence select="$xctx/value/malval"/>
152 </xsl:for-each>
153 </lvalue>
154 </malval>
155 </value>
156 </xsl:when>
157 <xsl:when test="value/malval/@kind = 'hash'">
158 <value>
159 <malval kind="hash">
160 <lvalue>
161 <xsl:for-each select="value/malval/lvalue/malval">
162 <xsl:variable name="ctx">
163 <value>
164 <xsl:sequence select="."/>
165 </value>
166 <xsl:sequence select="$atoms"/>
167 </xsl:variable>
168 <xsl:variable name="xctx">
169 <xsl:for-each select="$ctx">
170 <xsl:variable name="val">
171 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
172 </xsl:variable>
173 <xsl:sequence select="$val/data/value"/>
174 </xsl:for-each>
175 </xsl:variable>
176 <xsl:sequence select="$xctx/value/malval"/>
177 </xsl:for-each>
178 </lvalue>
179 </malval>
180 </value>
181 </xsl:when>
182 <xsl:otherwise>
183 <xsl:sequence select="." />
184 </xsl:otherwise>
185 </xsl:choose>
186 </xsl:template>
187
188 <xsl:template name="call-function">
189 <xsl:param name="func" />
190 <xsl:param name="args" />
191 <xsl:param name="env" />
192
193 <xsl:variable name="res">
194 <xsl:choose>
195 <xsl:when test="$func/malval/@kind = 'userfunction'">
196 <xsl:call-template name="uapply"><xsl:with-param name="func" select="$func"/><xsl:with-param name="args" select="$args"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
197 </xsl:when>
198 <xsl:otherwise>
199 <xsl:call-template name="core-apply"><xsl:with-param name="func" select="$func"/><xsl:with-param name="args" select="$args"/></xsl:call-template>
200 </xsl:otherwise>
201 </xsl:choose>
202 </xsl:variable>
203 <xsl:sequence select="$res/value"/>
204 <xsl:choose>
205 <xsl:when test="$res/atoms"><xsl:sequence select="$res/atoms[1]"/></xsl:when>
206 <xsl:otherwise>
207 <xsl:sequence select="atoms"/>
208 </xsl:otherwise>
209 </xsl:choose>
210 <xsl:choose>
211 <xsl:when test="$res/env"><xsl:sequence select="$res/env"/></xsl:when>
212 <xsl:otherwise>
213 <env data="{$env => env:serialise()}"/>
214 </xsl:otherwise>
215 </xsl:choose>
216 </xsl:template>
217
218 <!-- uapply[env, fn, args] -->
219 <xsl:template name="uapply">
220 <xsl:param name="func" />
221 <xsl:param name="args" />
222 <xsl:param name="env" />
223
224 <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)" />
309b36ee
A
225 <!-- <xsl:message>
226UAPPLY <xsl:sequence select="core:pr-str($func/malval/body/malval)/value/text()"/> WITH ATOMS <xsl:sequence select="atoms"/>
227 </xsl:message> -->
d4798a57
A
228 <xsl:variable name="body">
229 <value>
230 <xsl:sequence select="$func/malval/body/malval"/>
231 </value>
232 <xsl:sequence select="atoms[1]"/>
233 </xsl:variable>
234 <xsl:variable name="result">
235 <xsl:for-each select="$body">
236 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$nenv"/></xsl:call-template>
237 </xsl:for-each>
238 </xsl:variable>
239 <xsl:sequence select="$result/data/value"/>
240 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($result/env/@data) => env:replEnv()))}" />
241 <xsl:sequence select="$result/atoms[1]"/>
242 </xsl:template>
243
244 <xsl:template name="quasiquote">
245 <xsl:param name="ast" />
246 <xsl:variable name="result">
247 <xsl:choose>
248 <xsl:when test="fn:is-pair($ast)">
249 <xsl:choose>
250 <xsl:when test="let $fst := $ast/lvalue/malval[1] return $fst/@kind = 'symbol' and $fst/@value = 'unquote'">
251 <xsl:sequence select="$ast/lvalue/malval[2]"/>
252 </xsl:when>
253 <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')">
254 <malval kind="list">
255 <lvalue>
256 <malval kind="symbol" value="concat"/>
257 <xsl:sequence select="$ast/lvalue/malval[1]/lvalue/malval[2]"/>
258 <xsl:variable name="rest" select="$ast/lvalue/malval[position() > 1]"/>
259 <xsl:variable name="rest-">
260 <malval kind="list">
261 <lvalue>
262 <xsl:sequence select="$rest"/>
263 </lvalue>
264 </malval>
265 </xsl:variable>
266 <xsl:call-template name="quasiquote"><xsl:with-param name="ast" select="$rest-"/></xsl:call-template>
267 </lvalue>
268 </malval>
269 </xsl:when>
270 <xsl:otherwise>
271 <malval kind="list">
272 <lvalue>
273 <malval kind="symbol" value="cons"/>
274 <xsl:variable name="first" select="$ast/lvalue/malval[1]"/>
275 <xsl:variable name="rest" select="$ast/lvalue/malval[position() > 1]"/>
276 <xsl:variable name="rest-">
277 <malval kind="list">
278 <lvalue>
279 <xsl:sequence select="$rest"/>
280 </lvalue>
281 </malval>
282 </xsl:variable>
283 <xsl:call-template name="quasiquote"><xsl:with-param name="ast" select="$first"/></xsl:call-template>
284 <xsl:call-template name="quasiquote"><xsl:with-param name="ast" select="$rest-/malval"/></xsl:call-template>
285 </lvalue>
286 </malval>
287 </xsl:otherwise>
288 </xsl:choose>
289 </xsl:when>
290 <xsl:otherwise>
291 <malval kind="list">
292 <lvalue>
293 <malval kind="symbol" value="quote"/>
294 <xsl:sequence select="$ast"/>
295 </lvalue>
296 </malval>
297 </xsl:otherwise>
298 </xsl:choose>
299 </xsl:variable>
300 <xsl:sequence select="$result"/>
301 </xsl:template>
302
303 <xsl:template name="macroexpand">
304 <xsl:param name="ast" />
305 <xsl:param name="env" />
306 <xsl:choose>
307 <xsl:when test="fn:is-macro-call($ast, $env)">
308 <xsl:variable name="fn" select="env:get($env, $ast/lvalue/malval[1]/@value)"></xsl:variable>
309 <xsl:variable name="args">
310 <value>
311 <malval kind="list">
312 <lvalue>
313 <xsl:sequence select="$ast/lvalue/malval[position() > 1]"/>
314 </lvalue>
315 </malval>
316 </value>
317 </xsl:variable>
318 <xsl:variable name="new">
319 <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>
320 </xsl:variable>
321 <xsl:call-template name="macroexpand"><xsl:with-param name="ast" select="$new/value/malval"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
322 </xsl:when>
323 <xsl:otherwise>
324 <value>
325 <xsl:sequence select="$ast"/>
326 </value>
327 <xsl:sequence select="atoms[1]"/>
328 <env data="{$env => env:serialise()}" />
329 </xsl:otherwise>
330 </xsl:choose>
331 </xsl:template>
332
333 <xsl:template name="EVAL">
334 <xsl:param name="env" />
309b36ee 335 <!-- <xsl:message>
d4798a57 336
309b36ee 337EVALUATE <xsl:sequence select="core:pr-str(value/malval)/value/text()"/> IN (<xsl:sequence select="empty($env('replEnv'))"/>) ENV <xsl:sequence select="$env"/>
d4798a57 338
309b36ee 339</xsl:message> -->
d4798a57
A
340 <xsl:variable name="atoms" select="atoms[1]"></xsl:variable>
341 <xsl:variable name="data">
342 <xsl:choose>
343 <xsl:when test="value/malval/@kind = 'list'">
344 <xsl:choose>
345 <xsl:when test="count(value/malval/lvalue/malval) = 0">
346 <xsl:sequence select="."/>
347 <env data="{env:serialise($env)}" />
348 <xsl:sequence select="$atoms"/>
349 </xsl:when>
350 <xsl:otherwise>
351 <xsl:variable name="mexp">
352 <xsl:call-template name="macroexpand"><xsl:with-param name="ast" select="value/malval"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
353 </xsl:variable>
354 <xsl:for-each select="$mexp">
355 <xsl:choose>
356 <xsl:when test="value/malval/@kind != 'list'">
357 <xsl:variable name="ctx">
358 <xsl:sequence select="value"/>
359 </xsl:variable>
360 <xsl:for-each select="$ctx">
361 <xsl:call-template name="eval_ast"><xsl:with-param name="atoms" select="$atoms"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
362 <env data="{env:serialise($env)}"/>
363 <xsl:sequence select="$atoms"/>
364 </xsl:for-each>
365 </xsl:when>
366 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'def!'">
367 <xsl:variable name="name">
368 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
369 </xsl:variable>
370 <xsl:variable name="xvalue">
371 <value>
372 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
373 </value>
374 <xsl:sequence select="$atoms"/>
375 </xsl:variable>
376 <xsl:variable name="value">
377 <xsl:for-each select="$xvalue">
378 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
379 </xsl:for-each>
380 </xsl:variable>
381 <xsl:sequence select="$value/data/value"/>
382 <env data="{env:serialise(env:set($env, $name, $value/data/value/malval))}"/>
383 <xsl:sequence select="$value/atoms[1]"/>
384 </xsl:when>
385 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'defmacro!'">
386 <xsl:variable name="name">
387 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
388 </xsl:variable>
389 <xsl:variable name="xvalue">
390 <value>
391 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
392 </value>
393 <xsl:sequence select="$atoms"/>
394 </xsl:variable>
395 <xsl:variable name="value">
396 <xsl:for-each select="$xvalue">
397 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
398 </xsl:for-each>
399 </xsl:variable>
400 <xsl:variable name="resv">
401 <value>
402 <malval kind="{$value/data/value/malval/@kind}" value="{$value/data/value/malval/@value}">
403 <xsl:sequence select="$value/data/value/malval/*[name() != 'is_macro']" />
404 <is_macro>true</is_macro>
405 </malval>
406 </value>
407 </xsl:variable>
408 <xsl:sequence select="$resv"/>
409 <env data="{env:serialise(env:set($env, $name, $resv/value/malval))}"/>
309b36ee 410 <xsl:sequence select="$value/atoms[1]"/>
d4798a57
A
411 </xsl:when>
412 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'let*'">
413 <xsl:variable name="xvalue">
414 <value>
415 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
416 </value>
417 <xsl:sequence select="$atoms"/>
418 </xsl:variable>
419
420 <xsl:iterate select="fn:group_consec(value/malval/lvalue/malval[2]/lvalue/malval)">
421 <xsl:param name="new_env" select="env:close($env)"/>
422 <xsl:param name="new_atoms" select="$atoms"/>
423
424 <xsl:on-completion>
425 <xsl:variable name="xvalue">
426 <xsl:sequence select="$xvalue/value"/>
427 <xsl:sequence select="$new_atoms"/>
428 </xsl:variable>
429 <xsl:variable name="value">
430 <xsl:for-each select="$xvalue">
431 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$new_env"/></xsl:call-template>
432 </xsl:for-each>
433 </xsl:variable>
434 <xsl:sequence select="$value/data/value"></xsl:sequence>
435 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) => env:replEnv()))}" />
436
437 <xsl:sequence select="$value/atoms[1]"/>
438 </xsl:on-completion>
439
440 <xsl:variable name="name">
441 <xsl:value-of select="node()[name() = 'first']/malval/@value"/>
442 </xsl:variable>
443
444 <xsl:variable name="xvalue">
445 <value>
446 <xsl:sequence select="node()[name() = 'second']/malval"/>
447 </value>
448 <xsl:sequence select="$new_atoms"/>
449 </xsl:variable>
450
451 <xsl:variable name="value">
452 <xsl:for-each select="$xvalue">
453 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$new_env"/></xsl:call-template>
454 </xsl:for-each>
455 </xsl:variable>
456
457 <xsl:next-iteration>
458 <xsl:with-param name="new_env" select="env:set($new_env, $name, $value/data/value/malval)"/>
459 <xsl:with-param name="new_atoms" select="$value/atoms[1]"/>
460 </xsl:next-iteration>
461 </xsl:iterate>
462 </xsl:when>
463 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'do'">
464 <xsl:iterate select="value/malval/lvalue/malval[position() > 1]">
465 <xsl:param name="new_env" select="$env"/>
466 <xsl:param name="atoms" select="$atoms"/>
467 <xsl:param name="previous_res" select="()"/>
468 <xsl:on-completion>
469 <xsl:sequence select="$previous_res"/>
470 <env data="{env:serialise($new_env)}" />
471 <xsl:sequence select="$atoms"/>
472 </xsl:on-completion>
473 <xsl:variable name="xvalue">
474 <value>
475 <xsl:sequence select="."/>
476 </value>
477 <xsl:sequence select="$atoms"/>
478 </xsl:variable>
479 <xsl:variable name="value">
480 <xsl:for-each select="$xvalue">
481 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$new_env"/></xsl:call-template>
482 </xsl:for-each>
483 </xsl:variable>
484 <xsl:next-iteration>
485 <xsl:with-param name="new_env" select="env:deserialise($value/env/@data)"/>
486 <xsl:with-param name="previous_res" select="$value/data/value"/>
487 <xsl:with-param name="atoms" select="$value/atoms[1]"/>
488 </xsl:next-iteration>
489 </xsl:iterate>
490 </xsl:when>
491 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'if'">
492 <xsl:variable name="cond">
493 <xsl:for-each select="value/malval/lvalue/malval[2]">
494 <xsl:variable name="context">
495 <value>
496 <xsl:sequence select="."/>
497 </value>
498 <xsl:sequence select="$atoms"/>
499 </xsl:variable>
500 <xsl:for-each select="$context">
501 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
502 </xsl:for-each>
503 </xsl:for-each>
504 </xsl:variable>
505 <xsl:variable name="ptrue">
506 <xsl:for-each select="value/malval/lvalue/malval[3]">
507 <value>
508 <xsl:sequence select="."/>
509 </value>
510 <xsl:sequence select="$cond/atoms[1]"/>
511 </xsl:for-each>
512 </xsl:variable>
513 <xsl:variable name="pfalse">
514 <xsl:for-each select="value/malval/lvalue/malval[4]">
515 <value>
516 <xsl:sequence select="."/>
517 </value>
518 <xsl:sequence select="$cond/atoms[1]"/>
519 </xsl:for-each>
520 </xsl:variable>
521 <xsl:variable name="xfalse">
522 <xsl:choose>
523 <xsl:when test="empty($pfalse/value)">
524 <value>
525 <malval kind='nil' />
526 </value>
527 <xsl:sequence select="$cond/atoms[1]"/>
528 </xsl:when>
529 <xsl:otherwise>
530 <xsl:sequence select="$pfalse/value"/>
531 <xsl:sequence select="$pfalse/atoms[1]"/>
532 </xsl:otherwise>
533 </xsl:choose>
534 </xsl:variable>
535 <xsl:variable name="res">
536 <xsl:choose>
537 <xsl:when test="let $kind := $cond/data/value/malval/@kind return $kind = 'nil' or $kind = 'false'">
538 <xsl:for-each select="$xfalse">
539 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
540 </xsl:for-each>
541 </xsl:when>
542 <xsl:otherwise>
543 <xsl:for-each select="$ptrue">
544 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
545 </xsl:for-each>
546 </xsl:otherwise>
547 </xsl:choose>
548 </xsl:variable>
549 <xsl:sequence select="$res/data/value"/>
309b36ee 550 <xsl:sequence select="$res/env"/>
d4798a57
A
551 <xsl:sequence select="$res/atoms[1]"/>
552 </xsl:when>
553 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'fn*'">
554 <value>
555 <malval kind="userfunction">
556 <is_macro>false</is_macro>
557 <binds>
558 <xsl:sequence select="value/malval/lvalue/malval[2]/lvalue/malval" />
559 </binds>
560 <body>
561 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
562 </body>
563 <env data="{env:serialise(env:noReplEnv($env))}"/> <!-- capture current env -->
564 </malval>
565 </value>
566 <env data="{env:serialise($env)}" />
567 <xsl:sequence select="$atoms"/>
568 </xsl:when>
569 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quote'">
570 <value>
571 <xsl:sequence select="value/malval/lvalue/malval[2]" />
572 </value>
573 <env data="{env:serialise($env)}" />
574 <xsl:sequence select="$atoms"/>
575 </xsl:when>
576 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quasiquote'">
577 <xsl:variable name="exp">
578 <value>
579 <xsl:call-template name="quasiquote"><xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/></xsl:call-template>
580 </value>
581 <xsl:sequence select="$atoms"/>
582 </xsl:variable>
583 <xsl:variable name="res">
584 <xsl:for-each select="$exp">
585 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
586 </xsl:for-each>
587 </xsl:variable>
588 <xsl:sequence select="$res/data/value"/>
589 <xsl:sequence select="$res/env"/>
590 <xsl:sequence select="$res/atoms[1]"/>
591 </xsl:when>
592 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'macroexpand'">
593 <xsl:variable name="exp">
594 <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>
595 <xsl:sequence select="$atoms"/>
596 </xsl:variable>
597 <xsl:sequence select="$exp/value"/>
598 <env data="{env:serialise($env)}" />
599 <xsl:sequence select="$atoms"/>
600 </xsl:when>
601 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'try*'">
602 <xsl:variable name="tryv">
603 <xsl:try>
604 <xsl:variable name="xvalue">
605 <value>
606 <xsl:sequence select="value/malval/lvalue/malval[2]"/>
607 </value>
608 <xsl:sequence select="$atoms"/>
609 </xsl:variable>
610 <xsl:variable name="value">
611 <xsl:for-each select="$xvalue">
612 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$env"/></xsl:call-template>
613 </xsl:for-each>
614 </xsl:variable>
615 <xsl:sequence select="$value/data/value"/>
616 <xsl:sequence select="$value/env"/>
617 <xsl:sequence select="$value/atoms[1]"/>
618
619 <xsl:catch errors="*">
620 <xsl:variable name="catchv-name" select="value/malval/lvalue/malval[3]/lvalue/malval[2]/@value"/>
621 <xsl:variable name="catchv">
622 <value>
623 <xsl:sequence select="value/malval/lvalue/malval[3]/lvalue/malval[3]"/>
624 </value>
625 </xsl:variable>
626 <xsl:if test="empty($catchv/value/malval)">
627 <xsl:value-of select="error($err:code, $err:description, $err:value)"></xsl:value-of>
628 </xsl:if>
309b36ee 629 <!-- <xsl:message>
d4798a57 630 <xsl:sequence select="$env"/>
309b36ee 631 </xsl:message> -->
d4798a57
A
632 <xsl:variable name="newenv" select="env:close($env) => env:set($catchv-name, $err:value)"/>
633 <xsl:variable name="value">
634 <xsl:for-each select="$catchv">
635 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$newenv"/></xsl:call-template>
636 </xsl:for-each>
637 </xsl:variable>
638 <xsl:sequence select="$value/data/value"/>
309b36ee 639 <xsl:sequence select="$value/env"/> <!-- leaks the bound name, ouch -->
d4798a57
A
640 <xsl:sequence select="$value/atoms[1]"/>
641 </xsl:catch>
642 </xsl:try>
643 </xsl:variable>
644 <xsl:sequence select="$tryv"/>
645 </xsl:when>
646 <xsl:otherwise>
647 <xsl:variable name="new_list">
648 <xsl:call-template name="eval_ast"><xsl:with-param name="atoms" select="$atoms"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
649 </xsl:variable>
650 <xsl:variable name="func">
651 <xsl:for-each select="$new_list">
652 <xsl:sequence select="value/malval/lvalue/malval[1]"/>
653 </xsl:for-each>
654 </xsl:variable>
655 <xsl:variable name="args">
656 <xsl:for-each select="$new_list">
657 <value>
658 <malval kind="list">
659 <lvalue>
660 <xsl:sequence select="value/malval/lvalue/node()[position() != 1]" />
661 </lvalue>
662 </malval>
663 </value>
664 <xsl:sequence select="$atoms"/>
665 </xsl:for-each>
666 </xsl:variable>
667 <xsl:variable name="resultv">
668 <xsl:choose>
669 <xsl:when test="$func/malval/@kind = 'userfunction'">
670 <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>
671 </xsl:when>
672 <xsl:otherwise>
673 <xsl:choose>
674 <xsl:when test="$func/malval/@name = 'env??'"> <!-- needs access to env -->
675 <xsl:variable name="nev" select="env:dump($env)"></xsl:variable>
676 <xsl:variable name="value">
677 <malval kind="string" value="{$env => serialize(map{'method':'json'})}"/>
678 </xsl:variable>
679 <value>
680 <xsl:sequence select="$value"/>
681 </value>
682 <env data="{env:serialise($env)}"/>
683 <xsl:sequence select="$value/atoms[1]"/>
684 </xsl:when>
685 <xsl:when test="$func/malval/@name = 'eval'"> <!-- needs access to env -->
309b36ee
A
686 <xsl:variable name="venv" select="env:replEnv($env) => env:wrapReplEnv()"></xsl:variable>
687 <!-- <xsl:message>
688EVAL_FUNCTION ENV <xsl:sequence select="$venv"/>
689 </xsl:message> -->
d4798a57
A
690 <xsl:variable name="form">
691 <value>
692 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
693 </value>
694 <xsl:sequence select="$atoms"/>
695 </xsl:variable>
696 <xsl:variable name="value">
697 <xsl:for-each select="$form">
698 <xsl:call-template name="EVAL"><xsl:with-param name="env" select="$venv"/></xsl:call-template>
699 </xsl:for-each>
700 </xsl:variable>
701 <xsl:sequence select="$value/data/value"/>
309b36ee
A
702 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) => env:collapseReplEnv()))}"/>
703 <!-- <xsl:message>
704ENV IS <xsl:sequence select="$value/env/@data => env:deserialise()"/>
705 </xsl:message> -->
d4798a57
A
706 <xsl:sequence select="$value/atoms[1]"/>
707 </xsl:when>
708 <xsl:when test="$func/malval/@name = 'atom'"> <!-- needs access to atoms -->
309b36ee 709 <xsl:variable name="atom-ident" select="count($atoms/atom)"></xsl:variable>
d4798a57
A
710 <value>
711 <malval kind="atom" value="{$atom-ident}"/>
712 </value>
713 <atoms>
714 <xsl:for-each select="$atoms/atom">
715 <xsl:sequence select="."/>
716 </xsl:for-each>
717 <atom identity="{$atom-ident}">
718 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
719 </atom>
720 </atoms>
721 </xsl:when>
722 <xsl:when test="$func/malval/@name = 'deref'"> <!-- needs access to atoms -->
723 <value>
724 <xsl:sequence select="$atoms/atom[@identity = $args/value/malval/lvalue/malval[1]/@value]/malval"/>
725 </value>
726 <xsl:sequence select="$atoms"/>
727 </xsl:when>
728 <xsl:when test="$func/malval/@name = 'reset!'"> <!-- needs access to atoms -->
729 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"></xsl:variable>
730 <xsl:variable name="newv" select="$args/value/malval/lvalue/malval[2]"></xsl:variable>
731 <value>
732 <xsl:sequence select="$newv"/>
733 </value>
734 <atoms>
735 <xsl:for-each select="$atoms/atom[@identity != $atom-ident]">
736 <xsl:sequence select="."/>
737 </xsl:for-each>
738 <atom identity="{$atom-ident}">
739 <xsl:sequence select="$newv"/>
740 </atom>
741 </atoms>
742 </xsl:when>
743 <xsl:when test="$func/malval/@name = 'swap!'"> <!-- needs access to atoms -->
744 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"></xsl:variable>
745 <xsl:variable name="atom-value" select="$atoms/atom[@identity = $atom-ident]/malval"></xsl:variable>
746 <xsl:variable name="fn">
747 <xsl:sequence select="$args/value/malval/lvalue/malval[2]" />
748 </xsl:variable>
749 <xsl:variable name="cargs">
750 <value>
751 <malval kind="list">
752 <lvalue>
753 <xsl:sequence select="$atom-value"/>
754 <xsl:sequence select="$args/value/malval/lvalue/malval[position() > 2]"/>
755 </lvalue>
756 </malval>
757 </value>
758 </xsl:variable>
759 <xsl:variable name="newv">
760 <xsl:call-template name="call-function"><xsl:with-param name="func" select="$fn"/><xsl:with-param name="args" select="$cargs"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
761 </xsl:variable>
762 <xsl:sequence select="$newv/value"/>
763 <atoms>
764 <xsl:for-each select="$newv/atoms[1]/atom[@identity != $atom-ident]">
765 <xsl:sequence select="."/>
766 </xsl:for-each>
767 <atom identity="{$atom-ident}">
768 <xsl:sequence select="$newv/value/malval"/>
769 </atom>
770 </atoms>
771 <xsl:sequence select="$newv/env"/>
772 </xsl:when>
773 <xsl:when test="$func/malval/@name = 'apply'"> <!-- needs access to env -->
774 <!-- (apply F A... T) -> (F A... T...) -->
775 <xsl:variable name="fun">
776 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
777 </xsl:variable>
778 <xsl:variable name="args">
779 <value>
780 <malval kind="list">
781 <lvalue>
782 <xsl:variable name="argc" select="count($args/value/malval/lvalue/malval)"></xsl:variable>
783 <xsl:sequence select="$args/value/malval/lvalue/malval[position() gt 1 and position() lt $argc]"/>
784 <xsl:sequence select="$args/value/malval/lvalue/malval[$argc]/lvalue/malval"/>
785 </lvalue>
786 </malval>
787 </value>
788 </xsl:variable>
789 <xsl:variable name="res">
790 <xsl:call-template name="call-function"><xsl:with-param name="func" select="$fun"/><xsl:with-param name="args" select="$args"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
791 </xsl:variable>
792 <xsl:sequence select="$res/value"/>
793 <xsl:sequence select="$res/env"/>
794 <xsl:sequence select="$res/atoms[1]"/>
795 </xsl:when>
796 <xsl:when test="$func/malval/@name = 'map'"> <!-- needs access to env -->
797 <!-- (map F T) -> (list (F Tx)...) -->
798 <xsl:variable name="func">
799 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
800 </xsl:variable>
801 <xsl:iterate select="$args/value/malval/lvalue/malval[2]/lvalue/malval">
802 <xsl:param name="xenv" select="$env"/>
803 <xsl:param name="atoms" select="$atoms"/>
804 <xsl:param name="value" select="()"/>
805 <xsl:on-completion>
806 <value>
807 <malval kind="list">
808 <lvalue>
809 <xsl:sequence select="$value"/>
810 </lvalue>
811 </malval>
812 </value>
813 <env data="{$env => env:serialise()}"/>
814 <xsl:sequence select="$atoms"/>
815 </xsl:on-completion>
816 <xsl:variable name="args">
817 <value>
818 <malval kind="list">
819 <lvalue>
820 <xsl:sequence select="."/>
821 </lvalue>
822 </malval>
823 </value>
824 </xsl:variable>
825 <xsl:variable name="res">
826 <xsl:call-template name="call-function"><xsl:with-param name="func" select="$func"/><xsl:with-param name="args" select="$args"/><xsl:with-param name="env" select="$xenv"/></xsl:call-template>
827 </xsl:variable>
828 <xsl:next-iteration>
829 <xsl:with-param name="xenv" select="env:deserialise($res/env/@data)"/>
830 <xsl:with-param name="atoms" select="$res/atoms[1]"/>
831 <xsl:with-param name="value" select="$value, $res/value/malval"/>
832 </xsl:next-iteration>
833 </xsl:iterate>
834 </xsl:when>
835 <xsl:when test="$func/malval/@name = 'readline'"> <!-- requires interaction with harness -->
836 <xsl:message>
837 <request kind="readline" value="{$args/value/malval/lvalue/malval[1]/@value}"/>
838 </xsl:message>
c77e0464
A
839 <xsl:variable name="str" select="unparsed-text('xsl_input-string')"></xsl:variable>
840 <xsl:sequence select="core:makeMALType($str, if (string-length($str) = 0) then 'nil' else 'string')"/>
d4798a57
A
841 <xsl:sequence select="env"/>
842 <xsl:sequence select="$atoms"/>
843 </xsl:when>
844 <xsl:otherwise>
845 <xsl:call-template name="core-apply"><xsl:with-param name="func" select="$func"/><xsl:with-param name="args" select="$args"/></xsl:call-template>
846 <xsl:sequence select="$atoms"/>
847 </xsl:otherwise>
848 </xsl:choose>
849 </xsl:otherwise>
850 </xsl:choose>
851 </xsl:variable>
852 <xsl:for-each select="$resultv">
853 <xsl:choose>
854 <xsl:when test="empty(env)">
855 <env data="{env:serialise($env)}" />
856 </xsl:when>
857 <xsl:otherwise>
858 <xsl:sequence select="env"/>
859 </xsl:otherwise>
860 </xsl:choose>
861 <xsl:sequence select="atoms[1]"/>
862 <xsl:sequence select="value"/>
863 </xsl:for-each>
864 </xsl:otherwise>
865 </xsl:choose>
866 </xsl:for-each>
867 </xsl:otherwise>
868 </xsl:choose>
869 </xsl:when>
870 <xsl:otherwise>
871 <xsl:call-template name="eval_ast"><xsl:with-param name="atoms" select="$atoms"/><xsl:with-param name="env" select="$env"/></xsl:call-template>
872 <env data="{env:serialise($env)}" />
873 <xsl:sequence select="$atoms"/>
874 </xsl:otherwise>
875 </xsl:choose>
876 </xsl:variable>
309b36ee
A
877 <!-- <xsl:message>
878EVALUATED (<xsl:sequence select="empty($data/env/@data => env:deserialise() => env:replEnv())"/>) <xsl:sequence select="core:pr-str(value/malval)/value/text()"/> TO <xsl:sequence select="core:pr-str($data/value/malval)/value/text()"/> WITH ATOMS <xsl:sequence select="$data/atoms"/>
879 </xsl:message> -->
d4798a57
A
880 <data><xsl:sequence select="$data/value"/></data>
881 <env data="{$data/env/@data}" />
882 <xsl:sequence select="$data/atoms[1]"/>
883 </xsl:template>
884
885 <xsl:template name="READ">
886 <xsl:variable name="context">
887 <str>
888 <xsl:copy-of select="stdin/text()" />
889 </str>
890 </xsl:variable>
891 <xsl:variable name="form">
892 <xsl:sequence select="state/atoms[1]"/>
893 <xsl:for-each select="$context">
894 <xsl:call-template name="malreader-read_str"></xsl:call-template>
895 </xsl:for-each>
896 </xsl:variable>
897 <xsl:for-each select="$form">
898 <xsl:if test="error">
899 <xsl:value-of select="error(QName('MAL', 'Error'), string(error))" />
900 </xsl:if>
901 <xsl:sequence select="." />
902 </xsl:for-each>
903 </xsl:template>
904
905 <xsl:function name="fn:group_consec">
906 <xsl:param name="nodes" />
907 <xsl:variable name="groups">
908 <xsl:for-each-group select="$nodes" group-by="position() mod 2">
909 <xsl:choose>
910 <xsl:when test="position() = 1">
911 <first>
912 <xsl:sequence select="current-group()"/>
913 </first>
914 </xsl:when>
915 <xsl:otherwise>
916 <second>
917 <xsl:sequence select="current-group()"/>
918 </second>
919 </xsl:otherwise>
920 </xsl:choose>
921 </xsl:for-each-group>
922 </xsl:variable>
923 <xsl:iterate select="1 to count($groups/first/*)">
924 <element>
925 <xsl:variable name="idx" select="number(.)"></xsl:variable>
926 <first><xsl:sequence select="$groups/first/node()[position() = $idx]"/></first>
927 <second><xsl:sequence select="$groups/second/node()[position() = $idx]"/></second>
928 </element>
929 </xsl:iterate>
930 </xsl:function>
931
932 <xsl:function name="fn:is-pair">
933 <xsl:param name="list"/>
934 <xsl:sequence select="($list/@kind = 'list' or $list/@kind = 'vector') and count($list/lvalue/malval) != 0"/>
935 </xsl:function>
936
937 <xsl:function name="fn:is-macro-call">
938 <xsl:param name="ast"/>
939 <xsl:param name="env"/>
940 <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')"/>
941 <xsl:sequence select="$res"/>
942 </xsl:function>
943</xsl:stylesheet>