zuzu-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +113 -0
  3. package/bin/zuzu +17 -0
  4. package/bin/zuzu-build-browser-bundle +57 -0
  5. package/bin/zuzu-generate-browser-stdlib +584 -0
  6. package/bin/zuzu-js +23 -0
  7. package/bin/zuzu-js-compile +152 -0
  8. package/bin/zuzu-js-electron +19 -0
  9. package/dist/zuzu-browser-worker.js +45574 -0
  10. package/dist/zuzu-browser.js +45362 -0
  11. package/lib/browser-bundle-entry.js +160 -0
  12. package/lib/browser-gui-renderer.js +387 -0
  13. package/lib/browser-runtime.js +167 -0
  14. package/lib/browser-worker-entry.js +413 -0
  15. package/lib/browser-ztests/runner.html +103 -0
  16. package/lib/browser-ztests/runner.js +369 -0
  17. package/lib/cli.js +350 -0
  18. package/lib/collections.js +367 -0
  19. package/lib/compiler.js +303 -0
  20. package/lib/electron/launcher.js +70 -0
  21. package/lib/electron/main.js +956 -0
  22. package/lib/electron/preload.js +80 -0
  23. package/lib/electron/renderer.html +122 -0
  24. package/lib/electron/renderer.js +24 -0
  25. package/lib/execution-metadata.js +18 -0
  26. package/lib/gui/dom-renderer.js +778 -0
  27. package/lib/host/browser-host.js +278 -0
  28. package/lib/host/capabilities.js +47 -0
  29. package/lib/host/electron-host.js +15 -0
  30. package/lib/host/node-host.js +74 -0
  31. package/lib/paths.js +150 -0
  32. package/lib/runtime-entrypoints.js +60 -0
  33. package/lib/runtime-helpers.js +886 -0
  34. package/lib/runtime.js +3529 -0
  35. package/lib/tap.js +37 -0
  36. package/lib/transpiler-new/ast.js +23 -0
  37. package/lib/transpiler-new/codegen.js +2455 -0
  38. package/lib/transpiler-new/errors.js +28 -0
  39. package/lib/transpiler-new/index.js +26 -0
  40. package/lib/transpiler-new/lexer.js +834 -0
  41. package/lib/transpiler-new/parser.js +2332 -0
  42. package/lib/transpiler-new/validate-bindings.js +326 -0
  43. package/lib/transpiler-utils.js +95 -0
  44. package/lib/transpiler.js +33 -0
  45. package/lib/zuzu.js +53 -0
  46. package/modules/javascript.js +193 -0
  47. package/modules/std/archive.js +603 -0
  48. package/modules/std/clib.js +338 -0
  49. package/modules/std/data/csv.js +1331 -0
  50. package/modules/std/data/json.js +531 -0
  51. package/modules/std/data/xml.js +441 -0
  52. package/modules/std/data/yaml.js +256 -0
  53. package/modules/std/db-worker.js +250 -0
  54. package/modules/std/db.js +664 -0
  55. package/modules/std/digest/_hash.js +443 -0
  56. package/modules/std/digest/md5.js +26 -0
  57. package/modules/std/digest/sha.js +72 -0
  58. package/modules/std/eval.js +10 -0
  59. package/modules/std/gui/objects.js +1519 -0
  60. package/modules/std/internals.js +571 -0
  61. package/modules/std/io/socks-worker.js +318 -0
  62. package/modules/std/io/socks.js +186 -0
  63. package/modules/std/io.js +475 -0
  64. package/modules/std/marshal/cbor.js +463 -0
  65. package/modules/std/marshal/graph.js +1624 -0
  66. package/modules/std/marshal.js +87 -0
  67. package/modules/std/math/bignum.js +91 -0
  68. package/modules/std/math.js +79 -0
  69. package/modules/std/net/dns.js +306 -0
  70. package/modules/std/net/http.js +820 -0
  71. package/modules/std/net/smtp.js +943 -0
  72. package/modules/std/net/url.js +109 -0
  73. package/modules/std/proc.js +602 -0
  74. package/modules/std/secure.js +3724 -0
  75. package/modules/std/string/base64.js +138 -0
  76. package/modules/std/string.js +299 -0
  77. package/modules/std/task.js +914 -0
  78. package/modules/std/time.js +579 -0
  79. package/modules/std/tui.js +188 -0
  80. package/modules/std/worker-thread.js +246 -0
  81. package/modules/std/worker.js +790 -0
  82. package/package.json +67 -0
  83. package/stdlib/modules/javascript.zzm +99 -0
  84. package/stdlib/modules/perl.zzm +105 -0
  85. package/stdlib/modules/std/archive.zzm +132 -0
  86. package/stdlib/modules/std/cache/lru.zzm +174 -0
  87. package/stdlib/modules/std/clib.zzm +112 -0
  88. package/stdlib/modules/std/colour.zzm +220 -0
  89. package/stdlib/modules/std/config.zzm +818 -0
  90. package/stdlib/modules/std/data/cbor.zzm +497 -0
  91. package/stdlib/modules/std/data/csv.zzm +285 -0
  92. package/stdlib/modules/std/data/ini.zzm +472 -0
  93. package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
  94. package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
  95. package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
  96. package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
  97. package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
  98. package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
  99. package/stdlib/modules/std/data/json/schema.zzm +306 -0
  100. package/stdlib/modules/std/data/json.zzm +102 -0
  101. package/stdlib/modules/std/data/kdl/json.zzm +460 -0
  102. package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
  103. package/stdlib/modules/std/data/kdl.zzm +1631 -0
  104. package/stdlib/modules/std/data/toml.zzm +756 -0
  105. package/stdlib/modules/std/data/toon.zzm +1017 -0
  106. package/stdlib/modules/std/data/xml/escape.zzm +156 -0
  107. package/stdlib/modules/std/data/xml.zzm +276 -0
  108. package/stdlib/modules/std/data/yaml.zzm +94 -0
  109. package/stdlib/modules/std/db.zzm +173 -0
  110. package/stdlib/modules/std/defer.zzm +75 -0
  111. package/stdlib/modules/std/digest/crc32.zzm +196 -0
  112. package/stdlib/modules/std/digest/md5.zzm +54 -0
  113. package/stdlib/modules/std/digest/sha.zzm +83 -0
  114. package/stdlib/modules/std/dump.zzm +317 -0
  115. package/stdlib/modules/std/eval.zzm +63 -0
  116. package/stdlib/modules/std/getopt.zzm +432 -0
  117. package/stdlib/modules/std/gui/dialogue.zzm +592 -0
  118. package/stdlib/modules/std/gui/objects.zzm +123 -0
  119. package/stdlib/modules/std/gui.zzm +1914 -0
  120. package/stdlib/modules/std/internals.zzm +139 -0
  121. package/stdlib/modules/std/io/socks.zzm +139 -0
  122. package/stdlib/modules/std/io.zzm +157 -0
  123. package/stdlib/modules/std/lingua/en.zzm +347 -0
  124. package/stdlib/modules/std/log.zzm +169 -0
  125. package/stdlib/modules/std/mail.zzm +2726 -0
  126. package/stdlib/modules/std/marshal.zzm +138 -0
  127. package/stdlib/modules/std/math/bignum.zzm +98 -0
  128. package/stdlib/modules/std/math/range.zzm +116 -0
  129. package/stdlib/modules/std/math/roman.zzm +156 -0
  130. package/stdlib/modules/std/math.zzm +141 -0
  131. package/stdlib/modules/std/net/dns.zzm +93 -0
  132. package/stdlib/modules/std/net/http.zzm +278 -0
  133. package/stdlib/modules/std/net/smtp.zzm +257 -0
  134. package/stdlib/modules/std/net/url.zzm +69 -0
  135. package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
  136. package/stdlib/modules/std/path/kdl.zzm +1003 -0
  137. package/stdlib/modules/std/path/simple.zzm +520 -0
  138. package/stdlib/modules/std/path/z/context.zzm +147 -0
  139. package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
  140. package/stdlib/modules/std/path/z/functions.zzm +874 -0
  141. package/stdlib/modules/std/path/z/lexer.zzm +490 -0
  142. package/stdlib/modules/std/path/z/node.zzm +1455 -0
  143. package/stdlib/modules/std/path/z/operators.zzm +445 -0
  144. package/stdlib/modules/std/path/z/parser.zzm +359 -0
  145. package/stdlib/modules/std/path/z.zzm +403 -0
  146. package/stdlib/modules/std/path/zz/functions.zzm +828 -0
  147. package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
  148. package/stdlib/modules/std/path/zz.zzm +100 -0
  149. package/stdlib/modules/std/proc.zzm +155 -0
  150. package/stdlib/modules/std/result.zzm +149 -0
  151. package/stdlib/modules/std/secure.zzm +606 -0
  152. package/stdlib/modules/std/string/base64.zzm +66 -0
  153. package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
  154. package/stdlib/modules/std/string.zzm +179 -0
  155. package/stdlib/modules/std/task.zzm +221 -0
  156. package/stdlib/modules/std/template/z.zzm +531 -0
  157. package/stdlib/modules/std/template/zz.zzm +62 -0
  158. package/stdlib/modules/std/time.zzm +188 -0
  159. package/stdlib/modules/std/tui.zzm +89 -0
  160. package/stdlib/modules/std/uuid.zzm +223 -0
  161. package/stdlib/modules/std/web/session.zzm +388 -0
  162. package/stdlib/modules/std/web/static.zzm +329 -0
  163. package/stdlib/modules/std/web.zzm +1942 -0
  164. package/stdlib/modules/std/worker.zzm +202 -0
  165. package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
  166. package/stdlib/modules/test/more.zzm +528 -0
  167. package/stdlib/modules/test/parser.zzm +209 -0
