1 <?xml version="1.0" encoding="UTF-8"?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:core="CORE" version="3.0" exclude-result-prefixes="core fn xsl xs">
3 <xsl:function name="core:ns">
5 <malval kind="function" name="+">
6 <is_macro>false</is_macro>
8 <malval kind="function" name="-">
9 <is_macro>false</is_macro>
11 <malval kind="function" name="*">
12 <is_macro>false</is_macro>
14 <malval kind="function" name="/">
15 <is_macro>false</is_macro>
17 <malval kind="function" name="prn">
18 <is_macro>false</is_macro>
20 <malval kind="function" name="pr-str">
21 <is_macro>false</is_macro>
23 <malval kind="function" name="str">
24 <is_macro>false</is_macro>
26 <malval kind="function" name="println">
27 <is_macro>false</is_macro>
29 <malval kind="function" name="list">
30 <is_macro>false</is_macro>
32 <malval kind="function" name="list?">
33 <is_macro>false</is_macro>
35 <malval kind="function" name="empty?">
36 <is_macro>false</is_macro>
38 <malval kind="function" name="count">
39 <is_macro>false</is_macro>
41 <malval kind="function" name="=">
42 <is_macro>false</is_macro>
44 <malval kind="function" name="<">
45 <is_macro>false</is_macro>
47 <malval kind="function" name="<=">
48 <is_macro>false</is_macro>
50 <malval kind="function" name=">">
51 <is_macro>false</is_macro>
53 <malval kind="function" name=">=">
54 <is_macro>false</is_macro>
56 <malval kind="function" name="read-string">
57 <is_macro>false</is_macro>
59 <malval kind="function" name="slurp">
60 <is_macro>false</is_macro>
62 <malval kind="function" name="eval">
63 <is_macro>false</is_macro>
65 <!-- defined in the step files -->
66 <malval kind="function" name="atom">
67 <is_macro>false</is_macro>
69 <!-- defined in the step files -->
70 <malval kind="function" name="atom?">
71 <is_macro>false</is_macro>
73 <malval kind="function" name="deref">
74 <is_macro>false</is_macro>
76 <!-- defined in the step files -->
77 <malval kind="function" name="swap!">
78 <is_macro>false</is_macro>
80 <!-- defined in the step files -->
81 <malval kind="function" name="reset!">
82 <is_macro>false</is_macro>
84 <!-- defined in the step files -->
85 <malval kind="function" name="cons">
86 <is_macro>false</is_macro>
88 <malval kind="function" name="concat">
89 <is_macro>false</is_macro>
91 <malval kind="function" name="nth">
92 <is_macro>false</is_macro>
94 <malval kind="function" name="first">
95 <is_macro>false</is_macro>
97 <malval kind="function" name="rest">
98 <is_macro>false</is_macro>
100 <malval kind="function" name="throw">
101 <is_macro>false</is_macro>
103 <malval kind="function" name="apply">
104 <is_macro>false</is_macro>
106 <!-- defined in the step files -->
107 <malval kind="function" name="map">
108 <is_macro>false</is_macro>
110 <!-- defined in the step files -->
111 <malval kind="function" name="nil?">
112 <is_macro>false</is_macro>
114 <malval kind="function" name="true?">
115 <is_macro>false</is_macro>
117 <malval kind="function" name="false?">
118 <is_macro>false</is_macro>
120 <malval kind="function" name="symbol?">
121 <is_macro>false</is_macro>
123 <malval kind="function" name="symbol">
124 <is_macro>false</is_macro>
126 <malval kind="function" name="keyword">
127 <is_macro>false</is_macro>
129 <malval kind="function" name="keyword?">
130 <is_macro>false</is_macro>
132 <malval kind="function" name="vector">
133 <is_macro>false</is_macro>
135 <malval kind="function" name="vector?">
136 <is_macro>false</is_macro>
138 <malval kind="function" name="sequential?">
139 <is_macro>false</is_macro>
141 <malval kind="function" name="hash-map">
142 <is_macro>false</is_macro>
144 <malval kind="function" name="map?">
145 <is_macro>false</is_macro>
147 <malval kind="function" name="assoc">
148 <is_macro>false</is_macro>
150 <malval kind="function" name="dissoc">
151 <is_macro>false</is_macro>
153 <malval kind="function" name="get">
154 <is_macro>false</is_macro>
156 <malval kind="function" name="contains?">
157 <is_macro>false</is_macro>
159 <malval kind="function" name="keys">
160 <is_macro>false</is_macro>
162 <malval kind="function" name="vals">
163 <is_macro>false</is_macro>
165 <malval kind="function" name="readline">
166 <is_macro>false</is_macro>
168 <!-- defined in step file -->
169 <malval kind="function" name="meta">
170 <is_macro>false</is_macro>
172 <malval kind="function" name="with-meta">
173 <is_macro>false</is_macro>
175 <malval kind="function" name="time-ms">
176 <is_macro>false</is_macro>
178 <malval kind="function" name="conj">
179 <is_macro>false</is_macro>
181 <malval kind="function" name="string?">
182 <is_macro>false</is_macro>
184 <malval kind="function" name="number?">
185 <is_macro>false</is_macro>
187 <malval kind="function" name="fn?">
188 <is_macro>false</is_macro>
190 <malval kind="function" name="macro?">
191 <is_macro>false</is_macro>
193 <malval kind="function" name="seq">
194 <is_macro>false</is_macro>
196 <malval kind="function" name="xpath-eval">
197 <is_macro>false</is_macro>
199 <!-- evaluate xpath, no context node | requires Saxon PE/EE [paywalls piss me off] -->
202 <xsl:template name="core-apply">
203 <xsl:param name="func"/>
204 <xsl:param name="args"/>
205 <xsl:variable name="atoms" select="atoms"/>
207 <xsl:when test="$func/malval/@kind = 'function'">
209 <xsl:when test="$func/malval/@name = '+'">
210 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) + number($args/value/malval/lvalue/malval[2]/@value)"/>
211 <xsl:sequence select="core:makeMALType($result, 'number')"/>
213 <xsl:when test="$func/malval/@name = '-'">
214 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) - number($args/value/malval/lvalue/malval[2]/@value)"/>
215 <xsl:sequence select="core:makeMALType($result, 'number')"/>
217 <xsl:when test="$func/malval/@name = '*'">
218 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) * number($args/value/malval/lvalue/malval[2]/@value)"/>
219 <xsl:sequence select="core:makeMALType($result, 'number')"/>
221 <xsl:when test="$func/malval/@name = '/'">
222 <xsl:variable name="result" select="number($args/value/malval/lvalue/malval[1]/@value) div number($args/value/malval/lvalue/malval[2]/@value)"/>
223 <xsl:sequence select="core:makeMALType($result, 'number')"/>
225 <xsl:when test="$func/malval/@name = 'prn'">
226 <xsl:variable name="args" select="$args/value/malval/lvalue/malval"/>
227 <xsl:variable name="sargs">
228 <xsl:for-each select="$args">
229 <xsl:variable name="arg">
231 <xsl:sequence select="."/>
233 <xsl:sequence select="$atoms"/>
236 <xsl:for-each select="$arg">
237 <xsl:call-template name="malprinter-pr_str">
238 <xsl:with-param name="readably" select="true()"/>
245 <request kind="display" value="{string-join($sargs/str, ' ')}"/>
247 <xsl:sequence select="core:makeMALType((), 'nil')"/>
249 <xsl:when test="$func/malval/@name = 'pr-str'">
250 <xsl:variable name="args" select="$args/value/malval/lvalue/malval"/>
251 <xsl:variable name="sargs">
252 <xsl:for-each select="$args">
253 <xsl:variable name="arg">
255 <xsl:sequence select="."/>
257 <xsl:sequence select="$atoms"/>
260 <xsl:for-each select="$arg">
261 <xsl:call-template name="malprinter-pr_str">
262 <xsl:with-param name="readably" select="true()"/>
268 <xsl:sequence select="core:makeMALType(string-join($sargs/str, ' '), 'string')"/>
270 <xsl:when test="$func/malval/@name = 'str'">
271 <xsl:variable name="args" select="$args/value/malval/lvalue/malval"/>
272 <xsl:variable name="sargs">
273 <xsl:for-each select="$args">
274 <xsl:variable name="arg">
276 <xsl:sequence select="."/>
278 <xsl:sequence select="$atoms"/>
281 <xsl:for-each select="$arg">
282 <xsl:call-template name="malprinter-pr_str">
283 <xsl:with-param name="readably" select="false()"/>
289 <xsl:sequence select="core:makeMALType(string-join($sargs/str, ''), 'string')"/>
291 <xsl:when test="$func/malval/@name = 'println'">
292 <xsl:variable name="args" select="$args/value/malval/lvalue/malval"/>
293 <xsl:variable name="sargs">
294 <xsl:for-each select="$args">
295 <xsl:variable name="arg">
297 <xsl:sequence select="."/>
299 <xsl:sequence select="$atoms"/>
302 <xsl:for-each select="$arg">
303 <xsl:call-template name="malprinter-pr_str">
304 <xsl:with-param name="readably" select="false()"/>
311 <request kind="display" value="{string-join($sargs/str, ' ')}"/>
313 <xsl:sequence select="core:makeMALType((), 'nil')"/>
315 <xsl:when test="$func/malval/@name = 'list'">
316 <xsl:sequence select="$args"/>
318 <xsl:when test="$func/malval/@name = 'list?'">
319 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'list') then 'true' else 'false')"/>
321 <xsl:when test="$func/malval/@name = 'empty?'">
322 <xsl:sequence select="core:makeMALType((), if (count($args/value/malval/lvalue/malval[1]/lvalue/malval) = 0) then 'true' else 'false')"/>
324 <xsl:when test="$func/malval/@name = 'count'">
326 <xsl:when test="$args/value/malval/lvalue/malval[1]/@kind = 'hash'">
327 <xsl:sequence select="core:makeMALType(count($args/value/malval/lvalue/malval[1]/lvalue/malval) div 2, 'number')"/>
330 <xsl:sequence select="core:makeMALType(count($args/value/malval/lvalue/malval[1]/lvalue/malval), 'number')"/>
334 <xsl:when test="$func/malval/@name = '='">
335 <xsl:sequence select="core:makeMALType((), if (core:equal($args/value/malval/lvalue/malval[1], $args/value/malval/lvalue/malval[2])) then 'true' else 'false')"/>
337 <xsl:when test="$func/malval/@name = '<'">
338 <xsl:sequence select="core:makeMALType((), if (number($args/value/malval/lvalue/malval[1]/@value) lt number($args/value/malval/lvalue/malval[2]/@value)) then 'true' else 'false')"/>
340 <xsl:when test="$func/malval/@name = '<='">
341 <xsl:sequence select="core:makeMALType((), if (number($args/value/malval/lvalue/malval[1]/@value) le number($args/value/malval/lvalue/malval[2]/@value)) then 'true' else 'false')"/>
343 <xsl:when test="$func/malval/@name = '>'">
344 <xsl:sequence select="core:makeMALType((), if (number($args/value/malval/lvalue/malval[1]/@value) gt number($args/value/malval/lvalue/malval[2]/@value)) then 'true' else 'false')"/>
346 <xsl:when test="$func/malval/@name = '>='">
347 <xsl:sequence select="core:makeMALType((), if (number($args/value/malval/lvalue/malval[1]/@value) ge number($args/value/malval/lvalue/malval[2]/@value)) then 'true' else 'false')"/>
349 <xsl:when test="$func/malval/@name = 'read-string'">
350 <xsl:variable name="read-string-context">
352 <xsl:value-of select="$args/value/malval/lvalue/malval[1]/@value"/>
355 <xsl:for-each select="$read-string-context">
356 <xsl:call-template name="malreader-read_str"/>
359 <xsl:when test="$func/malval/@name = 'slurp'">
360 <xsl:sequence select="core:makeMALType(unparsed-text($args/value/malval/lvalue/malval[1]/@value), 'string')"/>
362 <xsl:when test="$func/malval/@name = 'atom?'">
363 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'atom') then 'true' else 'false')"/>
365 <xsl:when test="$func/malval/@name = 'cons'">
366 <xsl:variable name="result">
370 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
371 <xsl:sequence select="$args/value/malval/lvalue/malval[2]/lvalue/malval"/>
376 <xsl:sequence select="$result"/>
378 <xsl:when test="$func/malval/@name = 'concat'">
379 <xsl:variable name="result">
383 <xsl:sequence select="$args/value/malval/lvalue/malval/lvalue/malval"/>
388 <xsl:sequence select="$result"/>
390 <xsl:when test="$func/malval/@name = 'nth'">
392 <xsl:variable name="res" select="$args/value/malval/lvalue/malval[1]/lvalue/malval[position() = (number($args/value/malval/lvalue/malval[2]/@value) + 1)]"/>
393 <xsl:if test="empty($res)">
394 <xsl:value-of select="error(QName('MAL', 'Error'), 'Index out of bounds', core:makeMALValue('Index out of bounds', 'string'))"/>
396 <xsl:sequence select="$res"/>
399 <xsl:when test="$func/malval/@name = 'first'">
401 <xsl:variable name="res" select="$args/value/malval/lvalue/malval[1]/lvalue/malval[1]"/>
403 <xsl:when test="empty($res)">
407 <xsl:sequence select="$res"/>
412 <xsl:when test="$func/malval/@name = 'rest'">
416 <xsl:sequence select="$args/value/malval/lvalue/malval[1]/lvalue/malval[position() > 1]"/>
421 <xsl:when test="$func/malval/@name = 'throw'">
422 <xsl:variable name="err" select="$args/value/malval/lvalue/malval[1]"/>
423 <xsl:value-of select="error(QName('MAL', 'Error'), core:pr-str($err), $err)"/>
425 <xsl:when test="$func/malval/@name = 'nil?'">
426 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'nil') then 'true' else 'false')"/>
428 <xsl:when test="$func/malval/@name = 'true?'">
429 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'true') then 'true' else 'false')"/>
431 <xsl:when test="$func/malval/@name = 'false?'">
432 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'false') then 'true' else 'false')"/>
434 <xsl:when test="$func/malval/@name = 'symbol?'">
435 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'symbol') then 'true' else 'false')"/>
437 <xsl:when test="$func/malval/@name = 'symbol'">
438 <xsl:sequence select="core:makeMALType($args/value/malval/lvalue/malval[1]/@value, 'symbol')"/>
440 <xsl:when test="$func/malval/@name = 'keyword'">
441 <xsl:sequence select="core:makeMALType($args/value/malval/lvalue/malval[1]/@value, 'keyword')"/>
443 <xsl:when test="$func/malval/@name = 'keyword?'">
444 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'keyword') then 'true' else 'false')"/>
446 <xsl:when test="$func/malval/@name = 'vector'">
448 <malval kind="vector">
449 <xsl:sequence select="$args/value/malval/lvalue"/>
453 <xsl:when test="$func/malval/@name = 'vector?'">
454 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'vector') then 'true' else 'false')"/>
456 <xsl:when test="$func/malval/@name = 'sequential?'">
457 <xsl:sequence select="core:makeMALType((), if (let $kind := $args/value/malval/lvalue/malval[1]/@kind return $kind = 'vector' or $kind = 'list') then 'true' else 'false')"/>
459 <xsl:when test="$func/malval/@name = 'hash-map'">
460 <xsl:if test="count($args/value/malval/lvalue/malval) mod 2 = 1">
461 <xsl:value-of select="error(QName('MAL', 'Error'), 'Odd number of args to hash-map', core:makeMALValue('Odd number of args to hash-map', 'string'))"/>
465 <xsl:sequence select="$args/value/malval/lvalue"/>
469 <xsl:when test="$func/malval/@name = 'map?'">
470 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'hash') then 'true' else 'false')"/>
472 <xsl:when test="$func/malval/@name = 'assoc'">
473 <xsl:if test="count($args/value/malval/lvalue/malval) mod 2 = 0">
474 <xsl:value-of select="error(QName('MAL', 'Error'), 'Odd number of args to assoc', core:makeMALValue('Odd number of args to assoc', 'string'))"/>
476 <xsl:variable name="names" select="$args/value/malval/lvalue/malval[(position() gt 1) and (position() mod 2 = 0)]"/>
477 <xsl:variable name="values" select="$args/value/malval/lvalue/malval[(position() gt 2) and (position() mod 2 = 1)]"/>
478 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return core:map-dissoc($hash/lvalue/malval, $names) => core:map-assoc($names, $values) => core:makeMALList('hash')"/>
480 <xsl:when test="$func/malval/@name = 'dissoc'">
481 <xsl:variable name="names" select="$args/value/malval/lvalue/malval[position() gt 1]"/>
482 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return core:map-dissoc($hash/lvalue/malval, $names) => core:makeMALList('hash')"/>
484 <xsl:when test="$func/malval/@name = 'get'">
485 <xsl:variable name="name" select="$args/value/malval/lvalue/malval[2]"/>
487 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return (core:map-get($hash/lvalue/malval, $name), core:makeMALValue((), 'nil'))[1]"/>
490 <xsl:when test="$func/malval/@name = 'contains?'">
491 <xsl:variable name="name" select="$args/value/malval/lvalue/malval[2]"/>
492 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return core:makeMALType((), if (empty(core:map-get($hash/lvalue/malval, $name))) then 'false' else 'true')"/>
494 <xsl:when test="$func/malval/@name = 'keys'">
495 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return ($hash/lvalue/malval[position() mod 2 = 1]) => core:makeMALList('list')"/>
497 <xsl:when test="$func/malval/@name = 'vals'">
498 <xsl:sequence select="let $hash := $args/value/malval/lvalue/malval[1] return ($hash/lvalue/malval[position() mod 2 = 0]) => core:makeMALList('list')"/>
500 <xsl:when test="$func/malval/@name = 'meta'">
502 <xsl:sequence select="($args/value/malval/lvalue/malval[1]/meta/malval, core:makeMALValue((), 'nil'))[1]"/>
505 <xsl:when test="$func/malval/@name = 'with-meta'">
508 <xsl:sequence select="$args/value/malval/lvalue/malval[1]/(*[name() != 'meta']|@*)"/>
510 <xsl:sequence select="$args/value/malval/lvalue/malval[2]"/>
515 <xsl:when test="$func/malval/@name = 'time-ms'">
516 <!-- current-dateTime() does not change while transforming :( -->
517 <xsl:sequence select="core:makeMALType(core:mstime(), 'number')"/>
519 <xsl:when test="$func/malval/@name = 'conj'">
520 <xsl:variable name="xargs" select="$args/value/malval/lvalue/malval[position() > 1]"/>
521 <xsl:variable name="coll">
522 <xsl:sequence select="$args/value/malval/lvalue/malval[1]"/>
526 <xsl:when test="$coll/malval/@kind = 'list'">
529 <xsl:sequence select="reverse($xargs)"/>
530 <xsl:sequence select="$coll/malval/lvalue/malval"/>
535 <malval kind="vector">
537 <xsl:sequence select="$coll/malval/lvalue/malval"/>
538 <xsl:sequence select="$xargs"/>
545 <xsl:when test="$func/malval/@name = 'string?'">
546 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'string') then 'true' else 'false')"/>
548 <xsl:when test="$func/malval/@name = 'number?'">
549 <xsl:sequence select="core:makeMALType((), if ($args/value/malval/lvalue/malval[1]/@kind = 'number') then 'true' else 'false')"/>
551 <xsl:when test="$func/malval/@name = 'fn?'">
552 <xsl:sequence select="core:makeMALType((), if (let $f := $args/value/malval/lvalue/malval[1] return ($f/@kind = 'userfunction' or $f/@kind = 'function') and $f/is_macro/text() != 'true') then 'true' else 'false')"/>
554 <xsl:when test="$func/malval/@name = 'macro?'">
555 <xsl:sequence select="core:makeMALType((), if (let $f := $args/value/malval/lvalue/malval[1] return ($f/@kind = 'userfunction' or $f/@kind = 'function') and $f/is_macro/text() = 'true') then 'true' else 'false')"/>
557 <xsl:when test="$func/malval/@name = 'seq'">
558 <xsl:variable name="arg" select="$args/value/malval/lvalue/malval[1]"/>
560 <xsl:when test="$arg/@kind = 'string'">
562 <xsl:when test="string-length($arg/@value) = 0">
563 <xsl:sequence select="core:makeMALType((), 'nil')"/>
569 <xsl:for-each select="string-to-codepoints($arg/@value)">
570 <xsl:sequence select="core:makeMALValue(codepoints-to-string(.), 'string')"/>
580 <xsl:when test="count($arg/lvalue/malval) = 0">
581 <xsl:sequence select="core:makeMALType((), 'nil')"/>
586 <xsl:sequence select="$arg/lvalue"/>
594 <xsl:when test="$func/malval/@name = 'xpath-eval'">
596 <request kind="xpath-eval" value="{$args/value/malval/lvalue/malval[1]/@value}" context="{$args/value/malval/lvalue/malval[2] => serialize()}"/>
599 <xsl:sequence select="document('xsl_input-string')"/>
603 <xsl:value-of select="error(QName('MAL', 'Error'), concat('Invalid function ', $func/malval/@name), core:makeMALValue(concat('Invalid function ', $func/malval/@name), 'string'))"/>
610 <xsl:function name="core:makeMALList">
611 <xsl:param name="values"/>
612 <xsl:param name="kind"/>
614 <malval kind="{$kind}">
616 <xsl:sequence select="$values"/>
621 <xsl:function name="core:makeMALType">
622 <xsl:param name="value"/>
623 <xsl:param name="kind"/>
625 <malval kind="{$kind}" value="{$value}"/>
628 <xsl:function name="core:makeMALValue">
629 <xsl:param name="value"/>
630 <xsl:param name="kind"/>
631 <malval kind="{$kind}" value="{$value}"/>
633 <xsl:function name="core:pr-str">
634 <xsl:param name="value"/>
635 <xsl:variable name="ctx">
637 <xsl:sequence select="$value"/>
640 <xsl:variable name="res">
641 <xsl:for-each select="$ctx">
642 <xsl:call-template name="malprinter-pr_str">
643 <xsl:with-param name="readably" select="true()"/>
647 <xsl:sequence select="$res"/>
649 <xsl:function name="core:all-equal">
650 <xsl:param name="seq"/>
651 <xsl:param name="left"/>
652 <xsl:param name="right"/>
654 <xsl:when test="empty($seq)">
655 <xsl:sequence select="true()"/>
659 <xsl:when test="core:list-equal($left, $right, head($seq))">
660 <xsl:sequence select="core:all-equal(tail($seq), $right, $left)"/>
663 <xsl:sequence select="false()"/>
669 <xsl:function name="core:any-equal">
670 <xsl:param name="comps"/>
671 <xsl:param name="value"/>
673 <xsl:when test="empty($comps)">
674 <xsl:sequence select="false()"/>
676 <xsl:when test="core:equal($value, head($comps))">
677 <xsl:sequence select="true()"/>
680 <xsl:sequence select="core:any-equal(tail($comps), $value)"/>
684 <xsl:function name="core:map-values-equal">
685 <xsl:param name="ma"/>
686 <xsl:param name="mb"/>
688 <xsl:when test="empty($ma)">
689 <xsl:sequence select="true()"/>
692 <xsl:sequence select="core:equal($ma[2], core:map-get($mb, $ma[1])) and core:map-values-equal($ma[position() gt 2], $mb)"/>
696 <xsl:function name="core:equal">
697 <xsl:param name="left"/>
698 <xsl:param name="right"/>
701 <xsl:when test="$left/@kind = $right/@kind">
703 <xsl:when test="$left/@kind = 'hash' and $right/@kind = 'hash'">
704 <!-- counts are equal, check if all keys share the same value -->
705 <xsl:sequence select="core:map-values-equal($left/lvalue/malval, $right/lvalue/malval)"/>
708 <xsl:when test="$left/@kind = 'list' or $left/@kind = 'vector' or $left/@kind = 'hash'">
711 <xsl:when test="count($left/lvalue/malval) = count($right/lvalue/malval)">
712 <xsl:sequence select="core:all-equal(1 to count($left/lvalue/malval), $left, $right)"/>
714 <!-- different counts -->
716 <xsl:sequence select="false()"/>
720 <!-- simple 'value' type -->
722 <xsl:sequence select="string($left/@value) = string($right/@value)"/>
726 <!-- different types -->
729 <xsl:when test="($left/@kind = 'list' and $right/@kind = 'vector') or ($left/@kind = 'vector' and $right/@kind = 'list')">
732 <xsl:when test="count($left/lvalue/malval) = count($right/lvalue/malval)">
733 <xsl:sequence select="core:all-equal(1 to count($left/lvalue/malval), $left, $right)"/>
735 <!-- different counts -->
737 <xsl:sequence select="false()"/>
742 <xsl:sequence select="false()"/>
748 <xsl:function name="core:list-equal">
749 <xsl:param name="l"/>
750 <xsl:param name="r"/>
751 <xsl:param name="v"/>
752 <xsl:sequence select="core:equal($l/lvalue/malval[$v], $r/lvalue/malval[$v])"/>
754 <xsl:function name="core:map-assoc">
755 <xsl:param name="map"/>
756 <xsl:param name="names"/>
757 <xsl:param name="values"/>
758 <xsl:sequence select="$map"/>
759 <xsl:for-each select="1 to count($names)">
760 <xsl:variable name="idx" select="position()"/>
761 <xsl:sequence select="$names[position() = $idx]"/>
762 <xsl:sequence select="$values[position() = $idx]"/>
765 <xsl:function name="core:map-dissoc">
766 <xsl:param name="map"/>
767 <xsl:param name="names"/>
768 <xsl:sequence select="$map[let $pos := position() return not(($pos mod 2 = 1 and core:any-equal($names, .)) or ($pos mod 2 = 0 and core:any-equal($names, ../malval[$pos - 1])))]"/>
770 <xsl:function name="core:map-get">
771 <xsl:param name="map"/>
772 <xsl:param name="name"/>
773 <xsl:sequence select="$map[let $pos := position() return $pos mod 2 = 0 and core:equal($name, ../malval[$pos - 1])]"/>
775 <xsl:function name="core:mstime">
777 <request kind="time" value="now"/>
779 <xsl:sequence select="unparsed-text('xsl_input-string')"/>