Commit | Line | Data |
---|---|---|
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* (& 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> |
226 | UAPPLY <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 | 337 | EVALUATE <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> | |
688 | EVAL_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> | |
704 | ENV 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> |
878 | EVALUATED (<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> |