@@ -0,0 +1,874 @@
1
+ =encoding utf8
2
+
3
+ =head1 NAME
4
+
5
+ std/path/z/functions - Function definitions for ZPath.
6
+
7
+ =head1 IMPLEMENTATION SUPPORT
8
+
9
+ This module is supported by all implementations of ZuzuScript.
10
+
11
+ =head1 DESCRIPTION
12
+
13
+ This module defines the function objects and standard function table used
14
+ by C<std/path/z>.
15
+
16
+ =head1 EXPORTS
17
+
18
+ =head2 Classes
19
+
20
+ =over
21
+
22
+ =item C<< Func({ spelling: String, f: Function }) >>
23
+
24
+ Constructs a ZPath function definition. Returns: C<Func>.
25
+
26
+ =over
27
+
28
+ =item C<< func.has_name(n) >>
29
+
30
+ Parameters: C<n> is a function name. Returns: C<Boolean>. Returns true
31
+ when C<n> matches the function spelling.
32
+
33
+ =back
34
+
35
+ =back
36
+
37
+ =head2 Functions
38
+
39
+ =over
40
+
41
+ =item C<< replace(haystack, needle, replacement) >>
42
+
43
+ Parameters: C<haystack> is source text, C<needle> is a pattern, and
44
+ C<replacement> is replacement text. Returns: C<String>. Performs ZPath
45
+ replacement with capture substitutions.
46
+
47
+ =item C<< mk_single_number_function(String name, Function impl) >>
48
+
49
+ Parameters: C<name> is a ZPath function name and C<impl> maps one
50
+ number. Returns: C<Function>. Builds a function wrapper for per-node
51
+ numeric functions.
52
+
53
+ =item C<< mk_aggregate_number_function(String name, Function impl) >>
54
+
55
+ Parameters: C<name> is a ZPath function name and C<impl> maps an array
56
+ of numbers. Returns: C<Function>. Builds a function wrapper for
57
+ aggregate numeric functions.
58
+
59
+ =item C<< mk_single_string_function(String name, Function impl) >>
60
+
61
+ Parameters: C<name> is a ZPath function name and C<impl> maps one
62
+ string. Returns: C<Function>. Builds a function wrapper for per-node
63
+ string functions.
64
+
65
+ =item C<< mk_match_function() >>
66
+
67
+ Parameters: none. Returns: C<Function>. Builds the standard ZPath
68
+ C<match> function implementation.
69
+
70
+ =back
71
+
72
+ =head2 Constants
73
+
74
+ =over
75
+
76
+ =item C<STANDARD_FUNCTIONS>
77
+
78
+ Type: C<Array>. Standard ZPath function definitions.
79
+
80
+ =back
81
+
82
+ =head1 COPYRIGHT AND LICENCE
83
+
84
+ B<< std/path/z/functions >> is copyright Toby Inkster.
85
+
86
+ It is free software; you may redistribute it and/or modify it under
87
+ the terms of either the Artistic License 1.0 or the GNU General Public
88
+ License version 2.
89
+
90
+ =cut
91
+
92
+ from std/path/z/node import KDLNodeNode, KDLValueNode, Node, XmlNodeNode;
93
+ from std/path/z/operators import EvalHelpers;
94
+ from std/data/xml/escape import escape_xml, unescape_xml;
95
+ from std/string import index, rindex, search, sprint, substr, join;
96
+ from std/math import Math;
97
+
98
+
99
+ class Func with EvalHelpers {
100
+ let String spelling with get;
101
+ let Function f;
102
+
103
+ method has_name ( n ) {
104
+ return true if self.get_spelling eq n;
105
+ return false;
106
+ }
107
+ }
108
+
109
+ function replace ( haystack, needle, replacement ) {
110
+ let copy := haystack;
111
+
112
+ if ( replacement ~ /\$[0-9]/ ) {
113
+ let r := replacement;
114
+ copy ~= needle → do {
115
+ let matches := m;
116
+ r ~= /\$([0-9]+)/g → matches[ m[1] ];
117
+ r;
118
+ };
119
+ }
120
+ else {
121
+ copy ~= needle → replacement;
122
+ }
123
+
124
+ return copy;
125
+ }
126
+
127
+ function mk_single_number_function ( String name, Function impl ) {
128
+ return function ( funk, ev, ast, ctx, args ) {
129
+ let nodes := [];
130
+ for ( let a in args ) {
131
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
132
+ for ( let n in got ) {
133
+ nodes.push( n );
134
+ }
135
+ }
136
+ else {
137
+ nodes := ctx.nodeset;
138
+ }
139
+ return nodes
140
+ .map( fn x → x.number_value )
141
+ .grep( fn x → x instanceof Number )
142
+ .map( fn x → funk.wrap_for_array( impl(x) ) );
143
+ };
144
+ }
145
+
146
+ function mk_aggregate_number_function ( String name, Function impl ) {
147
+ return function ( funk, ev, ast, ctx, args ) {
148
+ let nodes := [];
149
+ for ( let a in args ) {
150
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
151
+ for ( let n in got ) {
152
+ nodes.push( n );
153
+ }
154
+ }
155
+ else {
156
+ nodes := ctx.nodeset;
157
+ }
158
+ const nums := nodes
159
+ .map( fn x → x.number_value )
160
+ .grep( fn x → x instanceof Number );
161
+ return funk.wrap( impl( nums ) );
162
+ };
163
+ }
164
+
165
+ function mk_single_string_function ( String name, Function impl ) {
166
+ return function ( funk, ev, ast, ctx, args ) {
167
+ let nodes := [];
168
+ for ( let a in args ) {
169
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
170
+ for ( let n in got ) {
171
+ nodes.push( n );
172
+ }
173
+ }
174
+ else {
175
+ nodes := ctx.nodeset;
176
+ }
177
+ return nodes
178
+ .map( fn x → x.string_value )
179
+ .grep( fn x → x instanceof String )
180
+ .map( fn x → funk.wrap_for_array( impl(x) ) );
181
+ };
182
+ }
183
+
184
+ function mk_match_function () {
185
+ return function ( funk, ev, ast, ctx, args ) {
186
+ let nodes := [];
187
+ let re;
188
+
189
+ if ( args.empty ) {
190
+ die "Not enough arguments for match()";
191
+ }
192
+ else {
193
+ re := try {
194
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
195
+ } catch {
196
+ "";
197
+ };
198
+ }
199
+
200
+ for ( let a in args[1:] ) {
201
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
202
+ for ( let n in got ) {
203
+ nodes.push( n );
204
+ }
205
+ }
206
+ else {
207
+ nodes := ctx.nodeset;
208
+ }
209
+
210
+ return nodes
211
+ .map( fn x → x.string_value )
212
+ .grep( fn x → x instanceof String )
213
+ .map( fn x → funk.wrap_for_array( ( x ~ re ) ? true : false ) );
214
+ }
215
+ }
216
+
217
+ const STANDARD_FUNCTIONS := [
218
+ new Func(
219
+ spelling: "true",
220
+ f: function ( funk, ev, ast, ctx, args ) {
221
+ die "Too many arguments for true()" unless args.empty;
222
+ return funk.wrap( true );
223
+ },
224
+ ),
225
+
226
+ new Func(
227
+ spelling: "false",
228
+ f: function ( funk, ev, ast, ctx, args ) {
229
+ die "Too many arguments for false()" unless args.empty;
230
+ return funk.wrap( false );
231
+ },
232
+ ),
233
+
234
+ new Func(
235
+ spelling: "null",
236
+ f: function ( funk, ev, ast, ctx, args ) {
237
+ die "Too many arguments for null()" unless args.empty;
238
+ return funk.wrap( null );
239
+ },
240
+ ),
241
+
242
+ new Func(
243
+ spelling: "die",
244
+ f: function ( funk, ev, ast, ctx, args ) {
245
+ die "Called 'die' function in zpath";
246
+ },
247
+ ),
248
+
249
+ new Func(
250
+ spelling: "count",
251
+ f: function ( funk, ev, ast, ctx, args ) {
252
+ let n := 0;
253
+ for ( let a in args ) {
254
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
255
+ n += got.length;
256
+ }
257
+ else {
258
+ const cur := ctx.parentset ?: ctx.nodeset;
259
+ n := cur.length;
260
+ }
261
+ return funk.wrap( n );
262
+ },
263
+ ),
264
+
265
+ new Func(
266
+ spelling: "index",
267
+ f: function ( funk, ev, ast, ctx, args ) {
268
+ if ( args.length = 0 ) {
269
+ const cur := ctx.nodeset.get( 0, null );
270
+ return funk.wrap( cur ? cur.ix : null );
271
+ }
272
+ else if ( args.length = 1 ) {
273
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
274
+ return got.map( fn x → funk.wrap_for_array(x.ix) );
275
+ }
276
+ die "Too many arguments for index()";
277
+ },
278
+ ),
279
+
280
+ new Func(
281
+ spelling: "key",
282
+ f: function ( funk, ev, ast, ctx, args ) {
283
+ if ( args.length = 0 ) {
284
+ const cur := ctx.nodeset.get( 0, null );
285
+ return funk.wrap( cur ? cur.key : null );
286
+ }
287
+ else if ( args.length = 1 ) {
288
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
289
+ return got.map(
290
+ fn x → funk.wrap_for_array(
291
+ x ≡ null ? null : x.key
292
+ )
293
+ );
294
+ }
295
+ die "Too many arguments for key()";
296
+ },
297
+ ),
298
+
299
+ new Func(
300
+ spelling: "type",
301
+ f: function ( funk, ev, ast, ctx, args ) {
302
+ if ( args.length = 0 ) {
303
+ const cur := ctx.nodeset.get( 0, null );
304
+ return funk.wrap( cur ? cur.type : "undefined" );
305
+ }
306
+ else if ( args.length = 1 ) {
307
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) ).get( 0, null );
308
+ return funk.wrap( got ? got.type : "undefined" );
309
+ }
310
+ die "Too many arguments for type()";
311
+ },
312
+ ),
313
+
314
+ new Func(
315
+ spelling: "union",
316
+ f: function ( funk, ev, ast, ctx, args ) {
317
+ let out := [];
318
+ for ( let arg in args ) {
319
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
320
+ for ( let n in got ) {
321
+ out.push( n );
322
+ }
323
+ }
324
+ return ev.dedup_nodes( out );
325
+ },
326
+ ),
327
+
328
+ new Func(
329
+ spelling: "intersection",
330
+ f: function ( funk, ev, ast, ctx, args ) {
331
+ return [] if args.empty;
332
+
333
+ let out := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
334
+ out := ev.dedup_nodes( out );
335
+
336
+ let i := 1;
337
+ while ( i < args.length() ) {
338
+ let got := ev.eval_expr( args[i], ev.nested_ctx( ctx ) );
339
+ got := ev.dedup_nodes( got );
340
+
341
+ let seen := {};
342
+ for ( let n in got ) {
343
+ let key := n.id();
344
+ if ( key ≡ null ) {
345
+ key := "anon:" _ ( "" _ n.raw() );
346
+ }
347
+ seen.set( key, true );
348
+ }
349
+
350
+ let next_out := [];
351
+ for ( let n in out ) {
352
+ let key := n.id();
353
+ if ( key ≡ null ) {
354
+ key := "anon:" _ ( "" _ n.raw() );
355
+ }
356
+ if ( seen.exists(key) ) {
357
+ next_out.push(n);
358
+ }
359
+ }
360
+
361
+ out := next_out;
362
+ last if out.empty;
363
+ i++;
364
+ }
365
+
366
+ return ev.dedup_nodes( out );
367
+ },
368
+ ),
369
+
370
+ new Func(
371
+ spelling: "is-first",
372
+ f: function ( funk, ev, ast, ctx, args ) {
373
+ if ( args.length = 0 ) {
374
+ const cur := ctx.nodeset.get( 0, null );
375
+ return [] unless cur and cur.parent;
376
+ return funk.wrap( cur.ix = 0 );
377
+ }
378
+ die "Too many arguments for is-first()";
379
+ },
380
+ ),
381
+
382
+ new Func(
383
+ spelling: "is-last",
384
+ f: function ( funk, ev, ast, ctx, args ) {
385
+ if ( args.length = 0 ) {
386
+ const cur := ctx.nodeset.get( 0, null );
387
+ return [] unless cur and cur.parent and cur.ix ≢ null;
388
+ const siblings := cur.parent.children
389
+ .grep( fn kid → kid.key ≡ cur.key );
390
+ return [] if siblings.empty;
391
+ let pos := 0;
392
+ while ( pos < siblings.length ) {
393
+ const kid := siblings[pos];
394
+ last if kid.id() ≡ cur.id();
395
+ pos++;
396
+ }
397
+ return [] if pos ≥ siblings.length;
398
+ return funk.wrap( pos = siblings.length - 1 );
399
+ }
400
+ die "Too many arguments for is-last()";
401
+ },
402
+ ),
403
+
404
+ new Func(
405
+ spelling: "next",
406
+ f: function ( funk, ev, ast, ctx, args ) {
407
+ if ( args.length = 0 ) {
408
+ const cur := ctx.nodeset.get( 0, null );
409
+ return [ cur.next_sibling ];
410
+ }
411
+ else {
412
+ let out := [];
413
+ for ( let arg in args ) {
414
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
415
+ for ( let n in got ) {
416
+ out.push( n.next_sibling );
417
+ }
418
+ }
419
+ return out;
420
+ }
421
+ },
422
+ ),
423
+
424
+ new Func(
425
+ spelling: "prev",
426
+ f: function ( funk, ev, ast, ctx, args ) {
427
+ if ( args.length = 0 ) {
428
+ const cur := ctx.nodeset.get( 0, null );
429
+ return [ cur.prev_sibling ];
430
+ }
431
+ else {
432
+ let out := [];
433
+ for ( let arg in args ) {
434
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
435
+ for ( let n in got ) {
436
+ out.push( n.prev_sibling );
437
+ }
438
+ }
439
+ return out;
440
+ }
441
+ },
442
+ ),
443
+
444
+ new Func(
445
+ spelling: "string",
446
+ f: function ( funk, ev, ast, ctx, args ) {
447
+ if ( args.length = 0 ) {
448
+ const cur := ctx.nodeset.get( 0, null );
449
+ return [] unless cur;
450
+ return funk.wrap( cur.string_value );
451
+ }
452
+ else {
453
+ let out := [];
454
+ for ( let arg in args ) {
455
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
456
+ for ( let n in got ) {
457
+ out.push( n );
458
+ }
459
+ }
460
+ return out.map( fn x → funk.wrap_for_array( x.string_value ) );
461
+ }
462
+ },
463
+ ),
464
+
465
+ new Func(
466
+ spelling: "number",
467
+ f: function ( funk, ev, ast, ctx, args ) {
468
+ if ( args.length = 0 ) {
469
+ const cur := ctx.nodeset.get( 0, null );
470
+ return [] unless cur;
471
+ return funk.wrap( cur.number_value );
472
+ }
473
+ else {
474
+ let out := [];
475
+ for ( let arg in args ) {
476
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
477
+ for ( let n in got ) {
478
+ out.push( n );
479
+ }
480
+ }
481
+ return out.map( fn x → funk.wrap_for_array( x.number_value ) );
482
+ }
483
+ },
484
+ ),
485
+
486
+ new Func(
487
+ spelling: "value",
488
+ f: function ( funk, ev, ast, ctx, args ) {
489
+ if ( args.length = 0 ) {
490
+ const cur := ctx.nodeset.get( 0, null );
491
+ return [] unless cur;
492
+ return funk.wrap( cur.primitive_value );
493
+ }
494
+ else {
495
+ let out := [];
496
+ for ( let arg in args ) {
497
+ const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );
498
+ for ( let n in got ) {
499
+ out.push( n );
500
+ }
501
+ }
502
+ return out.map( fn x → funk.wrap_for_array( x.primitive_value ) );
503
+ }
504
+ },
505
+ ),
506
+
507
+ new Func(
508
+ spelling: "ceil",
509
+ f: mk_single_number_function( "ceil", fn n → ceil n ),
510
+ ),
511
+
512
+ new Func(
513
+ spelling: "floor",
514
+ f: mk_single_number_function( "floor", fn n → floor n ),
515
+ ),
516
+
517
+ new Func(
518
+ spelling: "round",
519
+ f: mk_single_number_function( "round", fn n → round n ),
520
+ ),
521
+
522
+ new Func(
523
+ spelling: "sum",
524
+ f: mk_aggregate_number_function( "sum", fn nums → Math.sum(nums) ),
525
+ ),
526
+
527
+ new Func(
528
+ spelling: "min",
529
+ f: mk_aggregate_number_function( "min", fn nums → Math.min(nums) ),
530
+ ),
531
+
532
+ new Func(
533
+ spelling: "max",
534
+ f: mk_aggregate_number_function( "max", fn nums → Math.max(nums) ),
535
+ ),
536
+
537
+ new Func(
538
+ spelling: "escape",
539
+ f: mk_single_string_function( "escape", fn s → escape_xml(s) ),
540
+ ),
541
+
542
+ new Func(
543
+ spelling: "unescape",
544
+ f: mk_single_string_function( "unescape", fn s → unescape_xml(s) ),
545
+ ),
546
+
547
+ new Func(
548
+ spelling: "upper-case",
549
+ f: mk_single_string_function( "upper-case", fn s → uc s ),
550
+ ),
551
+
552
+ new Func(
553
+ spelling: "lower-case",
554
+ f: mk_single_string_function( "lower-case", fn s → lc s ),
555
+ ),
556
+
557
+ new Func(
558
+ spelling: "index-of",
559
+ f: function ( funk, ev, ast, ctx, args ) {
560
+ let nodes := [];
561
+ let search;
562
+
563
+ if ( args.empty ) {
564
+ die "Not enough arguments for index-of()";
565
+ }
566
+ else {
567
+ search := try {
568
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
569
+ } catch {
570
+ "";
571
+ };
572
+ }
573
+
574
+ for ( let a in args[1:] ) {
575
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
576
+ for ( let n in got ) {
577
+ nodes.push( n );
578
+ }
579
+ }
580
+ else {
581
+ nodes := ctx.nodeset;
582
+ }
583
+
584
+ return nodes
585
+ .map( fn x → x.string_value )
586
+ .grep( fn x → x instanceof String )
587
+ .map( fn x → funk.wrap_for_array( index(x, search) ) );
588
+ }
589
+ ),
590
+
591
+ new Func(
592
+ spelling: "last-index-of",
593
+ f: function ( funk, ev, ast, ctx, args ) {
594
+ let nodes := [];
595
+ let search;
596
+
597
+ if ( args.empty ) {
598
+ die "Not enough arguments for last-index-of()";
599
+ }
600
+ else {
601
+ search := try {
602
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
603
+ } catch {
604
+ "";
605
+ };
606
+ }
607
+
608
+ for ( let a in args[1:] ) {
609
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
610
+ for ( let n in got ) {
611
+ nodes.push( n );
612
+ }
613
+ }
614
+ else {
615
+ nodes := ctx.nodeset;
616
+ }
617
+
618
+ return nodes
619
+ .map( fn x → x.string_value )
620
+ .grep( fn x → x instanceof String )
621
+ .map( fn x → funk.wrap_for_array( rindex(x, search) ) );
622
+ }
623
+ ),
624
+
625
+ new Func(
626
+ spelling: "substring",
627
+ f: function ( funk, ev, ast, ctx, args ) {
628
+
629
+ let nodes := [];
630
+ let start;
631
+ let len;
632
+
633
+ if ( args.length < 2 ) {
634
+ die "Not enough arguments for substring()";
635
+ }
636
+ else {
637
+ start := try {
638
+ ev.eval_expr( args[-2], ev.nested_ctx( ctx ) )[0].number_value;
639
+ } catch {
640
+ 0;
641
+ };
642
+ len := try {
643
+ ev.eval_expr( args[-1], ev.nested_ctx( ctx ) )[0].number_value;
644
+ } catch {
645
+ 0;
646
+ };
647
+ }
648
+
649
+ for ( let a in args[0:-2] ) {
650
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
651
+ for ( let n in got ) {
652
+ nodes.push( n );
653
+ }
654
+ }
655
+ else {
656
+ nodes := ctx.nodeset;
657
+ }
658
+
659
+ return nodes
660
+ .map( fn x → x.string_value )
661
+ .grep( fn x → x instanceof String )
662
+ .map( fn x → funk.wrap_for_array( substr(x, start, len) ) );
663
+ }
664
+ ),
665
+
666
+ new Func(
667
+ spelling: "format",
668
+ f: function ( funk, ev, ast, ctx, args ) {
669
+ let nodes := [];
670
+ let fmt;
671
+
672
+ if ( args.empty ) {
673
+ die "Not enough arguments for format()";
674
+ }
675
+ else {
676
+ fmt := try {
677
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
678
+ } catch {
679
+ "";
680
+ };
681
+ }
682
+
683
+ for ( let a in args[1:] ) {
684
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
685
+ for ( let n in got ) {
686
+ nodes.push( n );
687
+ }
688
+ }
689
+ else {
690
+ nodes := ctx.nodeset;
691
+ }
692
+
693
+ return nodes
694
+ .map( fn x → x.string_value )
695
+ .grep( fn x → x instanceof String )
696
+ .map( fn x → funk.wrap_for_array( sprint(fmt, x) ) );
697
+ }
698
+ ),
699
+
700
+ new Func(
701
+ spelling: "string-length",
702
+ f: mk_single_string_function( "string-length", fn s → length s ),
703
+ ),
704
+
705
+ new Func(
706
+ spelling: "match",
707
+ f: mk_match_function(),
708
+ ),
709
+
710
+ new Func(
711
+ spelling: "matches",
712
+ f: mk_match_function(),
713
+ ),
714
+
715
+ new Func(
716
+ spelling: "replace",
717
+ f: function ( funk, ev, ast, ctx, args ) {
718
+ let nodes := [];
719
+ let pattern;
720
+ let replacement;
721
+
722
+ if ( args.length < 2 ) {
723
+ die "Not enough arguments for replace()";
724
+ }
725
+ else {
726
+ pattern := try {
727
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
728
+ } catch {
729
+ "";
730
+ };
731
+ replacement := try {
732
+ ev.eval_expr( args[1], ev.nested_ctx( ctx ) )[0].string_value;
733
+ } catch {
734
+ "";
735
+ };
736
+ }
737
+
738
+ for ( let a in args[2:] ) {
739
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
740
+ for ( let n in got ) {
741
+ nodes.push( n );
742
+ }
743
+ }
744
+ else {
745
+ nodes := ctx.nodeset;
746
+ }
747
+
748
+ return nodes
749
+ .map( fn x → x.string_value )
750
+ .grep( fn x → x instanceof String )
751
+ .map( fn x → funk.wrap_for_array( replace( x, pattern, replacement ) ) );
752
+ }
753
+ ),
754
+
755
+ new Func(
756
+ spelling: "join",
757
+ f: function ( funk, ev, ast, ctx, args ) {
758
+ let nodes := [];
759
+ let joiner;
760
+
761
+ if ( args.empty ) {
762
+ die "Not enough arguments for format()";
763
+ }
764
+ else {
765
+ joiner := try {
766
+ ev.eval_expr( args[0], ev.nested_ctx( ctx ) )[0].string_value;
767
+ } catch {
768
+ "";
769
+ };
770
+ }
771
+
772
+ for ( let a in args[1:] ) {
773
+ const got := ev.eval_expr( a, ev.nested_ctx( ctx ) );
774
+ for ( let n in got ) {
775
+ nodes.push( n );
776
+ }
777
+ }
778
+ else {
779
+ nodes := ctx.nodeset;
780
+ }
781
+
782
+ const strings := nodes
783
+ .map( fn x → x.string_value )
784
+ .grep( fn x → x instanceof String );
785
+ return funk.wrap( join( joiner, strings ) );
786
+ }
787
+ ),
788
+
789
+ new Func(
790
+ spelling: "url",
791
+ f: function ( funk, ev, ast, ctx, args ) {
792
+ if ( args.length = 0 ) {
793
+ const cur := ctx.nodeset.get( 0, null );
794
+ return [] unless cur;
795
+ return funk.wrap( cur instanceof XmlNodeNode ? cur.raw.namespaceURI() : null );
796
+ }
797
+ else if ( args.length = 1 ) {
798
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
799
+ return got.map(
800
+ fn x → funk.wrap_for_array(
801
+ x instanceof XmlNodeNode ? x.raw.namespaceURI() : null
802
+ )
803
+ );
804
+ }
805
+ die "Too many arguments for url()";
806
+ },
807
+ ),
808
+
809
+ new Func(
810
+ spelling: "local-name",
811
+ f: function ( funk, ev, ast, ctx, args ) {
812
+ if ( args.length = 0 ) {
813
+ const cur := ctx.nodeset.get( 0, null );
814
+ return [] unless cur;
815
+ return funk.wrap(
816
+ cur instanceof XmlNodeNode ? cur.raw.localName()
817
+ : cur instanceof KDLNodeNode ? cur.name()
818
+ : null
819
+ );
820
+ }
821
+ else if ( args.length = 1 ) {
822
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
823
+ return got.map(
824
+ fn x → funk.wrap_for_array(
825
+ x instanceof XmlNodeNode ? x.raw.localName()
826
+ : x instanceof KDLNodeNode ? x.name()
827
+ : null
828
+ )
829
+ );
830
+ }
831
+ die "Too many arguments for local-name()";
832
+ },
833
+ ),
834
+
835
+ new Func(
836
+ spelling: "tag",
837
+ f: function ( funk, ev, ast, ctx, args ) {
838
+ if ( args.length = 0 ) {
839
+ const cur := ctx.nodeset.get( 0, null );
840
+ return [] unless cur;
841
+ if ( cur instanceof KDLNodeNode ) {
842
+ let ann := cur.raw().type_annotation();
843
+ return funk.wrap( ann ≡ null ? null : "" _ ann );
844
+ }
845
+ if ( cur instanceof KDLValueNode ) {
846
+ let ann := cur.raw().type_annotation();
847
+ return funk.wrap( ann ≡ null ? null : "" _ ann );
848
+ }
849
+ return funk.wrap( cur.has_tagged ? cur.tagged{tag} : null );
850
+ }
851
+ else if ( args.length = 1 ) {
852
+ const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );
853
+ return got.map(
854
+ fn x → funk.wrap_for_array(
855
+ x instanceof KDLNodeNode
856
+ ? (
857
+ x.raw().type_annotation() ≡ null
858
+ ? null
859
+ : "" _ x.raw().type_annotation()
860
+ )
861
+ : x instanceof KDLValueNode
862
+ ? (
863
+ x.raw().type_annotation() ≡ null
864
+ ? null
865
+ : "" _ x.raw().type_annotation()
866
+ )
867
+ : x can has_tagged ? x.tagged{tag} : null
868
+ )
869
+ );
870
+ }
871
+ die "Too many arguments for tag()";
872
+ },
873
+ ),
874
+ ];