eliminate unnecessary env serialisations
[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-->
1c2f45cf
A
11<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:env="ENV" xmlns:core="CORE" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:MAL="MAL" version="3.0" exclude-result-prefixes="fn xs map env core err MAL">
12 <xsl:import href="reader.xslt"/>
13 <xsl:import href="printer.xslt"/>
14 <xsl:import href="env.xslt"/>
15 <xsl:import href="core.xslt"/>
16 <xsl:output method="xml" encoding="utf-8" indent="yes"/>
17 <xsl:template match="mal" name="rep">
18 <xsl:choose>
19 <xsl:when test="string(state/env/@data) = ''">
20 <xsl:variable name="argv">
21 <malval kind="list">
22 <lvalue>
23 <xsl:for-each select="argv/arg/text()">
24 <malval kind="string" value="{.}"/>
25 </xsl:for-each>
26 </lvalue>
27 </malval>
28 </xsl:variable>
29 <xsl:variable name="vstate">
30 <mal>
31 <state>
32 <env data="{env:serialise(env:empty() =&gt; env:bind-all(core:ns()/@name, core:ns()) =&gt; env:set('*ARGV*', $argv) =&gt; env:toReplEnv())}"/>
33 <atoms/>
34 </state>
35 <stdin>(do (def! not (fn* (a) (if a false true))) (def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) "\nnil)"))))) (defmacro! cond (fn* (&amp; xs) (if (&gt; (count xs) 0) (list 'if (first xs) (if (&gt; (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond (rest (rest xs))))))) (def! *host-language* "XSLT"))</stdin>
36 </mal>
37 </xsl:variable>
38 <xsl:variable name="new-state">
39 <xsl:for-each select="$vstate/mal">
40 <xsl:call-template name="rep"/>
41 </xsl:for-each>
42 </xsl:variable>
43 <xsl:variable name="state-v">
44 <xsl:sequence select="$new-state/mal/state"/>
45 <xsl:sequence select="stdin"/>
46 </xsl:variable>
47 <xsl:for-each select="$state-v">
48 <xsl:call-template name="rep"/>
49 </xsl:for-each>
50 </xsl:when>
51 <xsl:otherwise>
52 <mal>
53 <xsl:variable name="env" as="map(*)">
54 <xsl:sequence select="env:deserialise(state/env/@data)"/>
d4798a57 55 </xsl:variable>
1c2f45cf
A
56 <xsl:sequence select="stdin"/>
57 <xsl:variable name="_read">
58 <xsl:call-template name="READ"/>
d4798a57 59 </xsl:variable>
1c2f45cf
A
60 <xsl:variable name="_eval">
61 <xsl:for-each select="$_read">
62 <xsl:call-template name="EVAL">
63 <xsl:with-param name="env" select="$env"/>
64 </xsl:call-template>
d4798a57
A
65 </xsl:for-each>
66 </xsl:variable>
1c2f45cf
A
67 <xsl:for-each select="$_eval">
68 <stdout>
69 <xsl:variable name="data">
70 <xsl:sequence select="data/value"/>
71 <xsl:sequence select="atoms[1]"/>
72 </xsl:variable>
73 <xsl:for-each select="$data">
74 <xsl:call-template name="PRINT"/>
75 </xsl:for-each>
76 </stdout>
77 <state>
78 <env data="{env/@data}"/>
79 <xsl:sequence select="atoms[1]"/>
80 </state>
d4798a57 81 </xsl:for-each>
1c2f45cf
A
82 </mal>
83 </xsl:otherwise>
84 </xsl:choose>
85 </xsl:template>
86 <xsl:template name="PRINT">
87 <xsl:variable name="str">
88 <xsl:call-template name="malprinter-pr_str">
89 <xsl:with-param name="readably" select="true()"/>
90 </xsl:call-template>
91 </xsl:variable>
92 <xsl:value-of select="$str"/>
93 </xsl:template>
94 <xsl:template name="eval_ast">
95 <xsl:param name="env"/>
96 <xsl:param name="atoms"/>
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' or value/malval/@kind = 'vector' or value/malval/@kind = 'hash'">
107 <xsl:variable name="myctx">
108 <xsl:iterate select="value/malval/lvalue/malval">
109 <xsl:param name="atoms" select="$atoms"/>
110 <xsl:param name="xctx" select="()"/>
111 <xsl:on-completion>
112 <xsl:sequence select="$xctx/value/malval"/>
113 <xsl:sequence select="$atoms"/>
114 </xsl:on-completion>
115 <xsl:variable name="ctx">
116 <value>
117 <xsl:sequence select="."/>
118 </value>
119 <xsl:sequence select="$atoms"/>
d4798a57 120 </xsl:variable>
1c2f45cf
A
121 <xsl:variable name="xctxy">
122 <xsl:for-each select="$ctx">
123 <xsl:variable name="val">
124 <xsl:call-template name="EVAL">
125 <xsl:with-param name="env" select="$env"/>
a1252d40 126 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf
A
127 </xsl:call-template>
128 </xsl:variable>
129 <xsl:sequence select="$val/data/value"/>
130 <xsl:sequence select="$val/atoms"/>
d4798a57
A
131 </xsl:for-each>
132 </xsl:variable>
1c2f45cf
A
133 <xsl:next-iteration>
134 <xsl:with-param name="atoms" select="$xctxy/atoms"/>
135 <xsl:with-param name="xctx" select="$xctx, $xctxy"/>
136 </xsl:next-iteration>
137 </xsl:iterate>
138 </xsl:variable>
139 <value>
140 <malval kind="{value/malval/@kind}">
141 <lvalue>
142 <xsl:sequence select="$myctx/malval"/>
143 </lvalue>
144 </malval>
145 </value>
146 <xsl:sequence select="$myctx/atoms"/>
147 </xsl:when>
148 <xsl:otherwise>
149 <xsl:sequence select="."/>
150 <xsl:sequence select="$atoms"/>
151 </xsl:otherwise>
152 </xsl:choose>
153 </xsl:template>
154 <xsl:template name="call-function">
155 <xsl:param name="func"/>
156 <xsl:param name="args"/>
157 <xsl:param name="env"/>
158 <xsl:variable name="atoms" select="atoms"/>
159 <xsl:variable name="res">
d4798a57 160 <xsl:choose>
1c2f45cf
A
161 <xsl:when test="$func/malval/@kind = 'userfunction'">
162 <xsl:call-template name="uapply">
163 <xsl:with-param name="func" select="$func"/>
164 <xsl:with-param name="args" select="$args"/>
165 <xsl:with-param name="env" select="$env"/>
166 </xsl:call-template>
d4798a57 167 </xsl:when>
1c2f45cf
A
168 <xsl:otherwise>
169 <xsl:choose>
170 <xsl:when test="$func/malval/@name = 'env??'">
171 <!-- needs access to env -->
172 <xsl:variable name="nev" select="env:dump($env)"/>
173 <xsl:variable name="value">
174 <malval kind="string" value="{$env =&gt; serialize(map{'method':'json'})}"/>
175 </xsl:variable>
176 <value>
177 <xsl:sequence select="$value"/>
178 </value>
179 <env data="{env:serialise($env)}"/>
180 <xsl:sequence select="$value/atoms[1]"/>
181 </xsl:when>
182 <xsl:when test="$func/malval/@name = 'eval'">
183 <!-- needs access to env -->
184 <xsl:variable name="venv" select="env:replEnv($env) =&gt; env:wrapReplEnv()"/>
185 <xsl:variable name="form">
0365ac12 186 <value>
1c2f45cf 187 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
0365ac12
A
188 </value>
189 <xsl:sequence select="$atoms"/>
190 </xsl:variable>
1c2f45cf
A
191 <xsl:variable name="value">
192 <xsl:for-each select="$form">
193 <xsl:call-template name="EVAL">
194 <xsl:with-param name="env" select="$venv"/>
195 </xsl:call-template>
d4798a57 196 </xsl:for-each>
0365ac12 197 </xsl:variable>
1c2f45cf
A
198 <xsl:sequence select="$value/data/value"/>
199 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) =&gt; env:collapseReplEnv()))}"/>
200 <xsl:sequence select="$value/atoms[1]"/>
201 </xsl:when>
202 <xsl:when test="$func/malval/@name = 'atom'">
203 <!-- needs access to atoms -->
204 <xsl:variable name="atom-ident" select="count($atoms/atom)"/>
205 <value>
206 <malval kind="atom" value="{$atom-ident}"/>
207 </value>
208 <atoms>
209 <xsl:for-each select="$atoms/atom">
210 <xsl:sequence select="."/>
211 </xsl:for-each>
212 <atom identity="{$atom-ident}">
213 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
214 </atom>
215 </atoms>
216 </xsl:when>
217 <xsl:when test="$func/malval/@name = 'deref'">
218 <!-- needs access to atoms -->
219 <value>
220 <xsl:sequence select="$atoms/atom[@identity = $args/value/malval/lvalue/malval[1]/@value]/malval"/>
221 </value>
222 <xsl:sequence select="$atoms"/>
223 </xsl:when>
224 <xsl:when test="$func/malval/@name = 'reset!'">
225 <!-- needs access to atoms -->
226 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
227 <xsl:variable name="newv" select="$args/value/malval/lvalue/malval[2]"/>
228 <value>
229 <xsl:sequence select="$newv"/>
230 </value>
231 <atoms>
232 <xsl:for-each select="$atoms/atom[@identity != $atom-ident]">
233 <xsl:sequence select="."/>
234 </xsl:for-each>
235 <atom identity="{$atom-ident}">
236 <xsl:sequence select="$newv"/>
237 </atom>
238 </atoms>
239 </xsl:when>
240 <xsl:when test="$func/malval/@name = 'swap!'">
241 <!-- needs access to atoms -->
242 <xsl:variable name="atom-ident" select="$args/value/malval/lvalue/malval[1]/@value"/>
243 <xsl:variable name="atom-value" select="$atoms/atom[@identity = $atom-ident]/malval"/>
244 <xsl:variable name="fn">
245 <xsl:sequence select="$args/value/malval/lvalue/malval[2]"/>
246 </xsl:variable>
247 <xsl:variable name="cargs">
64eb1e7d 248 <value>
1c2f45cf
A
249 <malval kind="list">
250 <lvalue>
251 <xsl:sequence select="$atom-value"/>
252 <xsl:sequence select="$args/value/malval/lvalue/malval[position() &gt; 2]"/>
253 </lvalue>
254 </malval>
64eb1e7d 255 </value>
1c2f45cf
A
256 </xsl:variable>
257 <xsl:variable name="newv">
258 <xsl:call-template name="call-function">
259 <xsl:with-param name="func" select="$fn"/>
260 <xsl:with-param name="args" select="$cargs"/>
261 <xsl:with-param name="env" select="$env"/>
262 </xsl:call-template>
263 </xsl:variable>
264 <xsl:sequence select="$newv/value"/>
265 <atoms>
266 <xsl:for-each select="$newv/atoms[1]/atom[@identity != $atom-ident]">
267 <xsl:sequence select="."/>
268 </xsl:for-each>
269 <atom identity="{$atom-ident}">
270 <xsl:sequence select="$newv/value/malval"/>
271 </atom>
272 </atoms>
273 <xsl:sequence select="$newv/env"/>
274 </xsl:when>
275 <xsl:when test="$func/malval/@name = 'apply'">
276 <!-- needs access to env -->
277 <!-- (apply F A... T) -> (F A... T...) -->
278 <xsl:variable name="fun">
279 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
280 </xsl:variable>
281 <xsl:variable name="args">
64eb1e7d 282 <value>
1c2f45cf
A
283 <malval kind="list">
284 <lvalue>
285 <xsl:variable name="argc" select="count($args/value/malval/lvalue/malval)"/>
286 <xsl:sequence select="$args/value/malval/lvalue/malval[position() gt 1 and position() lt $argc]"/>
287 <xsl:sequence select="$args/value/malval/lvalue/malval[$argc]/lvalue/malval"/>
288 </lvalue>
289 </malval>
64eb1e7d 290 </value>
1c2f45cf
A
291 </xsl:variable>
292 <xsl:variable name="ctx">
293 <xsl:sequence select="./*"/>
64eb1e7d 294 <xsl:sequence select="$atoms"/>
1c2f45cf
A
295 </xsl:variable>
296 <xsl:variable name="res">
297 <xsl:for-each select="$ctx">
298 <xsl:call-template name="call-function">
299 <xsl:with-param name="func" select="$fun"/>
300 <xsl:with-param name="args" select="$args"/>
301 <xsl:with-param name="env" select="$env"/>
302 </xsl:call-template>
303 </xsl:for-each>
304 </xsl:variable>
305 <xsl:sequence select="$res/value"/>
306 <xsl:sequence select="$res/env"/>
307 <xsl:sequence select="$res/atoms[1]"/>
308 </xsl:when>
309 <xsl:when test="$func/malval/@name = 'map'">
310 <!-- needs access to env -->
311 <!-- (map F T) -> (list (F Tx)...) -->
312 <xsl:variable name="func">
313 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
314 </xsl:variable>
315 <xsl:iterate select="$args/value/malval/lvalue/malval[2]/lvalue/malval">
316 <xsl:param name="xenv" select="$env"/>
317 <xsl:param name="atoms" select="$atoms"/>
318 <xsl:param name="value" select="()"/>
319 <xsl:on-completion>
64eb1e7d
A
320 <value>
321 <malval kind="list">
322 <lvalue>
1c2f45cf 323 <xsl:sequence select="$value"/>
64eb1e7d
A
324 </lvalue>
325 </malval>
326 </value>
1c2f45cf
A
327 <env data="{$env =&gt; env:serialise()}"/>
328 <xsl:sequence select="$atoms"/>
329 </xsl:on-completion>
64eb1e7d
A
330 <xsl:variable name="args">
331 <value>
332 <malval kind="list">
333 <lvalue>
1c2f45cf 334 <xsl:sequence select="."/>
64eb1e7d
A
335 </lvalue>
336 </malval>
337 </value>
338 </xsl:variable>
339 <xsl:variable name="ctx">
340 <xsl:sequence select="./*"/>
341 <xsl:sequence select="$atoms"/>
342 </xsl:variable>
64eb1e7d
A
343 <xsl:variable name="res">
344 <xsl:for-each select="$ctx">
1c2f45cf
A
345 <xsl:call-template name="call-function">
346 <xsl:with-param name="func" select="$func"/>
347 <xsl:with-param name="args" select="$args"/>
348 <xsl:with-param name="env" select="$xenv"/>
349 </xsl:call-template>
64eb1e7d
A
350 </xsl:for-each>
351 </xsl:variable>
1c2f45cf
A
352 <xsl:next-iteration>
353 <xsl:with-param name="xenv" select="env:deserialise($res/env/@data)"/>
354 <xsl:with-param name="atoms" select="$res/atoms[1]"/>
355 <xsl:with-param name="value" select="$value, $res/value/malval"/>
356 </xsl:next-iteration>
357 </xsl:iterate>
358 </xsl:when>
359 <xsl:when test="$func/malval/@name = 'readline'">
360 <!-- requires interaction with harness -->
361 <xsl:message>
362 <request kind="readline" value="{$args/value/malval/lvalue/malval[1]/@value}"/>
363 </xsl:message>
364 <xsl:variable name="str" select="unparsed-text('xsl_input-string')"/>
365 <xsl:sequence select="core:makeMALType($str, if (string-length($str) = 0) then 'nil' else 'string')"/>
366 <xsl:sequence select="env"/>
367 <xsl:sequence select="$atoms"/>
368 </xsl:when>
369 <xsl:otherwise>
370 <xsl:variable name="ctx">
64eb1e7d 371 <xsl:sequence select="$atoms"/>
1c2f45cf
A
372 </xsl:variable>
373 <xsl:for-each select="$ctx">
374 <xsl:call-template name="core-apply">
375 <xsl:with-param name="func" select="$func"/>
376 <xsl:with-param name="args" select="$args"/>
377 </xsl:call-template>
378 </xsl:for-each>
379 <xsl:sequence select="$atoms"/>
380 </xsl:otherwise>
381 </xsl:choose>
d4798a57
A
382 </xsl:otherwise>
383 </xsl:choose>
1c2f45cf
A
384 </xsl:variable>
385 <xsl:sequence select="$res/value"/>
386 <xsl:choose>
387 <xsl:when test="$res/atoms">
388 <xsl:sequence select="$res/atoms[1]"/>
389 </xsl:when>
390 <xsl:otherwise>
391 <xsl:sequence select="atoms"/>
392 </xsl:otherwise>
393 </xsl:choose>
394 <xsl:choose>
395 <xsl:when test="$res/env">
396 <xsl:sequence select="$res/env"/>
397 </xsl:when>
398 <xsl:otherwise>
399 <env data="{$env =&gt; env:serialise()}"/>
400 </xsl:otherwise>
401 </xsl:choose>
402 </xsl:template>
403 <!-- uapply[env, fn, args] -->
404 <xsl:template name="uapply">
405 <xsl:param name="func"/>
406 <xsl:param name="args"/>
407 <xsl:param name="env"/>
408 <xsl:variable name="nenv" select="$env =&gt; env:hier(env:deserialise($func/malval/env/@data)) =&gt; env:close-with-binds($func/malval/binds/malval/@value, $args/value/malval/lvalue/malval)"/>
409 <xsl:variable name="body">
410 <value>
411 <xsl:sequence select="$func/malval/body/malval"/>
412 </value>
413 <xsl:sequence select="atoms[1]"/>
414 </xsl:variable>
415 <xsl:variable name="result">
416 <xsl:for-each select="$body">
417 <xsl:call-template name="EVAL">
418 <xsl:with-param name="env" select="$nenv"/>
419 </xsl:call-template>
420 </xsl:for-each>
421 </xsl:variable>
422 <xsl:sequence select="$result/data/value"/>
423 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($result/env/@data) =&gt; env:replEnv()))}"/>
424 <xsl:sequence select="$result/atoms[1]"/>
425 </xsl:template>
426 <xsl:template name="quasiquote">
427 <xsl:param name="ast"/>
428 <xsl:variable name="result">
d4798a57 429 <xsl:choose>
1c2f45cf
A
430 <xsl:when test="fn:is-pair($ast)">
431 <xsl:choose>
432 <xsl:when test="let $fst := $ast/lvalue/malval[1] return $fst/@kind = 'symbol' and $fst/@value = 'unquote'">
433 <xsl:sequence select="$ast/lvalue/malval[2]"/>
434 </xsl:when>
435 <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')">
d4798a57
A
436 <malval kind="list">
437 <lvalue>
1c2f45cf
A
438 <malval kind="symbol" value="concat"/>
439 <xsl:sequence select="$ast/lvalue/malval[1]/lvalue/malval[2]"/>
440 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
441 <xsl:variable name="rest-">
442 <malval kind="list">
443 <lvalue>
444 <xsl:sequence select="$rest"/>
445 </lvalue>
446 </malval>
447 </xsl:variable>
448 <xsl:call-template name="quasiquote">
449 <xsl:with-param name="ast" select="$rest-"/>
450 </xsl:call-template>
d4798a57
A
451 </lvalue>
452 </malval>
1c2f45cf
A
453 </xsl:when>
454 <xsl:otherwise>
455 <malval kind="list">
456 <lvalue>
457 <malval kind="symbol" value="cons"/>
458 <xsl:variable name="first" select="$ast/lvalue/malval[1]"/>
459 <xsl:variable name="rest" select="$ast/lvalue/malval[position() &gt; 1]"/>
460 <xsl:variable name="rest-">
461 <malval kind="list">
462 <lvalue>
463 <xsl:sequence select="$rest"/>
464 </lvalue>
465 </malval>
466 </xsl:variable>
467 <xsl:call-template name="quasiquote">
468 <xsl:with-param name="ast" select="$first"/>
469 </xsl:call-template>
470 <xsl:call-template name="quasiquote">
471 <xsl:with-param name="ast" select="$rest-/malval"/>
472 </xsl:call-template>
473 </lvalue>
474 </malval>
475 </xsl:otherwise>
476 </xsl:choose>
d4798a57
A
477 </xsl:when>
478 <xsl:otherwise>
1c2f45cf
A
479 <malval kind="list">
480 <lvalue>
481 <malval kind="symbol" value="quote"/>
482 <xsl:sequence select="$ast"/>
483 </lvalue>
484 </malval>
d4798a57
A
485 </xsl:otherwise>
486 </xsl:choose>
1c2f45cf
A
487 </xsl:variable>
488 <xsl:sequence select="$result"/>
489 </xsl:template>
490 <xsl:template name="macroexpand">
491 <xsl:param name="ast"/>
492 <xsl:param name="env"/>
a1252d40 493 <xsl:param name="encode-env"/>
1c2f45cf
A
494 <xsl:choose>
495 <xsl:when test="fn:is-macro-call($ast, $env)">
496 <xsl:variable name="fn" select="env:get($env, $ast/lvalue/malval[1]/@value)"/>
497 <xsl:variable name="args">
498 <value>
499 <malval kind="list">
500 <lvalue>
501 <xsl:sequence select="$ast/lvalue/malval[position() &gt; 1]"/>
502 </lvalue>
503 </malval>
504 </value>
505 </xsl:variable>
506 <xsl:variable name="new">
507 <xsl:call-template name="uapply">
508 <xsl:with-param name="func" select="$fn"/>
509 <xsl:with-param name="args" select="$args"/>
510 <xsl:with-param name="env" select="$env"/>
511 </xsl:call-template>
512 </xsl:variable>
513 <xsl:call-template name="macroexpand">
514 <xsl:with-param name="ast" select="$new/value/malval"/>
515 <xsl:with-param name="env" select="$env"/>
a1252d40 516 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf
A
517 </xsl:call-template>
518 </xsl:when>
519 <xsl:otherwise>
520 <value>
521 <xsl:sequence select="$ast"/>
522 </value>
523 <xsl:sequence select="atoms[1]"/>
a1252d40
A
524 <xsl:if test="$encode-env">
525 <env data="{$env =&gt; env:serialise()}"/>
526 </xsl:if>
1c2f45cf
A
527 </xsl:otherwise>
528 </xsl:choose>
529 </xsl:template>
530 <xsl:template name="EVAL">
531 <xsl:param name="env"/>
a1252d40 532 <xsl:param name="encode-env" select="true()"/>
1c2f45cf 533 <!-- <xsl:message>
d4798a57 534
0365ac12 535EVALUATE <xsl:sequence select="core:pr-str(value/malval)/value/text()"/> IN (<xsl:sequence select="empty(atoms)"/>) ATOMS <xsl:sequence select="fn:pretty(atoms)"/>
d4798a57 536
309b36ee 537</xsl:message> -->
1c2f45cf
A
538 <xsl:variable name="atoms" select="atoms[1]"/>
539 <xsl:variable name="data">
540 <xsl:choose>
541 <xsl:when test="value/malval/@kind = 'list'">
542 <xsl:choose>
543 <xsl:when test="count(value/malval/lvalue/malval) = 0">
544 <xsl:sequence select="."/>
a1252d40
A
545 <xsl:if test="$encode-env">
546 <env data="{env:serialise($env)}"/>
547 </xsl:if>
1c2f45cf
A
548 <xsl:sequence select="$atoms"/>
549 </xsl:when>
550 <xsl:otherwise>
551 <xsl:variable name="mexp">
552 <xsl:call-template name="macroexpand">
553 <xsl:with-param name="ast" select="value/malval"/>
554 <xsl:with-param name="env" select="$env"/>
a1252d40 555 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf
A
556 </xsl:call-template>
557 </xsl:variable>
558 <xsl:for-each select="$mexp">
559 <xsl:choose>
560 <xsl:when test="value/malval/@kind != 'list'">
561 <xsl:variable name="ctx">
562 <xsl:sequence select="value"/>
563 </xsl:variable>
564 <xsl:for-each select="$ctx">
565 <xsl:call-template name="eval_ast">
566 <xsl:with-param name="atoms" select="$atoms"/>
567 <xsl:with-param name="env" select="$env"/>
568 </xsl:call-template>
a1252d40
A
569 <xsl:if test="$encode-env">
570 <env data="{env:serialise($env)}"/>
571 </xsl:if>
1c2f45cf
A
572 <!-- <xsl:sequence select="$atoms"/> -->
573 </xsl:for-each>
574 </xsl:when>
575 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'def!'">
576 <xsl:variable name="name">
577 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
578 </xsl:variable>
579 <xsl:variable name="xvalue">
580 <value>
581 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
582 </value>
583 <xsl:sequence select="$atoms"/>
584 </xsl:variable>
585 <xsl:variable name="value">
586 <xsl:for-each select="$xvalue">
587 <xsl:call-template name="EVAL">
588 <xsl:with-param name="env" select="$env"/>
a1252d40 589 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf 590 </xsl:call-template>
d4798a57 591 </xsl:for-each>
1c2f45cf
A
592 </xsl:variable>
593 <xsl:sequence select="$value/data/value"/>
a1252d40
A
594 <xsl:if test="$encode-env">
595 <env data="{env:serialise(env:set($env, $name, $value/data/value/malval))}"/>
596 </xsl:if>
1c2f45cf
A
597 <xsl:sequence select="$value/atoms[1]"/>
598 </xsl:when>
599 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'defmacro!'">
600 <xsl:variable name="name">
601 <xsl:value-of select="value/malval/lvalue/malval[2]/@value"/>
602 </xsl:variable>
603 <xsl:variable name="xvalue">
604 <value>
605 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
606 </value>
607 <xsl:sequence select="$atoms"/>
608 </xsl:variable>
609 <xsl:variable name="value">
610 <xsl:for-each select="$xvalue">
611 <xsl:call-template name="EVAL">
612 <xsl:with-param name="env" select="$env"/>
a1252d40 613 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf
A
614 </xsl:call-template>
615 </xsl:for-each>
616 </xsl:variable>
617 <xsl:variable name="resv">
618 <value>
619 <malval kind="{$value/data/value/malval/@kind}" value="{$value/data/value/malval/@value}">
620 <xsl:sequence select="$value/data/value/malval/*[name() != 'is_macro']"/>
621 <is_macro>true</is_macro>
622 </malval>
623 </value>
624 </xsl:variable>
625 <xsl:sequence select="$resv"/>
a1252d40
A
626 <xsl:if test="$encode-env">
627 <env data="{env:serialise(env:set($env, $name, $resv/value/malval))}"/>
628 </xsl:if>
1c2f45cf
A
629 <xsl:sequence select="$value/atoms[1]"/>
630 </xsl:when>
631 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'let*'">
632 <xsl:variable name="xvalue">
633 <value>
634 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
635 </value>
636 <xsl:sequence select="$atoms"/>
637 </xsl:variable>
638 <xsl:iterate select="fn:group_consec(value/malval/lvalue/malval[2]/lvalue/malval)">
639 <xsl:param name="new_env" select="env:close($env)"/>
640 <xsl:param name="new_atoms" select="$atoms"/>
641 <xsl:on-completion>
642 <xsl:variable name="xvalue">
643 <xsl:sequence select="$xvalue/value"/>
644 <xsl:sequence select="$new_atoms"/>
645 </xsl:variable>
646 <xsl:variable name="value">
647 <xsl:for-each select="$xvalue">
648 <xsl:call-template name="EVAL">
649 <xsl:with-param name="env" select="$new_env"/>
a1252d40 650 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf
A
651 </xsl:call-template>
652 </xsl:for-each>
653 </xsl:variable>
654 <xsl:sequence select="$value/data/value"/>
a1252d40
A
655 <xsl:if test="$encode-env">
656 <env data="{env:serialise(env:swap-replEnv($env, env:deserialise($value/env/@data) =&gt; env:replEnv()))}"/>
657 </xsl:if>
1c2f45cf
A
658 <xsl:sequence select="$value/atoms[1]"/>
659 </xsl:on-completion>
d4798a57 660 <xsl:variable name="name">
1c2f45cf 661 <xsl:value-of select="node()[name() = 'first']/malval/@value"/>
d4798a57
A
662 </xsl:variable>
663 <xsl:variable name="xvalue">
664 <value>
1c2f45cf 665 <xsl:sequence select="node()[name() = 'second']/malval"/>
d4798a57 666 </value>
1c2f45cf 667 <xsl:sequence select="$new_atoms"/>
d4798a57
A
668 </xsl:variable>
669 <xsl:variable name="value">
670 <xsl:for-each select="$xvalue">
1c2f45cf
A
671 <xsl:call-template name="EVAL">
672 <xsl:with-param name="env" select="$new_env"/>
a1252d40 673 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf 674 </xsl:call-template>
d4798a57
A
675 </xsl:for-each>
676 </xsl:variable>
1c2f45cf
A
677 <xsl:next-iteration>
678 <xsl:with-param name="new_env" select="env:set($new_env, $name, $value/data/value/malval)"/>
679 <xsl:with-param name="new_atoms" select="$value/atoms[1]"/>
680 </xsl:next-iteration>
681 </xsl:iterate>
682 </xsl:when>
683 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'do'">
684 <xsl:iterate select="value/malval/lvalue/malval[position() &gt; 1]">
685 <xsl:param name="new_env" select="$env"/>
686 <xsl:param name="atoms" select="$atoms"/>
687 <xsl:param name="previous_res" select="()"/>
688 <xsl:on-completion>
689 <xsl:sequence select="$previous_res"/>
a1252d40
A
690 <xsl:if test="$encode-env">
691 <env data="{env:serialise($new_env)}"/>
692 </xsl:if>
1c2f45cf
A
693 <xsl:sequence select="$atoms"/>
694 </xsl:on-completion>
d4798a57
A
695 <xsl:variable name="xvalue">
696 <value>
1c2f45cf 697 <xsl:sequence select="."/>
d4798a57
A
698 </value>
699 <xsl:sequence select="$atoms"/>
700 </xsl:variable>
701 <xsl:variable name="value">
702 <xsl:for-each select="$xvalue">
1c2f45cf
A
703 <xsl:call-template name="EVAL">
704 <xsl:with-param name="env" select="$new_env"/>
705 </xsl:call-template>
d4798a57
A
706 </xsl:for-each>
707 </xsl:variable>
1c2f45cf
A
708 <xsl:next-iteration>
709 <xsl:with-param name="new_env" select="env:deserialise($value/env/@data)"/>
710 <xsl:with-param name="previous_res" select="$value/data/value"/>
711 <xsl:with-param name="atoms" select="$value/atoms[1]"/>
712 </xsl:next-iteration>
713 </xsl:iterate>
714 </xsl:when>
715 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'if'">
716 <xsl:variable name="cond">
717 <xsl:for-each select="value/malval/lvalue/malval[2]">
718 <xsl:variable name="context">
719 <value>
720 <xsl:sequence select="."/>
721 </value>
722 <xsl:sequence select="$atoms"/>
723 </xsl:variable>
724 <xsl:for-each select="$context">
725 <xsl:call-template name="EVAL">
726 <xsl:with-param name="env" select="$env"/>
a1252d40 727 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf
A
728 </xsl:call-template>
729 </xsl:for-each>
730 </xsl:for-each>
731 </xsl:variable>
732 <xsl:variable name="ptrue">
733 <xsl:for-each select="value/malval/lvalue/malval[3]">
d4798a57 734 <value>
1c2f45cf 735 <xsl:sequence select="."/>
d4798a57 736 </value>
1c2f45cf
A
737 <xsl:sequence select="$cond/atoms[1]"/>
738 </xsl:for-each>
739 </xsl:variable>
740 <xsl:variable name="pfalse">
741 <xsl:for-each select="value/malval/lvalue/malval[4]">
742 <value>
743 <xsl:sequence select="."/>
744 </value>
745 <xsl:sequence select="$cond/atoms[1]"/>
746 </xsl:for-each>
747 </xsl:variable>
748 <xsl:variable name="xfalse">
749 <xsl:choose>
750 <xsl:when test="empty($pfalse/value)">
d4798a57 751 <value>
1c2f45cf 752 <malval kind="nil"/>
d4798a57 753 </value>
1c2f45cf
A
754 <xsl:sequence select="$cond/atoms[1]"/>
755 </xsl:when>
756 <xsl:otherwise>
757 <xsl:sequence select="$pfalse/value"/>
758 <xsl:sequence select="$pfalse/atoms[1]"/>
759 </xsl:otherwise>
760 </xsl:choose>
761 </xsl:variable>
762 <xsl:variable name="res">
763 <xsl:choose>
764 <xsl:when test="let $kind := $cond/data/value/malval/@kind return $kind = 'nil' or $kind = 'false'">
765 <xsl:for-each select="$xfalse">
766 <xsl:call-template name="EVAL">
767 <xsl:with-param name="env" select="$env"/>
a1252d40 768 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf 769 </xsl:call-template>
d4798a57 770 </xsl:for-each>
1c2f45cf
A
771 </xsl:when>
772 <xsl:otherwise>
773 <xsl:for-each select="$ptrue">
774 <xsl:call-template name="EVAL">
775 <xsl:with-param name="env" select="$env"/>
a1252d40 776 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf
A
777 </xsl:call-template>
778 </xsl:for-each>
779 </xsl:otherwise>
780 </xsl:choose>
781 </xsl:variable>
782 <xsl:sequence select="$res/data/value"/>
a1252d40
A
783 <xsl:if test="$encode-env">
784 <xsl:sequence select="$res/env"/>
785 </xsl:if>
1c2f45cf
A
786 <xsl:sequence select="$res/atoms[1]"/>
787 </xsl:when>
788 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'fn*'">
789 <value>
790 <malval kind="userfunction">
791 <is_macro>false</is_macro>
792 <binds>
793 <xsl:sequence select="value/malval/lvalue/malval[2]/lvalue/malval"/>
794 </binds>
795 <body>
796 <xsl:sequence select="value/malval/lvalue/malval[3]"/>
797 </body>
798 <env data="{env:serialise(env:noReplEnv($env))}"/>
799 <!-- capture current env -->
800 </malval>
801 </value>
a1252d40
A
802 <xsl:if test="$encode-env">
803 <env data="{env:serialise($env)}"/>
804 </xsl:if>
1c2f45cf
A
805 <xsl:sequence select="$atoms"/>
806 </xsl:when>
807 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quote'">
808 <value>
809 <xsl:sequence select="value/malval/lvalue/malval[2]"/>
810 </value>
a1252d40
A
811 <xsl:if test="$encode-env">
812 <env data="{env:serialise($env)}"/>
813 </xsl:if>
1c2f45cf
A
814 <xsl:sequence select="$atoms"/>
815 </xsl:when>
816 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'quasiquote'">
817 <xsl:variable name="exp">
818 <value>
819 <xsl:call-template name="quasiquote">
820 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
821 </xsl:call-template>
822 </value>
823 <xsl:sequence select="$atoms"/>
824 </xsl:variable>
825 <xsl:variable name="res">
826 <xsl:for-each select="$exp">
827 <xsl:call-template name="EVAL">
828 <xsl:with-param name="env" select="$env"/>
a1252d40 829 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf
A
830 </xsl:call-template>
831 </xsl:for-each>
832 </xsl:variable>
833 <xsl:sequence select="$res/data/value"/>
a1252d40
A
834 <xsl:if test="$encode-env">
835 <xsl:sequence select="$res/env"/>
836 </xsl:if>
1c2f45cf
A
837 <xsl:sequence select="$res/atoms[1]"/>
838 </xsl:when>
839 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'macroexpand'">
840 <xsl:variable name="exp">
841 <xsl:call-template name="macroexpand">
842 <xsl:with-param name="ast" select="value/malval/lvalue/malval[2]"/>
843 <xsl:with-param name="env" select="$env"/>
a1252d40 844 <xsl:with-param name="encode-env" select="false()"/>
1c2f45cf
A
845 </xsl:call-template>
846 <xsl:sequence select="$atoms"/>
847 </xsl:variable>
848 <xsl:sequence select="$exp/value"/>
a1252d40
A
849 <xsl:if test="$encode-env">
850 <env data="{env:serialise($env)}"/>
851 </xsl:if>
1c2f45cf
A
852 <xsl:sequence select="$atoms"/>
853 </xsl:when>
854 <xsl:when test="let $fn := value/malval/lvalue/malval[1] return $fn/@kind = 'symbol' and $fn/@value = 'try*'">
855 <xsl:variable name="tryv">
856 <xsl:try>
d4798a57
A
857 <xsl:variable name="xvalue">
858 <value>
1c2f45cf 859 <xsl:sequence select="value/malval/lvalue/malval[2]"/>
d4798a57
A
860 </value>
861 <xsl:sequence select="$atoms"/>
862 </xsl:variable>
863 <xsl:variable name="value">
864 <xsl:for-each select="$xvalue">
1c2f45cf
A
865 <xsl:call-template name="EVAL">
866 <xsl:with-param name="env" select="$env"/>
a1252d40 867 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf 868 </xsl:call-template>
d4798a57
A
869 </xsl:for-each>
870 </xsl:variable>
1c2f45cf 871 <xsl:sequence select="$value/data/value"/>
a1252d40
A
872 <xsl:if test="$encode-env">
873 <xsl:sequence select="$value/env"/>
874 </xsl:if>
1c2f45cf
A
875 <xsl:sequence select="$value/atoms[1]"/>
876 <xsl:catch errors="*">
877 <xsl:variable name="catchv-name" select="value/malval/lvalue/malval[3]/lvalue/malval[2]/@value"/>
878 <xsl:variable name="catchv">
d4798a57 879 <value>
1c2f45cf 880 <xsl:sequence select="value/malval/lvalue/malval[3]/lvalue/malval[3]"/>
d4798a57 881 </value>
d4798a57 882 </xsl:variable>
1c2f45cf
A
883 <xsl:if test="empty($catchv/value/malval)">
884 <xsl:value-of select="error($err:code, $err:description, $err:value)"/>
885 </xsl:if>
886 <xsl:variable name="newenv" select="env:close($env) =&gt; env:set($catchv-name, $err:value)"/>
d4798a57 887 <xsl:variable name="value">
1c2f45cf
A
888 <xsl:for-each select="$catchv">
889 <xsl:call-template name="EVAL">
890 <xsl:with-param name="env" select="$newenv"/>
a1252d40 891 <xsl:with-param name="encode-env" select="$encode-env"/>
1c2f45cf 892 </xsl:call-template>
d4798a57
A
893 </xsl:for-each>
894 </xsl:variable>
895 <xsl:sequence select="$value/data/value"/>
a1252d40
A
896 <xsl:if test="$encode-env">
897 <xsl:sequence select="$value/env"/>
898 <!-- leaks the bound name, ouch -->
899 </xsl:if>
d4798a57 900 <xsl:sequence select="$value/atoms[1]"/>
1c2f45cf
A
901 </xsl:catch>
902 </xsl:try>
903 </xsl:variable>
904 <xsl:sequence select="$tryv"/>
905 </xsl:when>
906 <xsl:otherwise>
907 <xsl:variable name="new_list">
908 <xsl:call-template name="eval_ast">
909 <xsl:with-param name="atoms" select="$atoms"/>
910 <xsl:with-param name="env" select="$env"/>
911 </xsl:call-template>
912 </xsl:variable>
913 <xsl:variable name="func">
914 <xsl:for-each select="$new_list">
915 <xsl:sequence select="value/malval/lvalue/malval[1]"/>
d4798a57 916 </xsl:for-each>
1c2f45cf
A
917 </xsl:variable>
918 <xsl:variable name="args">
919 <xsl:for-each select="$new_list">
920 <value>
921 <malval kind="list">
922 <lvalue>
923 <xsl:sequence select="value/malval/lvalue/node()[position() != 1]"/>
924 </lvalue>
925 </malval>
926 </value>
927 </xsl:for-each>
928 </xsl:variable>
929 <xsl:variable name="ctx">
930 <xsl:sequence select="$new_list/atoms"/>
931 </xsl:variable>
932 <xsl:variable name="resultv">
933 <xsl:for-each select="$ctx">
934 <xsl:call-template name="call-function">
935 <xsl:with-param name="env" select="$env"/>
936 <xsl:with-param name="func" select="$func"/>
937 <xsl:with-param name="args" select="$args"/>
938 </xsl:call-template>
939 </xsl:for-each>
940 </xsl:variable>
941 <xsl:for-each select="$resultv">
942 <xsl:choose>
943 <xsl:when test="empty(env)">
a1252d40
A
944 <xsl:if test="$encode-env">
945 <env data="{env:serialise($env)}"/>
946 </xsl:if>
1c2f45cf
A
947 </xsl:when>
948 <xsl:otherwise>
a1252d40
A
949 <xsl:if test="$encode-env">
950 <xsl:sequence select="env"/>
951 </xsl:if>
1c2f45cf
A
952 </xsl:otherwise>
953 </xsl:choose>
954 <xsl:sequence select="atoms[1]"/>
955 <xsl:sequence select="value"/>
956 </xsl:for-each>
957 </xsl:otherwise>
958 </xsl:choose>
959 </xsl:for-each>
960 </xsl:otherwise>
961 </xsl:choose>
962 </xsl:when>
963 <xsl:otherwise>
964 <xsl:call-template name="eval_ast">
965 <xsl:with-param name="atoms" select="$atoms"/>
966 <xsl:with-param name="env" select="$env"/>
967 </xsl:call-template>
a1252d40
A
968 <xsl:if test="$encode-env">
969 <env data="{env:serialise($env)}"/>
970 </xsl:if>
1c2f45cf
A
971 <!-- <xsl:sequence select="$atoms"/> -->
972 </xsl:otherwise>
973 </xsl:choose>
974 </xsl:variable>
975 <xsl:variable name="new-atoms" select="($data/atoms[1], $atoms)[1]"/>
976 <!-- <xsl:message>
977EVALUATED (<xsl:sequence select="empty($data/atoms)"/>) <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="fn:pretty($new-atoms)"/>
978 </xsl:message> -->
979 <data>
980 <xsl:sequence select="$data/value"/>
981 </data>
a1252d40
A
982 <xsl:if test="$encode-env">
983 <env data="{$data/env/@data}"/>
984 </xsl:if>
1c2f45cf
A
985 <xsl:sequence select="$new-atoms"/>
986 </xsl:template>
987 <xsl:template name="READ">
988 <xsl:variable name="context">
989 <str>
990 <xsl:copy-of select="stdin/text()"/>
991 </str>
992 </xsl:variable>
993 <xsl:variable name="form">
994 <xsl:sequence select="state/atoms[1]"/>
995 <xsl:for-each select="$context">
996 <xsl:call-template name="malreader-read_str"/>
997 </xsl:for-each>
998 </xsl:variable>
999 <xsl:for-each select="$form">
1000 <xsl:if test="error">
1001 <xsl:value-of select="error(QName('MAL', 'Error'), string(error))"/>
1002 </xsl:if>
1003 <xsl:sequence select="."/>
1004 </xsl:for-each>
1005 </xsl:template>
1006 <xsl:function name="fn:group_consec">
1007 <xsl:param name="nodes"/>
1008 <xsl:variable name="groups">
1009 <xsl:for-each-group select="$nodes" group-by="position() mod 2">
1010 <xsl:choose>
1011 <xsl:when test="position() = 1">
1012 <first>
1013 <xsl:sequence select="current-group()"/>
1014 </first>
d4798a57
A
1015 </xsl:when>
1016 <xsl:otherwise>
1c2f45cf
A
1017 <second>
1018 <xsl:sequence select="current-group()"/>
1019 </second>
d4798a57
A
1020 </xsl:otherwise>
1021 </xsl:choose>
1c2f45cf
A
1022 </xsl:for-each-group>
1023 </xsl:variable>
1024 <xsl:iterate select="1 to count($groups/first/*)">
1025 <element>
1026 <xsl:variable name="idx" select="number(.)"/>
1027 <first>
1028 <xsl:sequence select="$groups/first/node()[position() = $idx]"/>
1029 </first>
1030 <second>
1031 <xsl:sequence select="$groups/second/node()[position() = $idx]"/>
1032 </second>
1033 </element>
1034 </xsl:iterate>
1035 </xsl:function>
1036 <xsl:function name="fn:is-pair">
1037 <xsl:param name="list"/>
1038 <xsl:sequence select="($list/@kind = 'list' or $list/@kind = 'vector') and count($list/lvalue/malval) != 0"/>
1039 </xsl:function>
1040 <xsl:function name="fn:is-macro-call">
1041 <xsl:param name="ast"/>
1042 <xsl:param name="env"/>
1043 <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')"/>
1044 <xsl:sequence select="$res"/>
1045 </xsl:function>
1046 <xsl:function name="fn:pretty">
1047 <xsl:param name="atoms"/>
1048 <xsl:sequence select="$atoms/atom/concat('(', @identity, ': ', malval/@kind, ' ', core:pr-str(malval), ')')"/>
1049 </xsl:function>
d4798a57 1050</xsl:stylesheet>