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,520 @@
1
+ =encoding utf8
2
+
3
+ =head1 NAME
4
+
5
+ std/path/simple - Tiny JSONPath/XPath-like traversal helper.
6
+
7
+ =head1 SYNOPSIS
8
+
9
+ from std/path/simple import SimplePath;
10
+
11
+ let data := {
12
+ store: {
13
+ books: [
14
+ { author: "Nigel Rees" },
15
+ { author: "J. R. R. Tolkien" },
16
+ ],
17
+ },
18
+ };
19
+
20
+ let p := new SimplePath( path: "store.books[*].author" );
21
+ for ( let name in p.query(data) ) {
22
+ say name;
23
+ }
24
+
25
+ =head1 IMPLEMENTATION SUPPORT
26
+
27
+ This module is supported by all implementations of ZuzuScript.
28
+
29
+ =head1 DESCRIPTION
30
+
31
+ C<SimplePath> implements only a tiny subset of path traversal:
32
+
33
+ =over
34
+
35
+ =item * C<.something>
36
+
37
+ Dict/PairList lookup by key.
38
+
39
+ =item * C<.*>
40
+
41
+ Dict/PairList wildcard that yields all values.
42
+
43
+ =item * C<[1]>
44
+
45
+ Array lookup by numeric index.
46
+
47
+ =item * C<[-1]>
48
+
49
+ Negative indexes count from the end of arrays.
50
+
51
+ =item * C<[*]>
52
+
53
+ Array/Bag/Set wildcard that yields all items.
54
+
55
+ =back
56
+
57
+ No other syntax is supported.
58
+
59
+ The public API intentionally mirrors key C<std/path/z> methods:
60
+ C<get>, C<select>, C<query>, C<first>, C<exists>,
61
+ C<expression>, C<assign_first>, C<assign_all>, C<assign_maybe>,
62
+ C<ref_first>, C<ref_all>, and C<ref_maybe>.
63
+
64
+ The path operators C<@>, C<@@>, and C<@?> can be set to use this module
65
+ in a lexical scope:
66
+
67
+ from std/path/simple import SimplePath;
68
+ SimplePath.use();
69
+
70
+ =head1 EXPORTS
71
+
72
+ =head2 Classes
73
+
74
+ =over
75
+
76
+ =item C<< SimplePath({ path: String }) >>
77
+
78
+ Constructs a simple path selector. Returns: C<SimplePath>.
79
+
80
+ =over
81
+
82
+ =item C<< SimplePath.use() >>
83
+
84
+ Parameters: none. Returns: C<null>. Makes this path class the lexical
85
+ implementation for C<@>, C<@@>, and C<@?>.
86
+
87
+ =item C<< path.expression() >>
88
+
89
+ Parameters: none. Returns: C<String>. Returns the original path
90
+ expression.
91
+
92
+ =item C<< path.get(value) >>, C<< path.select(value) >>, C<< path.query(value) >>
93
+
94
+ Parameters: C<value> is the query root. Returns: C<Array>. Evaluates the
95
+ path and returns selected values.
96
+
97
+ =item C<< path.first(value, fallback) >>
98
+
99
+ Parameters: C<value> is the query root and C<fallback> is returned when
100
+ there is no match. Returns: value. Returns the first selected value.
101
+
102
+ =item C<< path.exists(value) >>
103
+
104
+ Parameters: C<value> is the query root. Returns: C<Boolean>. Returns
105
+ true when the path selects at least one value.
106
+
107
+ =item C<< path.assign_first(target, value, op := ":=", weak := false) >>
108
+
109
+ Parameters: C<target> is the query root, C<value> is the assignment
110
+ value, C<op> is an assignment operator, and C<weak> is accepted for path
111
+ API compatibility. Returns: value. Updates the first selected location.
112
+
113
+ =item C<< path.assign_all(target, value, op := ":=", weak := false) >>
114
+
115
+ Parameters: same as C<assign_first>. Returns: value. Updates every
116
+ selected location.
117
+
118
+ =item C<< path.assign_maybe(target, value, op := ":=", weak := false) >>
119
+
120
+ Parameters: same as C<assign_first>. Returns: C<Boolean>. Updates the
121
+ first selected location when one exists.
122
+
123
+ =item C<< path.ref_first(target) >>
124
+
125
+ Parameters: C<target> is the query root. Returns: C<Function>. Returns a
126
+ reference-like getter/setter for the first selected location.
127
+
128
+ =item C<< path.ref_all(target) >>
129
+
130
+ Parameters: C<target> is the query root. Returns: C<Array>. Returns
131
+ reference-like getter/setters for all selected locations.
132
+
133
+ =item C<< path.ref_maybe(target) >>
134
+
135
+ Parameters: C<target> is the query root. Returns: C<Function> or
136
+ C<null>. Returns a reference-like getter/setter for the first selected
137
+ location when one exists.
138
+
139
+ =back
140
+
141
+ =back
142
+
143
+ =cut
144
+
145
+ from std/string import substr;
146
+
147
+
148
+ class SimplePath {
149
+ let String path;
150
+ let Array _steps := [];
151
+
152
+ static method use () {
153
+ from std/internals import setupperprop;
154
+ setupperprop( 1, "paths", self );
155
+ }
156
+
157
+ method __build__ () {
158
+ _steps := self._parse(path);
159
+ }
160
+
161
+ method expression () {
162
+ return path;
163
+ }
164
+
165
+ method _parse ( String raw ) {
166
+ let text := raw;
167
+ let steps := [];
168
+ let i := 0;
169
+
170
+ while ( i < length text ) {
171
+ let ch := substr( text, i, 1 );
172
+ if ( ch ≡ "." ) {
173
+ i++;
174
+ die "SimplePath parse error: expected name or * after '.'"
175
+ if i >= length text;
176
+ let after_dot := substr( text, i, 1 );
177
+ if ( after_dot ≡ "*" ) {
178
+ steps.push( { kind: "dict_wildcard" } );
179
+ i++;
180
+ next;
181
+ }
182
+ let start := i;
183
+ while ( i < length text ) {
184
+ let c := substr( text, i, 1 );
185
+ last if c ≡ "." or c ≡ "[" or c ≡ "]";
186
+ i++;
187
+ }
188
+ let key := substr( text, start, i - start );
189
+ die "SimplePath parse error: empty key"
190
+ if key ≡ "";
191
+ steps.push( { kind: "key", value: key } );
192
+ next;
193
+ }
194
+
195
+ if ( ch ≡ "[" ) {
196
+ let close := i + 1;
197
+ while ( close < length text and substr( text, close, 1 ) ≢ "]" ) {
198
+ close++;
199
+ }
200
+ die "SimplePath parse error: missing closing ']'"
201
+ if close >= length text;
202
+ let inner := substr( text, i + 1, close - i - 1 );
203
+ if ( inner ≡ "*" ) {
204
+ steps.push( { kind: "list_wildcard" } );
205
+ }
206
+ else if ( inner ~ /^-?[0-9]+$/ ) {
207
+ steps.push( { kind: "index", value: int(inner) } );
208
+ }
209
+ else {
210
+ die `SimplePath parse error: unsupported bracket token '[${inner}]'`;
211
+ }
212
+ i := close + 1;
213
+ next;
214
+ }
215
+
216
+ let start := i;
217
+ while ( i < length text ) {
218
+ let c := substr( text, i, 1 );
219
+ last if c ≡ "." or c ≡ "[" or c ≡ "]";
220
+ i++;
221
+ }
222
+ let key := substr( text, start, i - start );
223
+ die `SimplePath parse error: unexpected token '${ch}'`
224
+ if key ≡ "";
225
+ steps.push( { kind: "key", value: key } );
226
+ }
227
+
228
+ return steps;
229
+ }
230
+
231
+ method _node ( value, parent, key ) {
232
+ return {
233
+ value: value,
234
+ parent: parent,
235
+ key: key,
236
+ };
237
+ }
238
+
239
+ method _evaluate_nodes ( value ) {
240
+ let current := [ self._node( value, null, null ) ];
241
+
242
+ for ( let step in _steps ) {
243
+ let next_nodes := [];
244
+
245
+ for ( let node in current ) {
246
+ let v := node{value};
247
+
248
+ if ( step{kind} ≡ "key" ) {
249
+ if ( v instanceof Dict and v.exists( step{value} ) ) {
250
+ next_nodes.push( self._node( v.get( step{value} ), node, step{value} ) );
251
+ }
252
+ else if ( v instanceof PairList ) {
253
+ for ( let item in v.get_all( step{value} ) ) {
254
+ next_nodes.push( self._node( item, node, step{value} ) );
255
+ }
256
+ }
257
+ next;
258
+ }
259
+
260
+ if ( step{kind} ≡ "dict_wildcard" ) {
261
+ if ( v instanceof Dict ) {
262
+ for ( let k in v.keys() ) {
263
+ next_nodes.push( self._node( v.get(k), node, k ) );
264
+ }
265
+ }
266
+ else if ( v instanceof PairList ) {
267
+ for ( let pair in v.to_Array() ) {
268
+ next_nodes.push( self._node( pair.value, node, pair.key ) );
269
+ }
270
+ }
271
+ next;
272
+ }
273
+
274
+ if ( step{kind} ≡ "index" ) {
275
+ if ( v instanceof Array ) {
276
+ let idx := step{value};
277
+ if ( idx < 0 ) {
278
+ idx := v.length() + idx;
279
+ }
280
+ if ( idx >= 0 and idx < v.length() ) {
281
+ next_nodes.push( self._node( v[idx], node, idx ) );
282
+ }
283
+ }
284
+ next;
285
+ }
286
+
287
+ if ( step{kind} ≡ "list_wildcard" ) {
288
+ if ( v instanceof Array ) {
289
+ let i := 0;
290
+ while ( i < v.length() ) {
291
+ next_nodes.push( self._node( v[i], node, i ) );
292
+ i++;
293
+ }
294
+ }
295
+ else if ( v instanceof Bag or v instanceof Set ) {
296
+ for ( let item in v.to_Array() ) {
297
+ next_nodes.push( self._node( item, node, "*" ) );
298
+ }
299
+ }
300
+ next;
301
+ }
302
+ }
303
+
304
+ current := next_nodes;
305
+ }
306
+
307
+ return current;
308
+ }
309
+
310
+ method _evaluate ( value ) {
311
+ return self._evaluate_nodes(value).map( fn n -> n{value} );
312
+ }
313
+
314
+ method get ( value ) {
315
+ return self._evaluate(value);
316
+ }
317
+
318
+ method select ( value ) {
319
+ return self._evaluate(value);
320
+ }
321
+
322
+ method query ( value ) {
323
+ return self._evaluate(value);
324
+ }
325
+
326
+ method first ( value, fallback ) {
327
+ let out := self._evaluate(value);
328
+ return out.length() = 0 ? fallback : out[0];
329
+ }
330
+
331
+ method exists ( value ) {
332
+ return self._evaluate(value).length() > 0;
333
+ }
334
+
335
+ method _assign_node ( Dict node, value ) {
336
+ let parent := node{parent};
337
+ die "SimplePath assignment target has no parent node"
338
+ if parent ≡ null;
339
+
340
+ let container := parent{value};
341
+ let key := node{key};
342
+
343
+ if ( container instanceof Array ) {
344
+ die "SimplePath assignment expects numeric array index"
345
+ if not( key instanceof Number );
346
+ container[key] := value;
347
+ return value;
348
+ }
349
+
350
+ if ( container instanceof Dict ) {
351
+ die "SimplePath assignment expects string dict key"
352
+ if not( key instanceof String );
353
+ container{(key)} := value;
354
+ return value;
355
+ }
356
+
357
+ if ( container instanceof PairList ) {
358
+ die "SimplePath assignment expects string pairlist key"
359
+ if not( key instanceof String );
360
+ container.set( key, value );
361
+ return value;
362
+ }
363
+
364
+ die `SimplePath assignment target container '${typeof container}' is not assignable`;
365
+ }
366
+
367
+ method _ref_for_node ( Dict node ) {
368
+ let parent := node{parent};
369
+ die "SimplePath assignment target has no parent node"
370
+ if parent ≡ null;
371
+
372
+ let container := parent{value};
373
+ let key := node{key};
374
+
375
+ if ( container instanceof Array ) {
376
+ die "SimplePath assignment expects numeric array index"
377
+ if not( key instanceof Number );
378
+ return \ container[key];
379
+ }
380
+
381
+ if ( container instanceof Dict ) {
382
+ die "SimplePath assignment expects string dict key"
383
+ if not( key instanceof String );
384
+ return \ container{(key)};
385
+ }
386
+
387
+ if ( container instanceof PairList ) {
388
+ die "SimplePath assignment expects string pairlist key"
389
+ if not( key instanceof String );
390
+ return \ container{(key)};
391
+ }
392
+
393
+ die `SimplePath assignment target container '${typeof container}' is not assignable`;
394
+ }
395
+
396
+ method _apply_assignment_ref ( ref, value, op := ":=", weak := false ) {
397
+ die "SimplePath weak assignment is not supported"
398
+ if weak;
399
+
400
+ if ( op ≡ ":=" ) {
401
+ return ref(value);
402
+ }
403
+
404
+ let current := ref();
405
+
406
+ if ( op ≡ "+=" ) {
407
+ current += value;
408
+ }
409
+ else if ( op ≡ "-=" ) {
410
+ current -= value;
411
+ }
412
+ else if ( op ≡ "*=" or op ≡ "×=" ) {
413
+ current *= value;
414
+ }
415
+ else if ( op ≡ "/=" or op ≡ "÷=" ) {
416
+ current /= value;
417
+ }
418
+ else if ( op ≡ "**=" ) {
419
+ current **= value;
420
+ }
421
+ else if ( op ≡ "_=" ) {
422
+ current _= value;
423
+ }
424
+ else if ( op ≡ "?:=" ) {
425
+ current ?:= value;
426
+ }
427
+ else if ( op ≡ "~=" ) {
428
+ current ~= value[0] -> value[1](m);
429
+ }
430
+ else {
431
+ die `Unsupported path assignment operator '${op}'`;
432
+ }
433
+
434
+ ref(current);
435
+ return current;
436
+ }
437
+
438
+ method _assign_all_result ( value, op, last_result ) {
439
+ return op ≡ "~=" ? last_result : value;
440
+ }
441
+
442
+ method assign_first ( target, value, op := ":=", weak := false ) {
443
+ let nodes := self._evaluate_nodes(target);
444
+ die "SimplePath assignment found no matches"
445
+ if nodes.length() ≡ 0;
446
+ return self._apply_assignment_ref(
447
+ self._ref_for_node( nodes[0] ),
448
+ value,
449
+ op,
450
+ weak,
451
+ );
452
+ }
453
+
454
+ method assign_all ( target, value, op := ":=", weak := false ) {
455
+ let nodes := self._evaluate_nodes(target);
456
+ if ( nodes.length() ≡ 0 ) {
457
+ return self._assign_all_result( value, op, value );
458
+ }
459
+
460
+ let i := 0;
461
+ let last_result := value;
462
+ while ( i < nodes.length() ) {
463
+ last_result := self._apply_assignment_ref(
464
+ self._ref_for_node( nodes[i] ),
465
+ value,
466
+ op,
467
+ weak,
468
+ );
469
+ i++;
470
+ }
471
+
472
+ return self._assign_all_result( value, op, last_result );
473
+ }
474
+
475
+ method assign_maybe ( target, value, op := ":=", weak := false ) {
476
+ let nodes := self._evaluate_nodes(target);
477
+ if ( nodes.length() ≡ 0 ) {
478
+ return false;
479
+ }
480
+
481
+ self._apply_assignment_ref(
482
+ self._ref_for_node( nodes[0] ),
483
+ value,
484
+ op,
485
+ weak,
486
+ );
487
+ return true;
488
+ }
489
+
490
+ method ref_first ( target ) {
491
+ let nodes := self._evaluate_nodes(target);
492
+ die "SimplePath assignment found no matches"
493
+ if nodes.length() ≡ 0;
494
+ return self._ref_for_node( nodes[0] );
495
+ }
496
+
497
+ method ref_all ( target ) {
498
+ let nodes := self._evaluate_nodes(target);
499
+ let out := [];
500
+ for ( let node in nodes ) {
501
+ out.push( self._ref_for_node(node) );
502
+ }
503
+ return out;
504
+ }
505
+
506
+ method ref_maybe ( target ) {
507
+ let nodes := self._evaluate_nodes(target);
508
+ return nodes.length() ≡ 0 ? null : self._ref_for_node( nodes[0] );
509
+ }
510
+ }
511
+
512
+ =head1 COPYRIGHT AND LICENCE
513
+
514
+ B<< std/path/simple >> is copyright Toby Inkster.
515
+
516
+ It is free software; you may redistribute it and/or modify it under
517
+ the terms of either the Artistic License 1.0 or the GNU General Public
518
+ License version 2.
519
+
520
+ =cut
@@ -0,0 +1,147 @@
1
+ =encoding utf8
2
+
3
+ =head1 NAME
4
+
5
+ std/path/z/context - Evaluation context used by std/path/z.
6
+
7
+ =head1 IMPLEMENTATION SUPPORT
8
+
9
+ This module is supported by all implementations of ZuzuScript.
10
+
11
+ =head1 DESCRIPTION
12
+
13
+ This module provides the pure-Zuzu evaluation context used by ZPath.
14
+
15
+ =head1 EXPORTS
16
+
17
+ =head2 Classes
18
+
19
+ =over
20
+
21
+ =item C<< Ctx({ root, nodeset?, parentset?, meta? }) >>
22
+
23
+ Constructs a ZPath evaluation context. Returns: C<Ctx>. Wraps C<root>
24
+ as a C<std/path/z/node> C<Node> and stores the active node sets.
25
+
26
+ =over
27
+
28
+ =item C<< ctx.with_nodeset(ns, ps) >>
29
+
30
+ Parameters: C<ns> is the next node set and C<ps> is the parent set.
31
+ Returns: C<Ctx>. Returns a copy of the context with different node
32
+ sets.
33
+
34
+ =item C<< ctx.nested(extras?) >>
35
+
36
+ Parameters: C<extras> is optional metadata. Returns: C<Ctx>. Returns a
37
+ nested context with incremented metadata level.
38
+
39
+ =item C<< ctx.root() >>
40
+
41
+ Parameters: none. Returns: C<Node>. Returns the root node.
42
+
43
+ =item C<< ctx.nodeset() >>
44
+
45
+ Parameters: none. Returns: C<Array>. Returns the current node set.
46
+
47
+ =item C<< ctx.parentset() >>
48
+
49
+ Parameters: none. Returns: C<Array> or C<null>. Returns the parent node
50
+ set.
51
+
52
+ =item C<< ctx.meta() >>
53
+
54
+ Parameters: none. Returns: C<Dict>. Returns context metadata.
55
+
56
+ =back
57
+
58
+ =back
59
+
60
+ =head1 COPYRIGHT AND LICENCE
61
+
62
+ B<< std/path/z/context >> is copyright Toby Inkster.
63
+
64
+ It is free software; you may redistribute it and/or modify it under
65
+ the terms of either the Artistic License 1.0 or the GNU General Public
66
+ License version 2.
67
+
68
+ =cut
69
+
70
+ from std/path/z/node import Node;
71
+
72
+ class Ctx {
73
+ let root := null;
74
+ let nodeset := null;
75
+ let parentset := null;
76
+ let meta := null;
77
+
78
+ method __build__ () {
79
+ if ( not ( root instanceof Node ) ) {
80
+ let root_obj := root;
81
+ let node_type := null;
82
+
83
+ try {
84
+ node_type := int( "" _ root_obj.nodeType() );
85
+ }
86
+ catch {
87
+ }
88
+
89
+ let xml_document := node_type = 9;
90
+ if ( not xml_document and root_obj can documentElement ) {
91
+ try {
92
+ root_obj.documentElement();
93
+ xml_document := true;
94
+ }
95
+ catch {
96
+ }
97
+ }
98
+
99
+ if ( xml_document ) {
100
+ try {
101
+ let de := root_obj.documentElement();
102
+ root_obj := de if de ≢ null;
103
+ }
104
+ catch {
105
+ }
106
+ }
107
+
108
+ root := Node.wrap( root_obj );
109
+ }
110
+
111
+ nodeset ?:= [ root ];
112
+ meta ?:= { level: 0 };
113
+ }
114
+
115
+ method with_nodeset ( ns, ps ) {
116
+ return new Ctx(
117
+ root: root,
118
+ nodeset: ns,
119
+ parentset: ps,
120
+ meta: meta,
121
+ );
122
+ }
123
+
124
+ method nested ( extras? ) {
125
+ let extra_meta := extras ?: {};
126
+
127
+ let next_meta := {
128
+ level: meta.get( "level", 0 ) + 1,
129
+ };
130
+
131
+ for ( let pair in extra_meta.enumerate ) {
132
+ next_meta.add( pair );
133
+ }
134
+
135
+ return new Ctx(
136
+ root: root,
137
+ nodeset: nodeset,
138
+ parentset: parentset,
139
+ meta: next_meta,
140
+ );
141
+ }
142
+
143
+ method root () { return root; }
144
+ method nodeset () { return nodeset; }
145
+ method parentset () { return parentset; }
146
+ method meta () { return meta; }
147
+ }