zuzu-js 0.3.0 → 0.5.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.
- package/bin/zuzu-generate-browser-stdlib +1 -0
- package/dist/zuzu-browser-worker.js +2346 -427
- package/dist/zuzu-browser.js +2352 -431
- package/lib/browser-bundle-entry.js +2 -0
- package/lib/cli.js +1 -1
- package/lib/collections.js +55 -4
- package/lib/host/browser-host.js +124 -0
- package/lib/runtime-helpers.js +50 -1
- package/lib/runtime.js +648 -35
- package/lib/tap.js +8 -1
- package/lib/transpiler-new/codegen.js +126 -22
- package/lib/transpiler-new/lexer.js +89 -4
- package/lib/transpiler-new/parser.js +153 -25
- package/lib/zuzu.js +5 -1
- package/modules/std/marshal/graph.js +3 -1
- package/modules/std/math/bignum.js +158 -31
- package/modules/std/math.js +1 -1
- package/modules/std/net/url.js +33 -24
- package/modules/std/string/encode.js +188 -0
- package/modules/std/string.js +21 -0
- package/modules/std/time.js +95 -4
- package/package.json +2 -1
- package/stdlib/modules/std/colour.zzm +1 -0
- package/stdlib/modules/std/config.zzm +6 -5
- package/stdlib/modules/std/getopt.zzm +3 -15
- package/stdlib/modules/std/net/url.zzm +45 -3
- package/stdlib/modules/std/path/zz/operators.zzm +438 -75
- package/stdlib/modules/std/string/encode.zzm +95 -0
- package/stdlib/modules/std/uuid.zzm +1 -1
|
@@ -206,279 +206,6 @@
|
|
|
206
206
|
}
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
// modules/std/string.js
|
|
210
|
-
var require_string = __commonJS({
|
|
211
|
-
"modules/std/string.js"(exports2, module2) {
|
|
212
|
-
"use strict";
|
|
213
|
-
function toStringValue(value) {
|
|
214
|
-
if (value instanceof RegExp) {
|
|
215
|
-
return value.source;
|
|
216
|
-
}
|
|
217
|
-
if (value && typeof value.to_String === "function") {
|
|
218
|
-
return String(value.to_String());
|
|
219
|
-
}
|
|
220
|
-
if (value instanceof Error) {
|
|
221
|
-
return value.message || value.name || String(value);
|
|
222
|
-
}
|
|
223
|
-
return value == null ? "" : String(value);
|
|
224
|
-
}
|
|
225
|
-
function isRegexLike(value) {
|
|
226
|
-
if (value == null) {
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
if (value instanceof RegExp) {
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
return Object.prototype.toString.call(value) === "[object RegExp]";
|
|
233
|
-
}
|
|
234
|
-
function index(text, needle, start = 0) {
|
|
235
|
-
const haystack = [...toStringValue(text)];
|
|
236
|
-
const find = [...toStringValue(needle)];
|
|
237
|
-
const offset = Math.max(0, Math.trunc(Number(start ?? 0)));
|
|
238
|
-
if (find.length === 0) {
|
|
239
|
-
return Math.min(offset, haystack.length);
|
|
240
|
-
}
|
|
241
|
-
for (let i = offset; i <= haystack.length - find.length; i++) {
|
|
242
|
-
let matched = true;
|
|
243
|
-
for (let j = 0; j < find.length; j++) {
|
|
244
|
-
if (haystack[i + j] !== find[j]) {
|
|
245
|
-
matched = false;
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (matched) {
|
|
250
|
-
return i;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return -1;
|
|
254
|
-
}
|
|
255
|
-
function rindex(text, needle, start = null) {
|
|
256
|
-
const haystack = [...toStringValue(text)];
|
|
257
|
-
const find = [...toStringValue(needle)];
|
|
258
|
-
if (start == null) {
|
|
259
|
-
start = haystack.length - find.length;
|
|
260
|
-
} else {
|
|
261
|
-
start = Math.trunc(Number(start));
|
|
262
|
-
}
|
|
263
|
-
if (find.length === 0) {
|
|
264
|
-
return Math.min(Math.max(0, start), haystack.length);
|
|
265
|
-
}
|
|
266
|
-
start = Math.min(Math.max(0, start), haystack.length - find.length);
|
|
267
|
-
for (let i = start; i >= 0; i--) {
|
|
268
|
-
let matched = true;
|
|
269
|
-
for (let j = 0; j < find.length; j++) {
|
|
270
|
-
if (haystack[i + j] !== find[j]) {
|
|
271
|
-
matched = false;
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
if (matched) {
|
|
276
|
-
return i;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
return -1;
|
|
280
|
-
}
|
|
281
|
-
function contains(text, needle) {
|
|
282
|
-
return index(text, needle) >= 0;
|
|
283
|
-
}
|
|
284
|
-
function integerValue(value, label) {
|
|
285
|
-
const number = Number(value ?? 0);
|
|
286
|
-
if (!Number.isInteger(number)) {
|
|
287
|
-
throw new Error(`${label} expects an integer`);
|
|
288
|
-
}
|
|
289
|
-
return number;
|
|
290
|
-
}
|
|
291
|
-
function chr(codepoint) {
|
|
292
|
-
if (arguments.length !== 1) {
|
|
293
|
-
throw new Error("chr() expects one argument");
|
|
294
|
-
}
|
|
295
|
-
const value = integerValue(codepoint, "chr()");
|
|
296
|
-
if (value < 0 || value > 1114111) {
|
|
297
|
-
throw new Error("chr() expects a Unicode code point in 0..0x10FFFF");
|
|
298
|
-
}
|
|
299
|
-
if (value >= 55296 && value <= 57343) {
|
|
300
|
-
throw new Error("chr() rejects surrogate code points");
|
|
301
|
-
}
|
|
302
|
-
return String.fromCodePoint(value);
|
|
303
|
-
}
|
|
304
|
-
function ord(text, index2 = 0) {
|
|
305
|
-
if (arguments.length < 1 || arguments.length > 2) {
|
|
306
|
-
throw new Error("ord() expects one or two arguments");
|
|
307
|
-
}
|
|
308
|
-
const chars = [...toStringValue(text)];
|
|
309
|
-
const offset = integerValue(index2, "ord()");
|
|
310
|
-
if (offset < 0 || offset >= chars.length) {
|
|
311
|
-
throw new Error("ord() index out of range");
|
|
312
|
-
}
|
|
313
|
-
return chars[offset].codePointAt(0);
|
|
314
|
-
}
|
|
315
|
-
function substr(text, offset, length = null) {
|
|
316
|
-
const chars = [...toStringValue(text)];
|
|
317
|
-
const from = Number(offset ?? 0);
|
|
318
|
-
if (length == null) {
|
|
319
|
-
return chars.slice(from).join("");
|
|
320
|
-
}
|
|
321
|
-
return chars.slice(from, from + Number(length)).join("");
|
|
322
|
-
}
|
|
323
|
-
function pattern_to_regexp(pattern, caseInsensitive = false) {
|
|
324
|
-
return new RegExp(String(pattern ?? ""), caseInsensitive ? "i" : "");
|
|
325
|
-
}
|
|
326
|
-
var REGEXP_META_CHARS = /* @__PURE__ */ new Set([
|
|
327
|
-
"\\",
|
|
328
|
-
"/",
|
|
329
|
-
"^",
|
|
330
|
-
"$",
|
|
331
|
-
".",
|
|
332
|
-
"|",
|
|
333
|
-
"?",
|
|
334
|
-
"*",
|
|
335
|
-
"+",
|
|
336
|
-
"(",
|
|
337
|
-
")",
|
|
338
|
-
"[",
|
|
339
|
-
"]",
|
|
340
|
-
"{",
|
|
341
|
-
"}",
|
|
342
|
-
'"',
|
|
343
|
-
"'"
|
|
344
|
-
]);
|
|
345
|
-
function quotemeta(text) {
|
|
346
|
-
return [...toStringValue(text)].map((ch) => REGEXP_META_CHARS.has(ch) ? `\\${ch}` : ch).join("");
|
|
347
|
-
}
|
|
348
|
-
function normalizePattern(pattern, flags = "") {
|
|
349
|
-
if (isRegexLike(pattern)) {
|
|
350
|
-
const mergedFlags = [...pattern.flags || "", ...flags || ""];
|
|
351
|
-
const uniqFlags = [...new Set(mergedFlags)].join("");
|
|
352
|
-
return new RegExp(pattern.source, uniqFlags);
|
|
353
|
-
}
|
|
354
|
-
return new RegExp(String(pattern ?? ""), flags);
|
|
355
|
-
}
|
|
356
|
-
function search(text, pattern, flags = "") {
|
|
357
|
-
const match = toStringValue(text).match(normalizePattern(pattern, flags));
|
|
358
|
-
return match ? match[0] : null;
|
|
359
|
-
}
|
|
360
|
-
function matches(text, pattern, flags = "") {
|
|
361
|
-
return normalizePattern(pattern, flags).test(toStringValue(text));
|
|
362
|
-
}
|
|
363
|
-
function replace(text, pattern, replacement, flags = "") {
|
|
364
|
-
return toStringValue(text).replace(normalizePattern(pattern, flags), toStringValue(replacement));
|
|
365
|
-
}
|
|
366
|
-
function sprint(format, ...args) {
|
|
367
|
-
let idx = 0;
|
|
368
|
-
return toStringValue(format).replace(/%([0-9]+)?(?:\.([0-9]+))?([sdfc])/gu, (_token, width, precision, kind) => {
|
|
369
|
-
const value = args[idx++];
|
|
370
|
-
let out = "";
|
|
371
|
-
if (kind === "d") {
|
|
372
|
-
out = String(Math.trunc(Number(value ?? 0)));
|
|
373
|
-
} else if (kind === "f") {
|
|
374
|
-
const num = Number(value ?? 0);
|
|
375
|
-
out = precision != null ? num.toFixed(Number(precision)) : String(num);
|
|
376
|
-
} else if (kind === "c") {
|
|
377
|
-
out = String.fromCharCode(Number(value ?? 0));
|
|
378
|
-
} else {
|
|
379
|
-
out = toStringValue(value);
|
|
380
|
-
}
|
|
381
|
-
if (width != null) {
|
|
382
|
-
const target = Number(width);
|
|
383
|
-
if (out.length < target) {
|
|
384
|
-
out = `${" ".repeat(target - out.length)}${out}`;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return out;
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
function join(separator, values) {
|
|
391
|
-
const sep = toStringValue(separator);
|
|
392
|
-
if (Array.isArray(values)) {
|
|
393
|
-
return values.map((value) => toStringValue(value)).join(sep);
|
|
394
|
-
}
|
|
395
|
-
if (values == null) {
|
|
396
|
-
return "";
|
|
397
|
-
}
|
|
398
|
-
if (typeof values.to_Iterator === "function") {
|
|
399
|
-
const out = [];
|
|
400
|
-
for (const value of values.to_Iterator()) {
|
|
401
|
-
out.push(toStringValue(value));
|
|
402
|
-
}
|
|
403
|
-
return out.join(sep);
|
|
404
|
-
}
|
|
405
|
-
if (typeof values.to_Array === "function") {
|
|
406
|
-
return join(sep, values.to_Array());
|
|
407
|
-
}
|
|
408
|
-
if (typeof values[Symbol.iterator] === "function") {
|
|
409
|
-
return Array.from(values, (value) => toStringValue(value)).join(sep);
|
|
410
|
-
}
|
|
411
|
-
return toStringValue(values);
|
|
412
|
-
}
|
|
413
|
-
function split(text, pattern) {
|
|
414
|
-
return toStringValue(text).split(pattern);
|
|
415
|
-
}
|
|
416
|
-
function starts_with(text, prefix) {
|
|
417
|
-
return toStringValue(text).startsWith(toStringValue(prefix));
|
|
418
|
-
}
|
|
419
|
-
function ends_with(text, suffix) {
|
|
420
|
-
return toStringValue(text).endsWith(toStringValue(suffix));
|
|
421
|
-
}
|
|
422
|
-
function trim(text) {
|
|
423
|
-
return toStringValue(text).trim();
|
|
424
|
-
}
|
|
425
|
-
function pad(text, width, ch = " ", side = "right") {
|
|
426
|
-
const src = toStringValue(text);
|
|
427
|
-
const padChar = toStringValue(ch || " ");
|
|
428
|
-
const target = Number(width ?? 0);
|
|
429
|
-
if (src.length >= target) {
|
|
430
|
-
return src;
|
|
431
|
-
}
|
|
432
|
-
const fill = padChar.repeat(target - src.length);
|
|
433
|
-
return side === "left" ? `${fill}${src}` : `${src}${fill}`;
|
|
434
|
-
}
|
|
435
|
-
function chomp(text) {
|
|
436
|
-
return toStringValue(text).replace(/\r?\n$/u, "");
|
|
437
|
-
}
|
|
438
|
-
function words(text) {
|
|
439
|
-
return toStringValue(text).replace(/([a-z0-9])([A-Z])/gu, "$1 $2").replace(/[_\-]+/gu, " ").trim().split(/\s+/u).filter(Boolean);
|
|
440
|
-
}
|
|
441
|
-
function title(text) {
|
|
442
|
-
return words(text).map((w) => `${w[0].toUpperCase()}${w.slice(1).toLowerCase()}`).join(" ");
|
|
443
|
-
}
|
|
444
|
-
function snake(text) {
|
|
445
|
-
return words(text).map((w) => w.toLowerCase()).join("_");
|
|
446
|
-
}
|
|
447
|
-
function kebab(text) {
|
|
448
|
-
return words(text).map((w) => w.toLowerCase()).join("-");
|
|
449
|
-
}
|
|
450
|
-
function camel(text) {
|
|
451
|
-
const ws = words(text).map((w) => w.toLowerCase());
|
|
452
|
-
return ws.map((w, i) => i === 0 ? w : `${w[0].toUpperCase()}${w.slice(1)}`).join("");
|
|
453
|
-
}
|
|
454
|
-
module2.exports = {
|
|
455
|
-
camel,
|
|
456
|
-
chomp,
|
|
457
|
-
chr,
|
|
458
|
-
contains,
|
|
459
|
-
ends_with,
|
|
460
|
-
index,
|
|
461
|
-
join,
|
|
462
|
-
kebab,
|
|
463
|
-
matches,
|
|
464
|
-
ord,
|
|
465
|
-
pad,
|
|
466
|
-
pattern_to_regexp,
|
|
467
|
-
quotemeta,
|
|
468
|
-
rindex,
|
|
469
|
-
replace,
|
|
470
|
-
search,
|
|
471
|
-
snake,
|
|
472
|
-
split,
|
|
473
|
-
starts_with,
|
|
474
|
-
sprint,
|
|
475
|
-
substr,
|
|
476
|
-
title,
|
|
477
|
-
trim
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
|
|
482
209
|
// lib/collections.js
|
|
483
210
|
var require_collections = __commonJS({
|
|
484
211
|
"lib/collections.js"(exports2, module2) {
|
|
@@ -501,6 +228,12 @@
|
|
|
501
228
|
function makeSet(values) {
|
|
502
229
|
return runtimeHelpers().makeSet(values);
|
|
503
230
|
}
|
|
231
|
+
function operatorString(value) {
|
|
232
|
+
return runtimeHelpers().operatorString(value);
|
|
233
|
+
}
|
|
234
|
+
function stringSortComparator(a, b) {
|
|
235
|
+
return runtimeHelpers().stringSortComparator(a, b);
|
|
236
|
+
}
|
|
504
237
|
var ZuzuBag = class _ZuzuBag {
|
|
505
238
|
constructor(...items) {
|
|
506
239
|
let values;
|
|
@@ -548,7 +281,13 @@
|
|
|
548
281
|
return this.add(...values);
|
|
549
282
|
}
|
|
550
283
|
remove(value) {
|
|
551
|
-
|
|
284
|
+
for (let idx = this.items.length - 1; idx >= 0; idx--) {
|
|
285
|
+
if (this.items[idx] === value) {
|
|
286
|
+
releaseCollectionValue(this, this.items[idx]);
|
|
287
|
+
this.items.splice(idx, 1);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return this;
|
|
552
291
|
}
|
|
553
292
|
remove_first(value) {
|
|
554
293
|
const idx = this.items.indexOf(value);
|
|
@@ -568,9 +307,6 @@
|
|
|
568
307
|
});
|
|
569
308
|
return this;
|
|
570
309
|
}
|
|
571
|
-
get(idx, fallback = null) {
|
|
572
|
-
return idx >= 0 && idx < this.items.length ? this.items[idx] : fallback;
|
|
573
|
-
}
|
|
574
310
|
map(fn2) {
|
|
575
311
|
return new _ZuzuBag(this.items.map(fn2));
|
|
576
312
|
}
|
|
@@ -620,7 +356,7 @@
|
|
|
620
356
|
return this.to_Array().sort(fn2);
|
|
621
357
|
}
|
|
622
358
|
sortstr() {
|
|
623
|
-
return this.to_Array().sort(
|
|
359
|
+
return this.to_Array().sort(stringSortComparator);
|
|
624
360
|
}
|
|
625
361
|
sortnum() {
|
|
626
362
|
return this.to_Array().map((item) => Number(item)).sort((a, b) => a - b);
|
|
@@ -707,6 +443,9 @@
|
|
|
707
443
|
empty() {
|
|
708
444
|
return this.list.length === 0 ? 1 : 0;
|
|
709
445
|
}
|
|
446
|
+
is_empty() {
|
|
447
|
+
return this.empty();
|
|
448
|
+
}
|
|
710
449
|
keys() {
|
|
711
450
|
return this.list.map((pair) => pair[0]);
|
|
712
451
|
}
|
|
@@ -813,6 +552,7 @@
|
|
|
813
552
|
configurable: true
|
|
814
553
|
});
|
|
815
554
|
function withArrayMethods() {
|
|
555
|
+
const nativeJoin = Array.prototype.join;
|
|
816
556
|
const define = (name2, fn2) => {
|
|
817
557
|
if (!Object.prototype.hasOwnProperty.call(Array.prototype, name2)) {
|
|
818
558
|
const desc = /* @__PURE__ */ Object.create(null);
|
|
@@ -821,6 +561,38 @@
|
|
|
821
561
|
Object.defineProperty(Array.prototype, name2, desc);
|
|
822
562
|
}
|
|
823
563
|
};
|
|
564
|
+
if (Array.prototype.join.__zuzu_array_join !== true) {
|
|
565
|
+
const desc = /* @__PURE__ */ Object.create(null);
|
|
566
|
+
desc.value = function _join(separator, fallback) {
|
|
567
|
+
const hasFallback = arguments.length > 1;
|
|
568
|
+
let fallbackString;
|
|
569
|
+
const sep = operatorString(separator);
|
|
570
|
+
const out = [];
|
|
571
|
+
for (const value of this) {
|
|
572
|
+
try {
|
|
573
|
+
out.push(operatorString(value));
|
|
574
|
+
} catch (err) {
|
|
575
|
+
if (!hasFallback) {
|
|
576
|
+
throw err;
|
|
577
|
+
}
|
|
578
|
+
if (typeof fallback === "function") {
|
|
579
|
+
out.push(operatorString(fallback(value)));
|
|
580
|
+
} else {
|
|
581
|
+
if (fallbackString === void 0) {
|
|
582
|
+
fallbackString = operatorString(fallback);
|
|
583
|
+
}
|
|
584
|
+
out.push(fallbackString);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return nativeJoin.call(out, sep);
|
|
589
|
+
};
|
|
590
|
+
desc.value.__zuzu_array_join = true;
|
|
591
|
+
desc.enumerable = false;
|
|
592
|
+
desc.configurable = true;
|
|
593
|
+
desc.writable = true;
|
|
594
|
+
Object.defineProperty(Array.prototype, "join", desc);
|
|
595
|
+
}
|
|
824
596
|
define("count", function _count() {
|
|
825
597
|
return this.length;
|
|
826
598
|
});
|
|
@@ -911,7 +683,7 @@
|
|
|
911
683
|
return this;
|
|
912
684
|
});
|
|
913
685
|
define("sortstr", function _sortstr() {
|
|
914
|
-
return this.slice().sort(
|
|
686
|
+
return this.slice().sort(stringSortComparator);
|
|
915
687
|
});
|
|
916
688
|
define(
|
|
917
689
|
"sortnum",
|
|
@@ -1467,6 +1239,9 @@
|
|
|
1467
1239
|
if (name2 === "eq") {
|
|
1468
1240
|
return (left, right) => String(left) === String(right);
|
|
1469
1241
|
}
|
|
1242
|
+
if (name2 === "eqi") {
|
|
1243
|
+
return (left, right) => String(left).toLowerCase() === String(right).toLowerCase();
|
|
1244
|
+
}
|
|
1470
1245
|
if (name2 === "~") {
|
|
1471
1246
|
return (left, right) => {
|
|
1472
1247
|
if (right && typeof right.test === "function") {
|
|
@@ -1477,11 +1252,19 @@
|
|
|
1477
1252
|
}
|
|
1478
1253
|
return (left, right) => left == right;
|
|
1479
1254
|
}
|
|
1255
|
+
function switchTruthy(value) {
|
|
1256
|
+
return !!value;
|
|
1257
|
+
}
|
|
1480
1258
|
function runSwitch(value, cmpName, cases, defaultBody) {
|
|
1481
1259
|
const cmp = buildComparator(cmpName);
|
|
1482
1260
|
let runNext = false;
|
|
1483
1261
|
for (const section of cases) {
|
|
1484
|
-
|
|
1262
|
+
let matched = false;
|
|
1263
|
+
if (Array.isArray(section.tests)) {
|
|
1264
|
+
matched = section.tests.some((test) => switchTruthy(test(value)));
|
|
1265
|
+
} else {
|
|
1266
|
+
matched = section.values.some((item) => cmp(value, item));
|
|
1267
|
+
}
|
|
1485
1268
|
if (matched || runNext) {
|
|
1486
1269
|
const result = section.body();
|
|
1487
1270
|
runNext = result === true;
|
|
@@ -1758,6 +1541,32 @@
|
|
|
1758
1541
|
}
|
|
1759
1542
|
throw new Error(`TypeException: cannot coerce ${typeName2(value)} to String`);
|
|
1760
1543
|
}
|
|
1544
|
+
var surrogatePattern = /[\uD800-\uDFFF]/;
|
|
1545
|
+
function codePointStringCompare(left, right) {
|
|
1546
|
+
if (left === right) {
|
|
1547
|
+
return 0;
|
|
1548
|
+
}
|
|
1549
|
+
if (surrogatePattern.test(left) || surrogatePattern.test(right)) {
|
|
1550
|
+
const leftPoints = Array.from(left);
|
|
1551
|
+
const rightPoints = Array.from(right);
|
|
1552
|
+
const shared = Math.min(leftPoints.length, rightPoints.length);
|
|
1553
|
+
for (let i = 0; i < shared; i++) {
|
|
1554
|
+
const a = leftPoints[i].codePointAt(0);
|
|
1555
|
+
const b = rightPoints[i].codePointAt(0);
|
|
1556
|
+
if (a !== b) {
|
|
1557
|
+
return a < b ? -1 : 1;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
if (leftPoints.length === rightPoints.length) {
|
|
1561
|
+
return 0;
|
|
1562
|
+
}
|
|
1563
|
+
return leftPoints.length < rightPoints.length ? -1 : 1;
|
|
1564
|
+
}
|
|
1565
|
+
return left < right ? -1 : 1;
|
|
1566
|
+
}
|
|
1567
|
+
function stringSortComparator(a, b) {
|
|
1568
|
+
return codePointStringCompare(String(a), String(b));
|
|
1569
|
+
}
|
|
1761
1570
|
function operatorRegexp(value) {
|
|
1762
1571
|
value = resolveWeakValue(value);
|
|
1763
1572
|
if (value instanceof RegExp || Object.prototype.toString.call(value) === "[object RegExp]") {
|
|
@@ -1786,6 +1595,8 @@
|
|
|
1786
1595
|
lengthOf,
|
|
1787
1596
|
operatorString,
|
|
1788
1597
|
operatorRegexp,
|
|
1598
|
+
codePointStringCompare,
|
|
1599
|
+
stringSortComparator,
|
|
1789
1600
|
ZuzuBinary,
|
|
1790
1601
|
BinaryString: BinaryString2,
|
|
1791
1602
|
ZuzuWeakCell,
|
|
@@ -1810,6 +1621,295 @@
|
|
|
1810
1621
|
}
|
|
1811
1622
|
});
|
|
1812
1623
|
|
|
1624
|
+
// modules/std/string.js
|
|
1625
|
+
var require_string = __commonJS({
|
|
1626
|
+
"modules/std/string.js"(exports2, module2) {
|
|
1627
|
+
"use strict";
|
|
1628
|
+
var { BinaryString: BinaryString2 } = require_runtime_helpers();
|
|
1629
|
+
function toStringValue(value) {
|
|
1630
|
+
if (value instanceof RegExp) {
|
|
1631
|
+
return value.source;
|
|
1632
|
+
}
|
|
1633
|
+
if (value && typeof value.to_String === "function") {
|
|
1634
|
+
return String(value.to_String());
|
|
1635
|
+
}
|
|
1636
|
+
if (value instanceof Error) {
|
|
1637
|
+
return value.message || value.name || String(value);
|
|
1638
|
+
}
|
|
1639
|
+
return value == null ? "" : String(value);
|
|
1640
|
+
}
|
|
1641
|
+
function isRegexLike(value) {
|
|
1642
|
+
if (value == null) {
|
|
1643
|
+
return false;
|
|
1644
|
+
}
|
|
1645
|
+
if (value instanceof RegExp) {
|
|
1646
|
+
return true;
|
|
1647
|
+
}
|
|
1648
|
+
return Object.prototype.toString.call(value) === "[object RegExp]";
|
|
1649
|
+
}
|
|
1650
|
+
function index(text, needle, start = 0) {
|
|
1651
|
+
const haystack = [...toStringValue(text)];
|
|
1652
|
+
const find = [...toStringValue(needle)];
|
|
1653
|
+
const offset = Math.max(0, Math.trunc(Number(start ?? 0)));
|
|
1654
|
+
if (find.length === 0) {
|
|
1655
|
+
return Math.min(offset, haystack.length);
|
|
1656
|
+
}
|
|
1657
|
+
for (let i = offset; i <= haystack.length - find.length; i++) {
|
|
1658
|
+
let matched = true;
|
|
1659
|
+
for (let j = 0; j < find.length; j++) {
|
|
1660
|
+
if (haystack[i + j] !== find[j]) {
|
|
1661
|
+
matched = false;
|
|
1662
|
+
break;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
if (matched) {
|
|
1666
|
+
return i;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
return -1;
|
|
1670
|
+
}
|
|
1671
|
+
function rindex(text, needle, start = null) {
|
|
1672
|
+
const haystack = [...toStringValue(text)];
|
|
1673
|
+
const find = [...toStringValue(needle)];
|
|
1674
|
+
if (start == null) {
|
|
1675
|
+
start = haystack.length - find.length;
|
|
1676
|
+
} else {
|
|
1677
|
+
start = Math.trunc(Number(start));
|
|
1678
|
+
}
|
|
1679
|
+
if (find.length === 0) {
|
|
1680
|
+
return Math.min(Math.max(0, start), haystack.length);
|
|
1681
|
+
}
|
|
1682
|
+
start = Math.min(Math.max(0, start), haystack.length - find.length);
|
|
1683
|
+
for (let i = start; i >= 0; i--) {
|
|
1684
|
+
let matched = true;
|
|
1685
|
+
for (let j = 0; j < find.length; j++) {
|
|
1686
|
+
if (haystack[i + j] !== find[j]) {
|
|
1687
|
+
matched = false;
|
|
1688
|
+
break;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
if (matched) {
|
|
1692
|
+
return i;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
return -1;
|
|
1696
|
+
}
|
|
1697
|
+
function contains(text, needle) {
|
|
1698
|
+
return index(text, needle) >= 0;
|
|
1699
|
+
}
|
|
1700
|
+
function integerValue(value, label) {
|
|
1701
|
+
const number = Number(value ?? 0);
|
|
1702
|
+
if (!Number.isInteger(number)) {
|
|
1703
|
+
throw new Error(`${label} expects an integer`);
|
|
1704
|
+
}
|
|
1705
|
+
return number;
|
|
1706
|
+
}
|
|
1707
|
+
function chr(codepoint) {
|
|
1708
|
+
if (arguments.length !== 1) {
|
|
1709
|
+
throw new Error("chr() expects one argument");
|
|
1710
|
+
}
|
|
1711
|
+
const value = integerValue(codepoint, "chr()");
|
|
1712
|
+
if (value < 0 || value > 1114111) {
|
|
1713
|
+
throw new Error("chr() expects a Unicode code point in 0..0x10FFFF");
|
|
1714
|
+
}
|
|
1715
|
+
if (value >= 55296 && value <= 57343) {
|
|
1716
|
+
throw new Error("chr() rejects surrogate code points");
|
|
1717
|
+
}
|
|
1718
|
+
return String.fromCodePoint(value);
|
|
1719
|
+
}
|
|
1720
|
+
function ord(text, index2 = 0) {
|
|
1721
|
+
if (arguments.length < 1 || arguments.length > 2) {
|
|
1722
|
+
throw new Error("ord() expects one or two arguments");
|
|
1723
|
+
}
|
|
1724
|
+
const chars = [...toStringValue(text)];
|
|
1725
|
+
const offset = integerValue(index2, "ord()");
|
|
1726
|
+
if (offset < 0 || offset >= chars.length) {
|
|
1727
|
+
throw new Error("ord() index out of range");
|
|
1728
|
+
}
|
|
1729
|
+
return chars[offset].codePointAt(0);
|
|
1730
|
+
}
|
|
1731
|
+
function substr(text, offset, length = null) {
|
|
1732
|
+
const chars = [...toStringValue(text)];
|
|
1733
|
+
const from = Number(offset ?? 0);
|
|
1734
|
+
if (length == null) {
|
|
1735
|
+
return chars.slice(from).join("");
|
|
1736
|
+
}
|
|
1737
|
+
return chars.slice(from, from + Number(length)).join("");
|
|
1738
|
+
}
|
|
1739
|
+
function pattern_to_regexp(pattern, caseInsensitive = false) {
|
|
1740
|
+
return new RegExp(String(pattern ?? ""), caseInsensitive ? "i" : "");
|
|
1741
|
+
}
|
|
1742
|
+
var REGEXP_META_CHARS = /* @__PURE__ */ new Set([
|
|
1743
|
+
"\\",
|
|
1744
|
+
"/",
|
|
1745
|
+
"^",
|
|
1746
|
+
"$",
|
|
1747
|
+
".",
|
|
1748
|
+
"|",
|
|
1749
|
+
"?",
|
|
1750
|
+
"*",
|
|
1751
|
+
"+",
|
|
1752
|
+
"(",
|
|
1753
|
+
")",
|
|
1754
|
+
"[",
|
|
1755
|
+
"]",
|
|
1756
|
+
"{",
|
|
1757
|
+
"}",
|
|
1758
|
+
'"',
|
|
1759
|
+
"'"
|
|
1760
|
+
]);
|
|
1761
|
+
function quotemeta(text) {
|
|
1762
|
+
return [...toStringValue(text)].map((ch) => REGEXP_META_CHARS.has(ch) ? `\\${ch}` : ch).join("");
|
|
1763
|
+
}
|
|
1764
|
+
function normalizePattern(pattern, flags = "") {
|
|
1765
|
+
if (isRegexLike(pattern)) {
|
|
1766
|
+
const mergedFlags = [...pattern.flags || "", ...flags || ""];
|
|
1767
|
+
const uniqFlags = [...new Set(mergedFlags)].join("");
|
|
1768
|
+
return new RegExp(pattern.source, uniqFlags);
|
|
1769
|
+
}
|
|
1770
|
+
return new RegExp(String(pattern ?? ""), flags);
|
|
1771
|
+
}
|
|
1772
|
+
function search(text, pattern, flags = "") {
|
|
1773
|
+
const match = toStringValue(text).match(normalizePattern(pattern, flags));
|
|
1774
|
+
return match ? match[0] : null;
|
|
1775
|
+
}
|
|
1776
|
+
function matches(text, pattern, flags = "") {
|
|
1777
|
+
return normalizePattern(pattern, flags).test(toStringValue(text));
|
|
1778
|
+
}
|
|
1779
|
+
function replace(text, pattern, replacement, flags = "") {
|
|
1780
|
+
return toStringValue(text).replace(normalizePattern(pattern, flags), toStringValue(replacement));
|
|
1781
|
+
}
|
|
1782
|
+
function sprint(format, ...args) {
|
|
1783
|
+
let idx = 0;
|
|
1784
|
+
return toStringValue(format).replace(/%([0-9]+)?(?:\.([0-9]+))?([sdfc])/gu, (_token, width, precision, kind) => {
|
|
1785
|
+
const value = args[idx++];
|
|
1786
|
+
let out = "";
|
|
1787
|
+
if (kind === "d") {
|
|
1788
|
+
out = String(Math.trunc(Number(value ?? 0)));
|
|
1789
|
+
} else if (kind === "f") {
|
|
1790
|
+
const num = Number(value ?? 0);
|
|
1791
|
+
out = precision != null ? num.toFixed(Number(precision)) : String(num);
|
|
1792
|
+
} else if (kind === "c") {
|
|
1793
|
+
out = String.fromCharCode(Number(value ?? 0));
|
|
1794
|
+
} else {
|
|
1795
|
+
out = toStringValue(value);
|
|
1796
|
+
}
|
|
1797
|
+
if (width != null) {
|
|
1798
|
+
const target = Number(width);
|
|
1799
|
+
if (out.length < target) {
|
|
1800
|
+
out = `${" ".repeat(target - out.length)}${out}`;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
return out;
|
|
1804
|
+
});
|
|
1805
|
+
}
|
|
1806
|
+
function join(separator, values) {
|
|
1807
|
+
const sep = toStringValue(separator);
|
|
1808
|
+
if (Array.isArray(values)) {
|
|
1809
|
+
return values.map((value) => toStringValue(value)).join(sep);
|
|
1810
|
+
}
|
|
1811
|
+
if (values == null) {
|
|
1812
|
+
return "";
|
|
1813
|
+
}
|
|
1814
|
+
if (typeof values.to_Iterator === "function") {
|
|
1815
|
+
const out = [];
|
|
1816
|
+
for (const value of values.to_Iterator()) {
|
|
1817
|
+
out.push(toStringValue(value));
|
|
1818
|
+
}
|
|
1819
|
+
return out.join(sep);
|
|
1820
|
+
}
|
|
1821
|
+
if (typeof values.to_Array === "function") {
|
|
1822
|
+
return join(sep, values.to_Array());
|
|
1823
|
+
}
|
|
1824
|
+
if (typeof values[Symbol.iterator] === "function") {
|
|
1825
|
+
return Array.from(values, (value) => toStringValue(value)).join(sep);
|
|
1826
|
+
}
|
|
1827
|
+
return toStringValue(values);
|
|
1828
|
+
}
|
|
1829
|
+
function split(text, pattern) {
|
|
1830
|
+
return toStringValue(text).split(pattern);
|
|
1831
|
+
}
|
|
1832
|
+
function starts_with(text, prefix) {
|
|
1833
|
+
return toStringValue(text).startsWith(toStringValue(prefix));
|
|
1834
|
+
}
|
|
1835
|
+
function ends_with(text, suffix) {
|
|
1836
|
+
return toStringValue(text).endsWith(toStringValue(suffix));
|
|
1837
|
+
}
|
|
1838
|
+
function trim(text) {
|
|
1839
|
+
return toStringValue(text).trim();
|
|
1840
|
+
}
|
|
1841
|
+
function pad(text, width, ch = " ", side = "right") {
|
|
1842
|
+
const src = toStringValue(text);
|
|
1843
|
+
const padChar = toStringValue(ch || " ");
|
|
1844
|
+
const target = Number(width ?? 0);
|
|
1845
|
+
if (src.length >= target) {
|
|
1846
|
+
return src;
|
|
1847
|
+
}
|
|
1848
|
+
const fill = padChar.repeat(target - src.length);
|
|
1849
|
+
return side === "left" ? `${fill}${src}` : `${src}${fill}`;
|
|
1850
|
+
}
|
|
1851
|
+
function chomp(text) {
|
|
1852
|
+
return toStringValue(text).replace(/\r?\n$/u, "");
|
|
1853
|
+
}
|
|
1854
|
+
function words(text) {
|
|
1855
|
+
return toStringValue(text).replace(/([a-z0-9])([A-Z])/gu, "$1 $2").replace(/[_\-]+/gu, " ").trim().split(/\s+/u).filter(Boolean);
|
|
1856
|
+
}
|
|
1857
|
+
function title(text) {
|
|
1858
|
+
return words(text).map((w) => `${w[0].toUpperCase()}${w.slice(1).toLowerCase()}`).join(" ");
|
|
1859
|
+
}
|
|
1860
|
+
function snake(text) {
|
|
1861
|
+
return words(text).map((w) => w.toLowerCase()).join("_");
|
|
1862
|
+
}
|
|
1863
|
+
function kebab(text) {
|
|
1864
|
+
return words(text).map((w) => w.toLowerCase()).join("-");
|
|
1865
|
+
}
|
|
1866
|
+
function camel(text) {
|
|
1867
|
+
const ws = words(text).map((w) => w.toLowerCase());
|
|
1868
|
+
return ws.map((w, i) => i === 0 ? w : `${w[0].toUpperCase()}${w.slice(1)}`).join("");
|
|
1869
|
+
}
|
|
1870
|
+
function to_binary(value) {
|
|
1871
|
+
if (typeof value !== "string" && !(value instanceof String)) {
|
|
1872
|
+
const type = value == null ? "Null" : value && value.bytes instanceof Uint8Array ? "BinaryString" : typeof value;
|
|
1873
|
+
throw new Error(`TypeException: to_binary expects String, got ${type}`);
|
|
1874
|
+
}
|
|
1875
|
+
return new BinaryString2(new TextEncoder().encode(String(value)));
|
|
1876
|
+
}
|
|
1877
|
+
function to_string(value) {
|
|
1878
|
+
if (!(value && value.bytes instanceof Uint8Array)) {
|
|
1879
|
+
throw new Error("TypeException: to_string expects BinaryString");
|
|
1880
|
+
}
|
|
1881
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value.bytes);
|
|
1882
|
+
}
|
|
1883
|
+
module2.exports = {
|
|
1884
|
+
camel,
|
|
1885
|
+
chomp,
|
|
1886
|
+
chr,
|
|
1887
|
+
contains,
|
|
1888
|
+
ends_with,
|
|
1889
|
+
index,
|
|
1890
|
+
join,
|
|
1891
|
+
kebab,
|
|
1892
|
+
matches,
|
|
1893
|
+
ord,
|
|
1894
|
+
pad,
|
|
1895
|
+
pattern_to_regexp,
|
|
1896
|
+
quotemeta,
|
|
1897
|
+
rindex,
|
|
1898
|
+
replace,
|
|
1899
|
+
search,
|
|
1900
|
+
snake,
|
|
1901
|
+
split,
|
|
1902
|
+
starts_with,
|
|
1903
|
+
sprint,
|
|
1904
|
+
substr,
|
|
1905
|
+
title,
|
|
1906
|
+
to_binary,
|
|
1907
|
+
to_string,
|
|
1908
|
+
trim
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1911
|
+
});
|
|
1912
|
+
|
|
1813
1913
|
// modules/std/string/base64.js
|
|
1814
1914
|
var require_base64 = __commonJS({
|
|
1815
1915
|
"modules/std/string/base64.js"(exports2, module2) {
|
|
@@ -1924,6 +2024,172 @@
|
|
|
1924
2024
|
}
|
|
1925
2025
|
});
|
|
1926
2026
|
|
|
2027
|
+
// modules/std/string/encode.js
|
|
2028
|
+
var require_encode = __commonJS({
|
|
2029
|
+
"modules/std/string/encode.js"(exports2, module2) {
|
|
2030
|
+
"use strict";
|
|
2031
|
+
var { BinaryString: BinaryString2 } = require_runtime_helpers();
|
|
2032
|
+
function typeName2(value) {
|
|
2033
|
+
if (value == null) {
|
|
2034
|
+
return "Null";
|
|
2035
|
+
}
|
|
2036
|
+
if (typeof value === "string" || value instanceof String) {
|
|
2037
|
+
return "String";
|
|
2038
|
+
}
|
|
2039
|
+
if (value.bytes instanceof Uint8Array) {
|
|
2040
|
+
return "BinaryString";
|
|
2041
|
+
}
|
|
2042
|
+
return value.constructor && value.constructor.name ? value.constructor.name : typeof value;
|
|
2043
|
+
}
|
|
2044
|
+
function canonicalEncoding(name2) {
|
|
2045
|
+
const upper = String(name2 == null ? "UTF-8" : name2).toUpperCase().replace(/\s+/g, "");
|
|
2046
|
+
if (upper === "UTF-8" || upper === "UTF8") {
|
|
2047
|
+
return "utf8";
|
|
2048
|
+
}
|
|
2049
|
+
if (upper === "UTF-16" || upper === "UTF16" || upper === "UTF-16BE") {
|
|
2050
|
+
return "utf16";
|
|
2051
|
+
}
|
|
2052
|
+
if (upper === "UTF-32" || upper === "UTF32" || upper === "UTF-32BE") {
|
|
2053
|
+
return "utf32";
|
|
2054
|
+
}
|
|
2055
|
+
if (upper === "ISO-8859-1" || upper === "ISO8859-1" || upper === "LATIN-1" || upper === "LATIN1" || upper === "LATIN") {
|
|
2056
|
+
return "latin1";
|
|
2057
|
+
}
|
|
2058
|
+
return null;
|
|
2059
|
+
}
|
|
2060
|
+
function codePoints(text) {
|
|
2061
|
+
return Array.from(text, (ch) => ch.codePointAt(0));
|
|
2062
|
+
}
|
|
2063
|
+
function encode(value, encoding) {
|
|
2064
|
+
if (typeName2(value) !== "String") {
|
|
2065
|
+
throw new Error(`TypeException: encode expects String, got ${typeName2(value)}`);
|
|
2066
|
+
}
|
|
2067
|
+
const text = String(value);
|
|
2068
|
+
const codec = canonicalEncoding(encoding);
|
|
2069
|
+
if (codec === "utf8") {
|
|
2070
|
+
return new BinaryString2(new TextEncoder().encode(text));
|
|
2071
|
+
}
|
|
2072
|
+
if (codec === "utf16") {
|
|
2073
|
+
const out = [];
|
|
2074
|
+
for (let i = 0; i < text.length; i++) {
|
|
2075
|
+
const unit = text.charCodeAt(i);
|
|
2076
|
+
out.push(unit >> 8 & 255, unit & 255);
|
|
2077
|
+
}
|
|
2078
|
+
return new BinaryString2(out);
|
|
2079
|
+
}
|
|
2080
|
+
if (codec === "utf32") {
|
|
2081
|
+
const out = [];
|
|
2082
|
+
for (const point of codePoints(text)) {
|
|
2083
|
+
out.push(
|
|
2084
|
+
point >>> 24 & 255,
|
|
2085
|
+
point >>> 16 & 255,
|
|
2086
|
+
point >>> 8 & 255,
|
|
2087
|
+
point & 255
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
return new BinaryString2(out);
|
|
2091
|
+
}
|
|
2092
|
+
if (codec === "latin1") {
|
|
2093
|
+
const out = [];
|
|
2094
|
+
for (const point of codePoints(text)) {
|
|
2095
|
+
if (point > 255) {
|
|
2096
|
+
const hex = point.toString(16).toUpperCase().padStart(4, "0");
|
|
2097
|
+
throw new Error(`Exception: Character U+${hex} cannot be encoded as ISO-8859-1`);
|
|
2098
|
+
}
|
|
2099
|
+
out.push(point);
|
|
2100
|
+
}
|
|
2101
|
+
return new BinaryString2(out);
|
|
2102
|
+
}
|
|
2103
|
+
throw new Error(`Exception: Unsupported encoding: ${encoding}`);
|
|
2104
|
+
}
|
|
2105
|
+
function decode(value, encoding) {
|
|
2106
|
+
if (typeName2(value) !== "BinaryString") {
|
|
2107
|
+
throw new Error(`TypeException: decode expects BinaryString, got ${typeName2(value)}`);
|
|
2108
|
+
}
|
|
2109
|
+
let bytes = value.bytes;
|
|
2110
|
+
const codec = canonicalEncoding(encoding);
|
|
2111
|
+
if (codec === "utf8") {
|
|
2112
|
+
try {
|
|
2113
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
2114
|
+
} catch (_err) {
|
|
2115
|
+
throw new Error("Exception: Invalid UTF-8 in BinaryString");
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
if (codec === "utf16") {
|
|
2119
|
+
let bigEndian = true;
|
|
2120
|
+
if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
|
|
2121
|
+
bytes = bytes.subarray(2);
|
|
2122
|
+
} else if (bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 254) {
|
|
2123
|
+
bigEndian = false;
|
|
2124
|
+
bytes = bytes.subarray(2);
|
|
2125
|
+
}
|
|
2126
|
+
if (bytes.length % 2 !== 0) {
|
|
2127
|
+
throw new Error("Exception: UTF-16 input length must be a multiple of 2 bytes");
|
|
2128
|
+
}
|
|
2129
|
+
const units = [];
|
|
2130
|
+
for (let i = 0; i < bytes.length; i += 2) {
|
|
2131
|
+
units.push(bigEndian ? bytes[i] << 8 | bytes[i + 1] : bytes[i + 1] << 8 | bytes[i]);
|
|
2132
|
+
}
|
|
2133
|
+
let out = "";
|
|
2134
|
+
for (let i = 0; i < units.length; i++) {
|
|
2135
|
+
const unit = units[i];
|
|
2136
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
2137
|
+
const next = units[i + 1];
|
|
2138
|
+
if (next == null || next < 56320 || next > 57343) {
|
|
2139
|
+
throw new Error("Exception: Invalid UTF-16 in BinaryString");
|
|
2140
|
+
}
|
|
2141
|
+
out += String.fromCharCode(unit, next);
|
|
2142
|
+
i++;
|
|
2143
|
+
continue;
|
|
2144
|
+
}
|
|
2145
|
+
if (unit >= 56320 && unit <= 57343) {
|
|
2146
|
+
throw new Error("Exception: Invalid UTF-16 in BinaryString");
|
|
2147
|
+
}
|
|
2148
|
+
out += String.fromCharCode(unit);
|
|
2149
|
+
}
|
|
2150
|
+
return out;
|
|
2151
|
+
}
|
|
2152
|
+
if (codec === "utf32") {
|
|
2153
|
+
let bigEndian = true;
|
|
2154
|
+
if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 254 && bytes[3] === 255) {
|
|
2155
|
+
bytes = bytes.subarray(4);
|
|
2156
|
+
} else if (bytes.length >= 4 && bytes[0] === 255 && bytes[1] === 254 && bytes[2] === 0 && bytes[3] === 0) {
|
|
2157
|
+
bigEndian = false;
|
|
2158
|
+
bytes = bytes.subarray(4);
|
|
2159
|
+
}
|
|
2160
|
+
if (bytes.length % 4 !== 0) {
|
|
2161
|
+
throw new Error("Exception: UTF-32 input length must be a multiple of 4 bytes");
|
|
2162
|
+
}
|
|
2163
|
+
let out = "";
|
|
2164
|
+
for (let i = 0; i < bytes.length; i += 4) {
|
|
2165
|
+
const point = bigEndian ? bytes[i] * 16777216 + (bytes[i + 1] << 16) + (bytes[i + 2] << 8) + bytes[i + 3] : bytes[i + 3] * 16777216 + (bytes[i + 2] << 16) + (bytes[i + 1] << 8) + bytes[i];
|
|
2166
|
+
if (point > 1114111 || point >= 55296 && point <= 57343) {
|
|
2167
|
+
throw new Error("Exception: Invalid UTF-32 in BinaryString");
|
|
2168
|
+
}
|
|
2169
|
+
out += String.fromCodePoint(point);
|
|
2170
|
+
}
|
|
2171
|
+
return out;
|
|
2172
|
+
}
|
|
2173
|
+
if (codec === "latin1") {
|
|
2174
|
+
let out = "";
|
|
2175
|
+
for (const byte of bytes) {
|
|
2176
|
+
out += String.fromCharCode(byte);
|
|
2177
|
+
}
|
|
2178
|
+
return out;
|
|
2179
|
+
}
|
|
2180
|
+
throw new Error(`Exception: Unsupported encoding: ${encoding}`);
|
|
2181
|
+
}
|
|
2182
|
+
module2.exports = {
|
|
2183
|
+
encode,
|
|
2184
|
+
decode,
|
|
2185
|
+
ENCODING_UTF8: "UTF-8",
|
|
2186
|
+
ENCODING_UTF16: "UTF-16",
|
|
2187
|
+
ENCODING_UTF32: "UTF-32",
|
|
2188
|
+
ENCODING_LATIN: "ISO-8859-1"
|
|
2189
|
+
};
|
|
2190
|
+
}
|
|
2191
|
+
});
|
|
2192
|
+
|
|
1927
2193
|
// modules/std/time.js
|
|
1928
2194
|
var require_time = __commonJS({
|
|
1929
2195
|
"modules/std/time.js"(exports2, module2) {
|
|
@@ -1955,6 +2221,7 @@
|
|
|
1955
2221
|
["dec", 12],
|
|
1956
2222
|
["december", 12]
|
|
1957
2223
|
]);
|
|
2224
|
+
var DAY_ABBR = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
1958
2225
|
var WEEKDAY_BY_NAME = /* @__PURE__ */ new Set([
|
|
1959
2226
|
"sun",
|
|
1960
2227
|
"sunday",
|
|
@@ -2009,12 +2276,59 @@
|
|
|
2009
2276
|
const seconds = Number(m[2]) * 3600 + Number(m[3]) * 60;
|
|
2010
2277
|
return m[1] === "-" ? -seconds : seconds;
|
|
2011
2278
|
}
|
|
2012
|
-
function pad(value, width = 2) {
|
|
2013
|
-
return String(value).padStart(width,
|
|
2279
|
+
function pad(value, width = 2, fill = "0") {
|
|
2280
|
+
return String(value).padStart(width, fill);
|
|
2014
2281
|
}
|
|
2015
2282
|
function stripTrailingPeriod(text) {
|
|
2016
2283
|
return String(text).replace(/\.+$/u, "").toLowerCase();
|
|
2017
2284
|
}
|
|
2285
|
+
function weekdayIndex(parts) {
|
|
2286
|
+
const date = new Date(
|
|
2287
|
+
parts.year,
|
|
2288
|
+
parts.month - 1,
|
|
2289
|
+
parts.day
|
|
2290
|
+
);
|
|
2291
|
+
return (date.getDay() + 6) % 7 + 1;
|
|
2292
|
+
}
|
|
2293
|
+
function weekParts(parts) {
|
|
2294
|
+
const date = new Date(
|
|
2295
|
+
parts.year,
|
|
2296
|
+
parts.month - 1,
|
|
2297
|
+
parts.day
|
|
2298
|
+
);
|
|
2299
|
+
const weekDay = date.getDay() || 7;
|
|
2300
|
+
const shifted = new Date(date);
|
|
2301
|
+
shifted.setDate(date.getDate() + 4 - weekDay);
|
|
2302
|
+
const weekYear = shifted.getFullYear();
|
|
2303
|
+
const yearStart = new Date(weekYear, 0, 1);
|
|
2304
|
+
return {
|
|
2305
|
+
year: weekYear,
|
|
2306
|
+
week: Math.ceil((shifted - yearStart) / 864e5 / 7 + 1)
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
function dayOfMonthForDisplay(day) {
|
|
2310
|
+
return String(day).padStart(2, " ");
|
|
2311
|
+
}
|
|
2312
|
+
function dayOfYear(parts) {
|
|
2313
|
+
const start = new Date(parts.year, 0, 1);
|
|
2314
|
+
const now = new Date(parts.year, parts.month - 1, parts.day);
|
|
2315
|
+
return (now - start) / 864e5;
|
|
2316
|
+
}
|
|
2317
|
+
function julianDay(parts) {
|
|
2318
|
+
let year = parts.year;
|
|
2319
|
+
let month = parts.month;
|
|
2320
|
+
const day = parts.day;
|
|
2321
|
+
if (month <= 2) {
|
|
2322
|
+
year -= 1;
|
|
2323
|
+
month += 12;
|
|
2324
|
+
}
|
|
2325
|
+
const a = Math.floor((14 - month) / 12);
|
|
2326
|
+
const y = year + 4800 - a;
|
|
2327
|
+
const m = month + 12 * a - 3;
|
|
2328
|
+
const jd = day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) - 32045;
|
|
2329
|
+
const fraction = (parts.hour * 3600 + parts.minute * 60 + parts.second) / 86400;
|
|
2330
|
+
return jd + fraction - 0.5;
|
|
2331
|
+
}
|
|
2018
2332
|
function isLeapYear(year) {
|
|
2019
2333
|
if (year % 4 !== 0) return false;
|
|
2020
2334
|
if (year % 100 !== 0) return true;
|
|
@@ -2432,6 +2746,59 @@
|
|
|
2432
2746
|
year() {
|
|
2433
2747
|
return this._parts().year;
|
|
2434
2748
|
}
|
|
2749
|
+
yy() {
|
|
2750
|
+
return pad(this._parts().year % 100, 2);
|
|
2751
|
+
}
|
|
2752
|
+
day_of_week() {
|
|
2753
|
+
return weekdayIndex(this._parts());
|
|
2754
|
+
}
|
|
2755
|
+
day() {
|
|
2756
|
+
return DAY_ABBR[this.day_of_week() - 1];
|
|
2757
|
+
}
|
|
2758
|
+
day_of_year() {
|
|
2759
|
+
return dayOfYear(this._parts());
|
|
2760
|
+
}
|
|
2761
|
+
month_last_day() {
|
|
2762
|
+
return daysInMonth(this._parts().year, this._parts().month);
|
|
2763
|
+
}
|
|
2764
|
+
hms(separator = ":") {
|
|
2765
|
+
const p = this._parts();
|
|
2766
|
+
return `${pad(p.hour)}${String(separator)}${pad(p.minute)}${String(separator)}${pad(p.second)}`;
|
|
2767
|
+
}
|
|
2768
|
+
ymd(separator = "-") {
|
|
2769
|
+
const p = this._parts();
|
|
2770
|
+
const sep = String(separator);
|
|
2771
|
+
return `${pad(p.year, 4)}${sep}${pad(p.month)}${sep}${pad(p.day)}`;
|
|
2772
|
+
}
|
|
2773
|
+
mdy(separator = "-") {
|
|
2774
|
+
const p = this._parts();
|
|
2775
|
+
const sep = String(separator);
|
|
2776
|
+
return `${pad(p.month)}${sep}${pad(p.day)}${sep}${pad(p.year, 4)}`;
|
|
2777
|
+
}
|
|
2778
|
+
dmy(separator = "-") {
|
|
2779
|
+
const p = this._parts();
|
|
2780
|
+
const sep = String(separator);
|
|
2781
|
+
return `${pad(p.day)}${sep}${pad(p.month)}${sep}${pad(p.year, 4)}`;
|
|
2782
|
+
}
|
|
2783
|
+
cdate() {
|
|
2784
|
+
const p = this._parts();
|
|
2785
|
+
return `${DAY_ABBR[weekdayIndex(p) - 1]} ${MONTHS[p.month - 1]} ${dayOfMonthForDisplay(p.day)} ${pad(p.hour)}:${pad(p.minute)}:${pad(p.second)} ${p.year}`;
|
|
2786
|
+
}
|
|
2787
|
+
tzoffset() {
|
|
2788
|
+
return offsetForEpoch(this._epoch, this._timezone);
|
|
2789
|
+
}
|
|
2790
|
+
is_leap_year() {
|
|
2791
|
+
return isLeapYear(this._parts().year);
|
|
2792
|
+
}
|
|
2793
|
+
week() {
|
|
2794
|
+
return weekParts(this._parts()).week;
|
|
2795
|
+
}
|
|
2796
|
+
week_year() {
|
|
2797
|
+
return weekParts(this._parts()).year;
|
|
2798
|
+
}
|
|
2799
|
+
julian_day() {
|
|
2800
|
+
return julianDay(this._parts());
|
|
2801
|
+
}
|
|
2435
2802
|
add_seconds(n) {
|
|
2436
2803
|
return this._clone(this._epoch + Number(n));
|
|
2437
2804
|
}
|
|
@@ -2546,8 +2913,7 @@
|
|
|
2546
2913
|
}
|
|
2547
2914
|
to_rfc5322(options = {}) {
|
|
2548
2915
|
const p = this._parts();
|
|
2549
|
-
const
|
|
2550
|
-
const weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d.getUTCDay()];
|
|
2916
|
+
const weekday = DAY_ABBR[weekdayIndex(p) - 1];
|
|
2551
2917
|
const core = `${pad(p.day)} ${MONTHS[p.month - 1]} ${pad(p.year, 4)} ${pad(p.hour)}:${pad(p.minute)}:${pad(p.second)} ${formatOffset(offsetForEpoch(this._epoch, this._timezone), false)}`;
|
|
2552
2918
|
return options.include_weekday === false ? core : `${weekday}, ${core}`;
|
|
2553
2919
|
}
|
|
@@ -4119,6 +4485,33 @@
|
|
|
4119
4485
|
return `
|
|
4120
4486
|
//# sourceURL=${filename.replace(/[\r\n]/gu, "_")}`;
|
|
4121
4487
|
}
|
|
4488
|
+
var browserModuleUrls = /* @__PURE__ */ new Map();
|
|
4489
|
+
function _normalizeModuleName(value) {
|
|
4490
|
+
const name2 = String(value ?? "").trim().replace(/\\/gu, "/");
|
|
4491
|
+
if (name2 === "" || name2.startsWith("/") || name2.endsWith("/") || /(^|\/)\.\.?(\/|$)/u.test(name2)) {
|
|
4492
|
+
throw new Error(`Invalid browser module name: ${value}`);
|
|
4493
|
+
}
|
|
4494
|
+
return name2.replace(/\.zzm$/u, "");
|
|
4495
|
+
}
|
|
4496
|
+
function _moduleNameFromPath(filename) {
|
|
4497
|
+
const path = _resolvePath(filename);
|
|
4498
|
+
if (!path.startsWith("/modules/") || !path.endsWith(".zzm")) {
|
|
4499
|
+
return null;
|
|
4500
|
+
}
|
|
4501
|
+
return path.slice("/modules/".length, -".zzm".length);
|
|
4502
|
+
}
|
|
4503
|
+
function addBrowserModule(moduleName, url) {
|
|
4504
|
+
const logicalName = _normalizeModuleName(moduleName);
|
|
4505
|
+
const moduleUrl = String(url ?? "").trim();
|
|
4506
|
+
if (moduleUrl === "") {
|
|
4507
|
+
throw new Error(`Invalid URL for browser module '${logicalName}'`);
|
|
4508
|
+
}
|
|
4509
|
+
browserModuleUrls.set(logicalName, moduleUrl);
|
|
4510
|
+
return logicalName;
|
|
4511
|
+
}
|
|
4512
|
+
function hasBrowserModules() {
|
|
4513
|
+
return browserModuleUrls.size > 0;
|
|
4514
|
+
}
|
|
4122
4515
|
function _browserEval(source, context, runOptions = {}) {
|
|
4123
4516
|
context.globalThis = context;
|
|
4124
4517
|
const sourceUrl = _sourceUrlComment(runOptions);
|
|
@@ -4217,6 +4610,11 @@
|
|
|
4217
4610
|
const virtualFiles = new Map(Object.entries(options.virtualFiles || {}).map(([filename, source]) => [_resolvePath(filename), String(source)]));
|
|
4218
4611
|
const jsModules = new Map(Object.entries(options.jsModules || {}).map(([filename, loaded]) => [_resolvePath(filename), loaded]));
|
|
4219
4612
|
const fetchedFiles = /* @__PURE__ */ new Map();
|
|
4613
|
+
const fetchingFiles = /* @__PURE__ */ new Map();
|
|
4614
|
+
const optionModuleUrls = new Map(
|
|
4615
|
+
Object.entries(options.remoteModules || {}).map(([name2, url]) => [_normalizeModuleName(name2), String(url)])
|
|
4616
|
+
);
|
|
4617
|
+
const fetchText = typeof options.fetch === "function" ? options.fetch : typeof fetch === "function" ? fetch : null;
|
|
4220
4618
|
const fetchModule = typeof options.fetchModule === "function" ? options.fetchModule : null;
|
|
4221
4619
|
const runInContext = typeof options.evaluate === "function" ? options.evaluate : _browserEval;
|
|
4222
4620
|
const capabilities2 = /* @__PURE__ */ new Set([
|
|
@@ -4236,6 +4634,56 @@
|
|
|
4236
4634
|
capabilities2.add("worker");
|
|
4237
4635
|
}
|
|
4238
4636
|
const gui = _defaultGuiBridge(options);
|
|
4637
|
+
function browserModuleUrlForPath(filename) {
|
|
4638
|
+
const logicalName = _moduleNameFromPath(filename);
|
|
4639
|
+
if (!logicalName) {
|
|
4640
|
+
return null;
|
|
4641
|
+
}
|
|
4642
|
+
if (optionModuleUrls.has(logicalName)) {
|
|
4643
|
+
return optionModuleUrls.get(logicalName);
|
|
4644
|
+
}
|
|
4645
|
+
return browserModuleUrls.get(logicalName) || null;
|
|
4646
|
+
}
|
|
4647
|
+
function hasAsyncModules() {
|
|
4648
|
+
return optionModuleUrls.size > 0 || browserModuleUrls.size > 0;
|
|
4649
|
+
}
|
|
4650
|
+
async function fetchBrowserModule(key, url) {
|
|
4651
|
+
if (fetchedFiles.has(key)) {
|
|
4652
|
+
return fetchedFiles.get(key);
|
|
4653
|
+
}
|
|
4654
|
+
if (fetchingFiles.has(key)) {
|
|
4655
|
+
return fetchingFiles.get(key);
|
|
4656
|
+
}
|
|
4657
|
+
if (!fetchText) {
|
|
4658
|
+
throw new Error(`Exception: Browser host cannot fetch module '${key}'`);
|
|
4659
|
+
}
|
|
4660
|
+
const pending = Promise.resolve(fetchText(url)).then(async (response) => {
|
|
4661
|
+
if (typeof response === "string") {
|
|
4662
|
+
return response;
|
|
4663
|
+
}
|
|
4664
|
+
if (response && response.ok === false) {
|
|
4665
|
+
throw new Error(
|
|
4666
|
+
`Exception: Fetch failed for browser module '${key}' (${response.status})`
|
|
4667
|
+
);
|
|
4668
|
+
}
|
|
4669
|
+
if (!response || typeof response.text !== "function") {
|
|
4670
|
+
throw new Error(
|
|
4671
|
+
`Exception: Fetch did not return text for browser module '${key}'`
|
|
4672
|
+
);
|
|
4673
|
+
}
|
|
4674
|
+
return response.text();
|
|
4675
|
+
}).then((source) => {
|
|
4676
|
+
const text = String(source);
|
|
4677
|
+
fetchedFiles.set(key, text);
|
|
4678
|
+
fetchingFiles.delete(key);
|
|
4679
|
+
return text;
|
|
4680
|
+
}, (err) => {
|
|
4681
|
+
fetchingFiles.delete(key);
|
|
4682
|
+
throw err;
|
|
4683
|
+
});
|
|
4684
|
+
fetchingFiles.set(key, pending);
|
|
4685
|
+
return pending;
|
|
4686
|
+
}
|
|
4239
4687
|
return {
|
|
4240
4688
|
name: "browser",
|
|
4241
4689
|
repoRoot,
|
|
@@ -4272,13 +4720,33 @@
|
|
|
4272
4720
|
return fetched;
|
|
4273
4721
|
}
|
|
4274
4722
|
}
|
|
4723
|
+
if (browserModuleUrlForPath(key)) {
|
|
4724
|
+
throw new Error(`Exception: Browser module '${filename}' requires asynchronous loading`);
|
|
4725
|
+
}
|
|
4275
4726
|
throw new Error(`Exception: Browser host cannot read file '${filename}'`);
|
|
4276
4727
|
},
|
|
4728
|
+
async readFileTextAsync(filename) {
|
|
4729
|
+
const key = _resolvePath(filename);
|
|
4730
|
+
if (virtualFiles.has(key)) {
|
|
4731
|
+
return virtualFiles.get(key);
|
|
4732
|
+
}
|
|
4733
|
+
if (fetchedFiles.has(key)) {
|
|
4734
|
+
return fetchedFiles.get(key);
|
|
4735
|
+
}
|
|
4736
|
+
const browserModuleUrl = browserModuleUrlForPath(key);
|
|
4737
|
+
if (browserModuleUrl) {
|
|
4738
|
+
return fetchBrowserModule(key, browserModuleUrl);
|
|
4739
|
+
}
|
|
4740
|
+
return this.readFileText(key);
|
|
4741
|
+
},
|
|
4277
4742
|
fileExists(filename) {
|
|
4278
4743
|
const key = _resolvePath(filename);
|
|
4279
4744
|
if (virtualFiles.has(key) || jsModules.has(key) || fetchedFiles.has(key)) {
|
|
4280
4745
|
return true;
|
|
4281
4746
|
}
|
|
4747
|
+
if (browserModuleUrlForPath(key)) {
|
|
4748
|
+
return true;
|
|
4749
|
+
}
|
|
4282
4750
|
if (fetchModule) {
|
|
4283
4751
|
const fetched = fetchModule(key);
|
|
4284
4752
|
if (typeof fetched === "string") {
|
|
@@ -4312,11 +4780,14 @@
|
|
|
4312
4780
|
throw new Error(`Exception: Browser host has no JS module for '${filename}'`);
|
|
4313
4781
|
}
|
|
4314
4782
|
return jsModules.get(key);
|
|
4315
|
-
}
|
|
4783
|
+
},
|
|
4784
|
+
hasAsyncModules
|
|
4316
4785
|
};
|
|
4317
4786
|
}
|
|
4318
4787
|
module2.exports = {
|
|
4319
|
-
|
|
4788
|
+
addBrowserModule,
|
|
4789
|
+
createBrowserHost,
|
|
4790
|
+
hasBrowserModules
|
|
4320
4791
|
};
|
|
4321
4792
|
}
|
|
4322
4793
|
});
|
|
@@ -4469,6 +4940,10 @@
|
|
|
4469
4940
|
"or",
|
|
4470
4941
|
"xor",
|
|
4471
4942
|
"nand",
|
|
4943
|
+
"nor",
|
|
4944
|
+
"xnor",
|
|
4945
|
+
"onlyif",
|
|
4946
|
+
"butnot",
|
|
4472
4947
|
"not",
|
|
4473
4948
|
// TODO: Remove stale legacy JS-only words that are not current
|
|
4474
4949
|
// ZuzuScript keywords: contains, difference, elsif, export, foreach,
|
|
@@ -4544,6 +5019,7 @@
|
|
|
4544
5019
|
"throw",
|
|
4545
5020
|
"sub",
|
|
4546
5021
|
"union",
|
|
5022
|
+
"divides",
|
|
4547
5023
|
"intersection",
|
|
4548
5024
|
"difference",
|
|
4549
5025
|
"subsetof",
|
|
@@ -4552,6 +5028,31 @@
|
|
|
4552
5028
|
"contains"
|
|
4553
5029
|
]);
|
|
4554
5030
|
var SIMPLE_PUNCTUATION = /* @__PURE__ */ new Set(["(", ")", "{", "}", "[", "]", ",", ";", "."]);
|
|
5031
|
+
var VALUE_PRESERVING_LOGICAL_OPERATORS = /* @__PURE__ */ new Set([
|
|
5032
|
+
"and",
|
|
5033
|
+
"\u22C0",
|
|
5034
|
+
"or",
|
|
5035
|
+
"\u22C1",
|
|
5036
|
+
"xor",
|
|
5037
|
+
"\u22BB",
|
|
5038
|
+
"xnor",
|
|
5039
|
+
"\u2194",
|
|
5040
|
+
"nand",
|
|
5041
|
+
"\u22BC",
|
|
5042
|
+
"nor",
|
|
5043
|
+
"\u22BD",
|
|
5044
|
+
"onlyif",
|
|
5045
|
+
"\u22A8",
|
|
5046
|
+
"butnot",
|
|
5047
|
+
"\u22AD"
|
|
5048
|
+
]);
|
|
5049
|
+
function maybeValuePreservingOperator(value, peek, advance) {
|
|
5050
|
+
if (VALUE_PRESERVING_LOGICAL_OPERATORS.has(value) && peek() === "?") {
|
|
5051
|
+
advance();
|
|
5052
|
+
return `${value}?`;
|
|
5053
|
+
}
|
|
5054
|
+
return value;
|
|
5055
|
+
}
|
|
4555
5056
|
function decodeSimpleEscape(esc) {
|
|
4556
5057
|
switch (esc) {
|
|
4557
5058
|
case "n":
|
|
@@ -4823,7 +5324,30 @@
|
|
|
4823
5324
|
if (lastToken.type === "operator") {
|
|
4824
5325
|
return true;
|
|
4825
5326
|
}
|
|
4826
|
-
if (lastToken.type === "keyword" && [
|
|
5327
|
+
if (lastToken.type === "keyword" && [
|
|
5328
|
+
"return",
|
|
5329
|
+
"case",
|
|
5330
|
+
"if",
|
|
5331
|
+
"while",
|
|
5332
|
+
"throw",
|
|
5333
|
+
"and",
|
|
5334
|
+
"and?",
|
|
5335
|
+
"or",
|
|
5336
|
+
"or?",
|
|
5337
|
+
"xor",
|
|
5338
|
+
"xor?",
|
|
5339
|
+
"xnor",
|
|
5340
|
+
"xnor?",
|
|
5341
|
+
"nand",
|
|
5342
|
+
"nand?",
|
|
5343
|
+
"nor",
|
|
5344
|
+
"nor?",
|
|
5345
|
+
"onlyif",
|
|
5346
|
+
"onlyif?",
|
|
5347
|
+
"butnot",
|
|
5348
|
+
"butnot?",
|
|
5349
|
+
"not"
|
|
5350
|
+
].includes(lastToken.value)) {
|
|
4827
5351
|
return true;
|
|
4828
5352
|
}
|
|
4829
5353
|
return false;
|
|
@@ -5159,6 +5683,18 @@
|
|
|
5159
5683
|
continue;
|
|
5160
5684
|
}
|
|
5161
5685
|
if (isDigit(ch)) {
|
|
5686
|
+
const radixDigitOk = ch === "0" ? peek(1) === "x" ? (c) => /[0-9a-fA-F]/.test(c || "") : peek(1) === "b" ? (c) => c === "0" || c === "1" : peek(1) === "o" ? (c) => /[0-7]/.test(c || "") : null : null;
|
|
5687
|
+
if (radixDigitOk && radixDigitOk(peek(2))) {
|
|
5688
|
+
const radix = peek(1) === "x" ? 16 : peek(1) === "b" ? 2 : 8;
|
|
5689
|
+
advance();
|
|
5690
|
+
advance();
|
|
5691
|
+
let digits = "";
|
|
5692
|
+
while (radixDigitOk(peek())) {
|
|
5693
|
+
digits += advance();
|
|
5694
|
+
}
|
|
5695
|
+
addToken("number", String(parseInt(digits, radix)), start, cursor());
|
|
5696
|
+
continue;
|
|
5697
|
+
}
|
|
5162
5698
|
let value = "";
|
|
5163
5699
|
while (isDigit(peek())) {
|
|
5164
5700
|
value += advance();
|
|
@@ -5169,15 +5705,30 @@
|
|
|
5169
5705
|
value += advance();
|
|
5170
5706
|
}
|
|
5171
5707
|
}
|
|
5708
|
+
if (peek() === "E" && (isDigit(peek(1)) || (peek(1) === "+" || peek(1) === "-") && isDigit(peek(2)))) {
|
|
5709
|
+
value += advance();
|
|
5710
|
+
if (peek() === "+" || peek() === "-") {
|
|
5711
|
+
value += advance();
|
|
5712
|
+
}
|
|
5713
|
+
while (isDigit(peek())) {
|
|
5714
|
+
value += advance();
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5172
5717
|
addToken("number", value, start, cursor());
|
|
5173
5718
|
continue;
|
|
5174
5719
|
}
|
|
5720
|
+
if (ch === "\u22A4" || ch === "\u22A5") {
|
|
5721
|
+
advance();
|
|
5722
|
+
addToken("keyword", ch === "\u22A4" ? "true" : "false", start, cursor());
|
|
5723
|
+
continue;
|
|
5724
|
+
}
|
|
5175
5725
|
if (isIdentifierStart(ch)) {
|
|
5176
5726
|
let value = "";
|
|
5177
5727
|
while (isIdentifierPart(peek())) {
|
|
5178
5728
|
value += advance();
|
|
5179
5729
|
}
|
|
5180
5730
|
if (KEYWORDS.has(value)) {
|
|
5731
|
+
value = maybeValuePreservingOperator(value, peek, advance);
|
|
5181
5732
|
addToken("keyword", value, start, cursor());
|
|
5182
5733
|
} else {
|
|
5183
5734
|
addToken("identifier", value, start, cursor());
|
|
@@ -5189,12 +5740,13 @@
|
|
|
5189
5740
|
addToken("punctuation", ch, start, cursor());
|
|
5190
5741
|
continue;
|
|
5191
5742
|
}
|
|
5192
|
-
if (["+", "-", "*", "/", "%", "<", ">", "=", "_", "?", ":", "~", "!", "\\", "&", "|", "^", "@", "\xD7", "\xF7", "\xAC", "\u22C0", "\u22C1", "\u22BB", "\u22BC"].includes(ch)) {
|
|
5743
|
+
if (["+", "-", "*", "/", "%", "<", ">", "=", "_", "?", ":", "~", "!", "\\", "&", "|", "^", "@", "\xD7", "\xF7", "\xAC", "\u22C0", "\u22C1", "\u22BB", "\u22BC", "\u22BD", "\u2194", "\u22A8", "\u22AD"].includes(ch)) {
|
|
5193
5744
|
advance();
|
|
5194
|
-
|
|
5745
|
+
const value = maybeValuePreservingOperator(ch, peek, advance);
|
|
5746
|
+
addToken("operator", value, start, cursor());
|
|
5195
5747
|
continue;
|
|
5196
5748
|
}
|
|
5197
|
-
if (["\u2261", "\u2262", "\u2260", "\u2264", "\u2265", "\u2192", "\u221A", "\u230A", "\u230B", "\u2308", "\u2309", "\u2208", "\u2209", "\u22C3", "\u22C2", "\u2216", "\u2282", "\u2283", "\xAB", "\xBB", "\u2276", "\u2277", "\u25B7", "\u25C1"].includes(ch)) {
|
|
5749
|
+
if (["\u2261", "\u2262", "\u2260", "\u2264", "\u2265", "\u2192", "\u221A", "\u230A", "\u230B", "\u2308", "\u2309", "\u2208", "\u2209", "\u22C3", "\u22C2", "\u2216", "\u2282", "\u2283", "\xAB", "\xBB", "\u2276", "\u2277", "\u25B7", "\u25C1", "\u2223", "\u2224"].includes(ch)) {
|
|
5198
5750
|
advance();
|
|
5199
5751
|
addToken("operator", ch, start, cursor());
|
|
5200
5752
|
continue;
|
|
@@ -5252,6 +5804,7 @@
|
|
|
5252
5804
|
UnsupportedSyntaxError
|
|
5253
5805
|
} = require_errors();
|
|
5254
5806
|
function parse(tokens, options = {}) {
|
|
5807
|
+
const pendingSetClosers = [];
|
|
5255
5808
|
let index = 0;
|
|
5256
5809
|
let asyncContextDepth = 1;
|
|
5257
5810
|
function startLocFromToken(token) {
|
|
@@ -6181,11 +6734,11 @@
|
|
|
6181
6734
|
let comparator = "==";
|
|
6182
6735
|
if (match("operator", ":")) {
|
|
6183
6736
|
const token = current();
|
|
6184
|
-
|
|
6737
|
+
const operator = parseSwitchComparator();
|
|
6738
|
+
if (!operator) {
|
|
6185
6739
|
throw new TranspilerSyntaxError("Expected switch comparator after :", token);
|
|
6186
6740
|
}
|
|
6187
|
-
|
|
6188
|
-
comparator = token.value;
|
|
6741
|
+
comparator = operator;
|
|
6189
6742
|
}
|
|
6190
6743
|
expect("punctuation", ")", "Expected ) after switch header");
|
|
6191
6744
|
expect("punctuation", "{", "Expected { to start switch body");
|
|
@@ -6219,18 +6772,97 @@
|
|
|
6219
6772
|
}
|
|
6220
6773
|
function parseSwitchCase() {
|
|
6221
6774
|
const start = expect("keyword", "case");
|
|
6222
|
-
const
|
|
6775
|
+
const first = parseSwitchCaseValue();
|
|
6776
|
+
const values = [first.value];
|
|
6777
|
+
const operators = [first.operator];
|
|
6223
6778
|
while (match("punctuation", ",")) {
|
|
6224
|
-
|
|
6779
|
+
const item = parseSwitchCaseValue();
|
|
6780
|
+
values.push(item.value);
|
|
6781
|
+
operators.push(item.operator);
|
|
6225
6782
|
}
|
|
6226
6783
|
expect("operator", ":", "Expected : after switch case");
|
|
6227
6784
|
const consequent = parseSwitchConsequent(start);
|
|
6228
6785
|
return withLoc({
|
|
6229
6786
|
type: "SwitchCase",
|
|
6230
6787
|
values,
|
|
6788
|
+
operators,
|
|
6231
6789
|
consequent
|
|
6232
6790
|
}, start, endLocFromNode(consequent));
|
|
6233
6791
|
}
|
|
6792
|
+
function parseSwitchCaseValue() {
|
|
6793
|
+
const operator = parseSwitchComparator();
|
|
6794
|
+
return {
|
|
6795
|
+
operator,
|
|
6796
|
+
value: parseExpression()
|
|
6797
|
+
};
|
|
6798
|
+
}
|
|
6799
|
+
function parseSwitchComparator() {
|
|
6800
|
+
if (!isSwitchComparatorToken(current())) {
|
|
6801
|
+
return null;
|
|
6802
|
+
}
|
|
6803
|
+
const operator = current().value;
|
|
6804
|
+
index++;
|
|
6805
|
+
return operator;
|
|
6806
|
+
}
|
|
6807
|
+
function isSwitchComparatorToken(token) {
|
|
6808
|
+
if (!token) {
|
|
6809
|
+
return false;
|
|
6810
|
+
}
|
|
6811
|
+
if (token.type === "identifier" && token.value === "instanceof") {
|
|
6812
|
+
return true;
|
|
6813
|
+
}
|
|
6814
|
+
if (token.type !== "operator" && token.type !== "keyword") {
|
|
6815
|
+
return false;
|
|
6816
|
+
}
|
|
6817
|
+
return [
|
|
6818
|
+
">",
|
|
6819
|
+
"<",
|
|
6820
|
+
">=",
|
|
6821
|
+
"\u2264",
|
|
6822
|
+
"<=",
|
|
6823
|
+
"\u2265",
|
|
6824
|
+
"=",
|
|
6825
|
+
"!=",
|
|
6826
|
+
"\u2260",
|
|
6827
|
+
"==",
|
|
6828
|
+
"\u2261",
|
|
6829
|
+
"\u2262",
|
|
6830
|
+
"<=>",
|
|
6831
|
+
"\u2276",
|
|
6832
|
+
"\u2277",
|
|
6833
|
+
"eq",
|
|
6834
|
+
"ne",
|
|
6835
|
+
"gt",
|
|
6836
|
+
"ge",
|
|
6837
|
+
"lt",
|
|
6838
|
+
"le",
|
|
6839
|
+
"cmp",
|
|
6840
|
+
"eqi",
|
|
6841
|
+
"nei",
|
|
6842
|
+
"gti",
|
|
6843
|
+
"gei",
|
|
6844
|
+
"lti",
|
|
6845
|
+
"lei",
|
|
6846
|
+
"cmpi",
|
|
6847
|
+
"in",
|
|
6848
|
+
"\u2208",
|
|
6849
|
+
"not_in",
|
|
6850
|
+
"\u2209",
|
|
6851
|
+
"subsetof",
|
|
6852
|
+
"\u2282",
|
|
6853
|
+
"supersetof",
|
|
6854
|
+
"\u2283",
|
|
6855
|
+
"equivalentof",
|
|
6856
|
+
"\u2282\u2283",
|
|
6857
|
+
"does",
|
|
6858
|
+
"can",
|
|
6859
|
+
"~",
|
|
6860
|
+
"@?",
|
|
6861
|
+
"\u2223",
|
|
6862
|
+
"divides",
|
|
6863
|
+
"\u2224"
|
|
6864
|
+
].includes(token.value);
|
|
6865
|
+
}
|
|
6234
6866
|
function parseSwitchDefaultCase() {
|
|
6235
6867
|
const start = expect("keyword", "default");
|
|
6236
6868
|
expect("operator", ":", "Expected : after default");
|
|
@@ -6617,15 +7249,27 @@
|
|
|
6617
7249
|
}, startLocFromNode(left), endLocFromNode(right));
|
|
6618
7250
|
}
|
|
6619
7251
|
function parseLogicalOr() {
|
|
7252
|
+
return parseLeftAssociative(
|
|
7253
|
+
parseOnlyif,
|
|
7254
|
+
(token) => token.type === "keyword" && ["or", "or?"].includes(token.value) || token.type === "operator" && ["\u22C1", "\u22C1?"].includes(token.value)
|
|
7255
|
+
);
|
|
7256
|
+
}
|
|
7257
|
+
function parseOnlyif() {
|
|
7258
|
+
return parseRightAssociative(
|
|
7259
|
+
parseLogicalXor,
|
|
7260
|
+
(token) => token.type === "keyword" && ["onlyif", "onlyif?"].includes(token.value) || token.type === "operator" && ["\u22A8", "\u22A8?"].includes(token.value)
|
|
7261
|
+
);
|
|
7262
|
+
}
|
|
7263
|
+
function parseLogicalXor() {
|
|
6620
7264
|
return parseLeftAssociative(
|
|
6621
7265
|
parseLogicalAnd,
|
|
6622
|
-
(token) => token.type === "keyword" && ["
|
|
7266
|
+
(token) => token.type === "keyword" && ["xor", "xor?", "nor", "nor?", "xnor", "xnor?"].includes(token.value) || token.type === "operator" && ["\u22BB", "\u22BB?", "\u22BD", "\u22BD?", "\u2194", "\u2194?"].includes(token.value)
|
|
6623
7267
|
);
|
|
6624
7268
|
}
|
|
6625
7269
|
function parseLogicalAnd() {
|
|
6626
7270
|
return parseLeftAssociative(
|
|
6627
7271
|
parseEquality,
|
|
6628
|
-
(token) => token.type === "keyword" &&
|
|
7272
|
+
(token) => token.type === "keyword" && ["and", "and?", "nand", "nand?", "butnot", "butnot?"].includes(token.value) || token.type === "operator" && ["\u22C0", "\u22C0?", "\u22BC", "\u22BC?", "\u22AD", "\u22AD?"].includes(token.value)
|
|
6629
7273
|
);
|
|
6630
7274
|
}
|
|
6631
7275
|
function parseEquality() {
|
|
@@ -6636,14 +7280,20 @@
|
|
|
6636
7280
|
}
|
|
6637
7281
|
function parseBitwise() {
|
|
6638
7282
|
return parseLeftAssociative(
|
|
6639
|
-
|
|
7283
|
+
parseShift,
|
|
6640
7284
|
(token) => token.type === "operator" && ["&", "|", "^"].includes(token.value)
|
|
6641
7285
|
);
|
|
6642
7286
|
}
|
|
7287
|
+
function parseShift() {
|
|
7288
|
+
return parseLeftAssociative(
|
|
7289
|
+
parseComparison,
|
|
7290
|
+
(token) => token.type === "operator" && ["<<", ">>", "\xAB", "\xBB"].includes(token.value) && token.value !== pendingSetClosers[pendingSetClosers.length - 1]
|
|
7291
|
+
);
|
|
7292
|
+
}
|
|
6643
7293
|
function parseComparison() {
|
|
6644
7294
|
return parseLeftAssociative(
|
|
6645
7295
|
parseRange,
|
|
6646
|
-
(token) => token.type === "operator" && ["<", "<=", ">", ">=", "\u2264", "\u2265", "~", "<=>", "@", "@@", "@?", "\\", "\u2208", "\u2209", "\u22C3", "\u22C2", "\u2216", "\u2282", "\u2283", "\u2282\u2283", "\u2276", "\u2277"].includes(token.value) || token.type === "keyword" && ["gt", "ge", "lt", "le", "cmp", "eqi", "nei", "gti", "gei", "lti", "lei", "cmpi", "in", "not_in", "union", "intersection", "difference", "subsetof", "supersetof", "equivalentof", "does", "can"].includes(token.value) || token.type === "identifier" && token.value === "instanceof"
|
|
7296
|
+
(token) => token.type === "operator" && ["<", "<=", ">", ">=", "\u2264", "\u2265", "~", "<=>", "@", "@@", "@?", "\\", "\u2208", "\u2209", "\u22C3", "\u22C2", "\u2216", "\u2282", "\u2283", "\u2282\u2283", "\u2276", "\u2277", "\u2223", "\u2224"].includes(token.value) || token.type === "keyword" && ["gt", "ge", "lt", "le", "cmp", "eqi", "nei", "gti", "gei", "lti", "lei", "cmpi", "in", "not_in", "union", "intersection", "difference", "subsetof", "supersetof", "equivalentof", "does", "can", "divides"].includes(token.value) || token.type === "identifier" && token.value === "instanceof"
|
|
6647
7297
|
);
|
|
6648
7298
|
}
|
|
6649
7299
|
function parseRange() {
|
|
@@ -6679,6 +7329,21 @@
|
|
|
6679
7329
|
}
|
|
6680
7330
|
return expr;
|
|
6681
7331
|
}
|
|
7332
|
+
function parseRightAssociative(nextFn, predicate) {
|
|
7333
|
+
const left = nextFn();
|
|
7334
|
+
if (!predicate(current())) {
|
|
7335
|
+
return left;
|
|
7336
|
+
}
|
|
7337
|
+
const op = current();
|
|
7338
|
+
index++;
|
|
7339
|
+
const right = parseRightAssociative(nextFn, predicate);
|
|
7340
|
+
return withLoc({
|
|
7341
|
+
type: "BinaryExpression",
|
|
7342
|
+
operator: op.value,
|
|
7343
|
+
left,
|
|
7344
|
+
right
|
|
7345
|
+
}, startLocFromNode(left), endLocFromNode(right));
|
|
7346
|
+
}
|
|
6682
7347
|
function parseUnary() {
|
|
6683
7348
|
if (current().type === "operator" && ["-", "+", "++", "--", "!", "~", "\\", "\u221A", "\xAC"].includes(current().value) || current().type === "keyword" && ["not", "typeof", "abs", "sqrt", "floor", "ceil", "round", "int", "length", "uc", "lc"].includes(current().value)) {
|
|
6684
7349
|
const op = current();
|
|
@@ -6862,6 +7527,17 @@
|
|
|
6862
7527
|
argument
|
|
6863
7528
|
}, start, endLocFromNode(argument));
|
|
6864
7529
|
}
|
|
7530
|
+
if (startsNamedKeyBeforeColon()) {
|
|
7531
|
+
const normalized = parseNamedKeyBeforeColon();
|
|
7532
|
+
expect("operator", ":", "Expected : in named argument");
|
|
7533
|
+
const value = parseExpression();
|
|
7534
|
+
return withLoc({
|
|
7535
|
+
type: "NamedArgument",
|
|
7536
|
+
key: normalized.key,
|
|
7537
|
+
keyExpr: normalized.keyExpr,
|
|
7538
|
+
value
|
|
7539
|
+
}, startLocFromNode(normalized.keyExpr), previous());
|
|
7540
|
+
}
|
|
6865
7541
|
const expr = parseExpression();
|
|
6866
7542
|
if (current().type === "keyword" && current().value === "but") {
|
|
6867
7543
|
throw new TranspilerSyntaxError(
|
|
@@ -6882,6 +7558,20 @@
|
|
|
6882
7558
|
}
|
|
6883
7559
|
return expr;
|
|
6884
7560
|
}
|
|
7561
|
+
function startsNamedKeyBeforeColon() {
|
|
7562
|
+
return ["identifier", "keyword", "string"].includes(current().type) && peekToken().type === "operator" && peekToken().value === ":";
|
|
7563
|
+
}
|
|
7564
|
+
function parseNamedKeyBeforeColon() {
|
|
7565
|
+
const token = current();
|
|
7566
|
+
index++;
|
|
7567
|
+
return {
|
|
7568
|
+
key: token.value,
|
|
7569
|
+
keyExpr: withLoc({
|
|
7570
|
+
type: "StringLiteral",
|
|
7571
|
+
value: token.value
|
|
7572
|
+
}, token, token)
|
|
7573
|
+
};
|
|
7574
|
+
}
|
|
6885
7575
|
function normalizeNamedArgumentKey(expr) {
|
|
6886
7576
|
if (expr.type === "Identifier") {
|
|
6887
7577
|
return {
|
|
@@ -7150,9 +7840,10 @@
|
|
|
7150
7840
|
break;
|
|
7151
7841
|
}
|
|
7152
7842
|
const start = current();
|
|
7153
|
-
const
|
|
7843
|
+
const literalKey = startsNamedKeyBeforeColon() ? parseNamedKeyBeforeColon() : null;
|
|
7844
|
+
const keyExpr = literalKey ? literalKey.keyExpr : parseExpression();
|
|
7154
7845
|
if (current().type === "operator" && current().value === ":") {
|
|
7155
|
-
const normalized = normalizeNamedArgumentKey(keyExpr);
|
|
7846
|
+
const normalized = literalKey || normalizeNamedArgumentKey(keyExpr);
|
|
7156
7847
|
expect("operator", ":", "Expected : in pairlist literal");
|
|
7157
7848
|
const value = parseExpression();
|
|
7158
7849
|
entries.push(withLoc({
|
|
@@ -7286,18 +7977,23 @@
|
|
|
7286
7977
|
if (match("operator", closer)) {
|
|
7287
7978
|
return elements;
|
|
7288
7979
|
}
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7980
|
+
pendingSetClosers.push(closer);
|
|
7981
|
+
try {
|
|
7982
|
+
while (true) {
|
|
7983
|
+
if (match("punctuation", ",")) {
|
|
7984
|
+
continue;
|
|
7985
|
+
}
|
|
7986
|
+
if (match("operator", closer)) {
|
|
7987
|
+
break;
|
|
7988
|
+
}
|
|
7989
|
+
elements.push(parseExpression());
|
|
7990
|
+
if (match("operator", closer)) {
|
|
7991
|
+
break;
|
|
7992
|
+
}
|
|
7993
|
+
match("punctuation", ",");
|
|
7299
7994
|
}
|
|
7300
|
-
|
|
7995
|
+
} finally {
|
|
7996
|
+
pendingSetClosers.pop();
|
|
7301
7997
|
}
|
|
7302
7998
|
return elements;
|
|
7303
7999
|
}
|
|
@@ -7378,8 +8074,8 @@
|
|
|
7378
8074
|
function emitProgram(ast, options = {}) {
|
|
7379
8075
|
loopCounter = 0;
|
|
7380
8076
|
chainCounter = 0;
|
|
7381
|
-
const needsAsyncWrapper = programNeedsAsyncWrapper(ast);
|
|
7382
8077
|
const syncEval = options.syncEval === true;
|
|
8078
|
+
const needsAsyncWrapper = programNeedsAsyncWrapper(ast) || options.asyncImports === true && !syncEval && programContainsImport(ast);
|
|
7383
8079
|
const expressionDeclaredNames = collectExpressionDeclaredNames(ast.body);
|
|
7384
8080
|
const sharedOptions = {
|
|
7385
8081
|
...options,
|
|
@@ -7405,7 +8101,7 @@ ${emitExpressionBlock({ body: ast.body }, sharedOptions)}
|
|
|
7405
8101
|
})).join("\n");
|
|
7406
8102
|
const prelude = emitPredeclaredNames(expressionDeclaredNames);
|
|
7407
8103
|
const source = [prelude, body].filter(Boolean).join("\n");
|
|
7408
|
-
if (needsAsyncWrapper && !syncEval) {
|
|
8104
|
+
if (needsAsyncWrapper && !syncEval && options.deferAsyncWrapper !== true) {
|
|
7409
8105
|
return `( async () => {
|
|
7410
8106
|
${source}
|
|
7411
8107
|
} )()`;
|
|
@@ -8162,14 +8858,19 @@ globalThis[${JSON.stringify(node.id.name)}] = ${name2};` : declaration;
|
|
|
8162
8858
|
return `try ${emitBlock(node.block, options)} catch ( __zuzu_err ) { ${catchBody} }`;
|
|
8163
8859
|
}
|
|
8164
8860
|
function emitImportDeclaration(node, options = {}) {
|
|
8861
|
+
const asyncImport = options.asyncImports === true && options.syncEval !== true;
|
|
8862
|
+
const importModule = () => {
|
|
8863
|
+
const call = `__zuzu_import( ${JSON.stringify(node.source)} )`;
|
|
8864
|
+
return asyncImport ? `await ${call}` : call;
|
|
8865
|
+
};
|
|
8165
8866
|
if (node.importAll) {
|
|
8166
8867
|
if (options.syncEval) {
|
|
8167
8868
|
return `{ const __zuzu_star = __zuzu_import( ${JSON.stringify(node.source)} ); }`;
|
|
8168
8869
|
}
|
|
8169
8870
|
if (node.source === "std/eval") {
|
|
8170
|
-
return `{ const __zuzu_star =
|
|
8871
|
+
return `{ const __zuzu_star = ${importModule()}; for ( const __zuzu_key of Object.keys( __zuzu_star ) ) { if ( __zuzu_key === "eval" ) { continue; } const __zuzu_desc = Object.create( null ); __zuzu_desc.configurable = true; __zuzu_desc.enumerable = true; __zuzu_desc.get = function() { return __zuzu_star[ __zuzu_key ] ?? null; }; __zuzu_desc.set = function( value ) { __zuzu_star[ __zuzu_key ] = value; }; Object.defineProperty( globalThis, __zuzu_key, __zuzu_desc ); } }`;
|
|
8171
8872
|
}
|
|
8172
|
-
return `{ const __zuzu_star =
|
|
8873
|
+
return `{ const __zuzu_star = ${importModule()}; if ( Object.prototype.hasOwnProperty.call( __zuzu_star, "done_testing" ) ) { var done_testing = __zuzu_star.done_testing ?? null; } for ( const __zuzu_key of Object.keys( __zuzu_star ) ) { if ( __zuzu_key === "done_testing" ) { continue; } const __zuzu_desc = Object.create( null ); __zuzu_desc.configurable = true; __zuzu_desc.enumerable = true; __zuzu_desc.get = function() { return __zuzu_star[ __zuzu_key ] ?? null; }; __zuzu_desc.set = function( value ) { __zuzu_star[ __zuzu_key ] = value; }; Object.defineProperty( globalThis, __zuzu_key, __zuzu_desc ); } }`;
|
|
8173
8874
|
}
|
|
8174
8875
|
const moduleName = `__zuzu_imported_${Math.abs(hashString(node.source))}_${node.specifiers.length}_${options.syncEval ? loopCounter++ : 0}`;
|
|
8175
8876
|
const defineImports = node.specifiers.map((specifier) => {
|
|
@@ -8218,6 +8919,22 @@ globalThis[${JSON.stringify(node.id.name)}] = ${name2};` : declaration;
|
|
|
8218
8919
|
return `const ${moduleName} = __zuzu_import( ${JSON.stringify(node.source)} ); ${defineImports.join(" ")}`;
|
|
8219
8920
|
}
|
|
8220
8921
|
if (node.tryMode) {
|
|
8922
|
+
if (asyncImport) {
|
|
8923
|
+
return [
|
|
8924
|
+
`{ ${legacyShape} const ${moduleName} = await ( async () => {`,
|
|
8925
|
+
"try {",
|
|
8926
|
+
importCondition ? `if ( !( ${importCondition} ) ) { return {}; }` : "",
|
|
8927
|
+
`return ${importModule()};`,
|
|
8928
|
+
"}",
|
|
8929
|
+
"catch ( __zuzu_err ) {",
|
|
8930
|
+
"if ( __zuzu_err && __zuzu_err.__zuzu_nonlocal_return ) { throw __zuzu_err; }",
|
|
8931
|
+
"return {};",
|
|
8932
|
+
"}",
|
|
8933
|
+
"} )();",
|
|
8934
|
+
...defineImports,
|
|
8935
|
+
"}"
|
|
8936
|
+
].filter(Boolean).join(" ");
|
|
8937
|
+
}
|
|
8221
8938
|
return [
|
|
8222
8939
|
`{ ${legacyShape} const ${moduleName} = ( () => {`,
|
|
8223
8940
|
"try {",
|
|
@@ -8234,6 +8951,16 @@ globalThis[${JSON.stringify(node.id.name)}] = ${name2};` : declaration;
|
|
|
8234
8951
|
].filter(Boolean).join(" ");
|
|
8235
8952
|
}
|
|
8236
8953
|
if (importCondition) {
|
|
8954
|
+
if (asyncImport) {
|
|
8955
|
+
return [
|
|
8956
|
+
`{ ${legacyShape} const ${moduleName} = await ( async () => {`,
|
|
8957
|
+
`if ( !( ${importCondition} ) ) { return ${disabledImports}; }`,
|
|
8958
|
+
`return ${importModule()};`,
|
|
8959
|
+
"} )();",
|
|
8960
|
+
...defineImports,
|
|
8961
|
+
"}"
|
|
8962
|
+
].join(" ");
|
|
8963
|
+
}
|
|
8237
8964
|
return [
|
|
8238
8965
|
`{ ${legacyShape} const ${moduleName} = ( () => {`,
|
|
8239
8966
|
`if ( !( ${importCondition} ) ) { return ${disabledImports}; }`,
|
|
@@ -8243,7 +8970,7 @@ globalThis[${JSON.stringify(node.id.name)}] = ${name2};` : declaration;
|
|
|
8243
8970
|
"}"
|
|
8244
8971
|
].join(" ");
|
|
8245
8972
|
}
|
|
8246
|
-
return `{ ${legacyShape} const ${moduleName} =
|
|
8973
|
+
return `{ ${legacyShape} const ${moduleName} = ${importModule()}; ${defineImports.join(" ")} }`;
|
|
8247
8974
|
}
|
|
8248
8975
|
function normalizeImportedName(source, imported) {
|
|
8249
8976
|
return source === "std/math" && imported === "pi" ? "\u03C0" : imported;
|
|
@@ -8542,7 +9269,7 @@ ${cleanup}
|
|
|
8542
9269
|
}
|
|
8543
9270
|
function emitSwitchStatement(node, options = {}) {
|
|
8544
9271
|
if (options.asyncContext && !options.syncEval) {
|
|
8545
|
-
const cases2 = node.cases.map((section) => `{
|
|
9272
|
+
const cases2 = node.cases.map((section) => `{ tests: [ ${section.values.map((value, index) => `async function( __zuzu_switch_value ) { return __zuzu_truthy( ${emitSwitchTestExpression(section, index, node.comparator)} ); }`).join(", ")} ], body: async function() ${emitBlock(section.consequent, {
|
|
8546
9273
|
...options,
|
|
8547
9274
|
inSwitchSection: true,
|
|
8548
9275
|
loopDepth: 0
|
|
@@ -8555,7 +9282,7 @@ ${cleanup}
|
|
|
8555
9282
|
const tail2 = switchStatementContainsReturn(node) ? options.inSwitchSection ? "if ( __zuzu_switch_result && __zuzu_switch_result.__zuzu_return ) { return __zuzu_switch_result; }" : "if ( __zuzu_switch_result && __zuzu_switch_result.__zuzu_return ) { return __zuzu_switch_result.value; }" : "";
|
|
8556
9283
|
return `{ let __zuzu_switch_result = await __zuzu_switch_async( ${emitExpression(node.discriminant)}, ${JSON.stringify(node.comparator)}, [ ${cases2.join(", ")} ], ${defaultBody2} ); ${tail2} }`;
|
|
8557
9284
|
}
|
|
8558
|
-
const cases = node.cases.map((section) => `{
|
|
9285
|
+
const cases = node.cases.map((section) => `{ tests: [ ${section.values.map((value, index) => `function( __zuzu_switch_value ) { return __zuzu_truthy( ${emitSwitchTestExpression(section, index, node.comparator)} ); }`).join(", ")} ], body: function() ${emitBlock(section.consequent, {
|
|
8559
9286
|
...options,
|
|
8560
9287
|
inSwitchSection: true,
|
|
8561
9288
|
loopDepth: 0
|
|
@@ -8568,6 +9295,19 @@ ${cleanup}
|
|
|
8568
9295
|
const tail = switchStatementContainsReturn(node) ? options.inSwitchSection ? "if ( __zuzu_switch_result && __zuzu_switch_result.__zuzu_return ) { return __zuzu_switch_result; }" : "if ( __zuzu_switch_result && __zuzu_switch_result.__zuzu_return ) { return __zuzu_switch_result.value; }" : "";
|
|
8569
9296
|
return `{ let __zuzu_switch_result = __zuzu_switch( ${emitExpression(node.discriminant)}, ${JSON.stringify(node.comparator)}, [ ${cases.join(", ")} ], ${defaultBody} ); ${tail} }`;
|
|
8570
9297
|
}
|
|
9298
|
+
function emitSwitchTestExpression(section, index, defaultComparator) {
|
|
9299
|
+
const right = section.values[index];
|
|
9300
|
+
const operator = section.operators && section.operators[index] || defaultComparator || "==";
|
|
9301
|
+
return emitBinaryExpression({
|
|
9302
|
+
type: "BinaryExpression",
|
|
9303
|
+
operator,
|
|
9304
|
+
left: {
|
|
9305
|
+
type: "Identifier",
|
|
9306
|
+
name: "__zuzu_switch_value"
|
|
9307
|
+
},
|
|
9308
|
+
right
|
|
9309
|
+
});
|
|
9310
|
+
}
|
|
8571
9311
|
function emitTraitDeclaration(node, options = {}) {
|
|
8572
9312
|
const methods = completeMethodDeclarations(node.body || []).map((method) => {
|
|
8573
9313
|
const value = emitMethodFunction(method, {
|
|
@@ -8869,13 +9609,17 @@ ${cleanup}
|
|
|
8869
9609
|
source = `await __zuzu_collection_${method}_async( ${object}, ${args} )`;
|
|
8870
9610
|
} else if (node.arguments.length === 0) {
|
|
8871
9611
|
const object = emitExpression(node.callee.object);
|
|
8872
|
-
|
|
8873
|
-
|
|
9612
|
+
if (node.callee.computed) {
|
|
9613
|
+
const property = node.callee.property.type === "BraceIdentifier" ? `__zuzu_resolve_brace_key( __zuzu_receiver, ${JSON.stringify(node.callee.property.name)}, () => ${node.callee.property.name} )` : emitExpression(node.callee.property);
|
|
9614
|
+
source = `( () => { const __zuzu_receiver = ${object}; return __zuzu_call_member( __zuzu_receiver, ${property} ); } )()`;
|
|
9615
|
+
} else {
|
|
9616
|
+
source = `__zuzu_call_member( ${object}, ${JSON.stringify(node.callee.property.name)} )`;
|
|
9617
|
+
}
|
|
8874
9618
|
} else {
|
|
8875
9619
|
const object = emitExpression(node.callee.object);
|
|
8876
9620
|
if (node.callee.computed) {
|
|
8877
|
-
const property = node.callee.property.type === "BraceIdentifier" ? `__zuzu_resolve_brace_key(
|
|
8878
|
-
source = `
|
|
9621
|
+
const property = node.callee.property.type === "BraceIdentifier" ? `__zuzu_resolve_brace_key( __zuzu_receiver, ${JSON.stringify(node.callee.property.name)}, () => ${node.callee.property.name} )` : emitExpression(node.callee.property);
|
|
9622
|
+
source = `( () => { const __zuzu_receiver = ${object}; return __zuzu_call_member( __zuzu_receiver, ${property}, ${args} ); } )()`;
|
|
8879
9623
|
} else {
|
|
8880
9624
|
source = `__zuzu_call_member( ${object}, ${JSON.stringify(node.callee.property.name)}, ${args} )`;
|
|
8881
9625
|
}
|
|
@@ -9058,16 +9802,52 @@ ${cleanup}
|
|
|
9058
9802
|
switch (node.operator) {
|
|
9059
9803
|
case "and":
|
|
9060
9804
|
case "\u22C0":
|
|
9061
|
-
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ?
|
|
9805
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? __zuzu_truthy( ${right} ) : false; } )()`;
|
|
9806
|
+
case "and?":
|
|
9807
|
+
case "\u22C0?":
|
|
9808
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? ${right} : __zuzu_left; } )()`;
|
|
9062
9809
|
case "or":
|
|
9063
9810
|
case "\u22C1":
|
|
9064
|
-
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ?
|
|
9811
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? true : __zuzu_truthy( ${right} ); } )()`;
|
|
9812
|
+
case "or?":
|
|
9813
|
+
case "\u22C1?":
|
|
9814
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? __zuzu_left : ${right}; } )()`;
|
|
9815
|
+
case "nor":
|
|
9816
|
+
case "\u22BD":
|
|
9817
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? false : !__zuzu_truthy( ${right} ); } )()`;
|
|
9818
|
+
case "nor?":
|
|
9819
|
+
case "\u22BD?":
|
|
9820
|
+
return `( () => { const __zuzu_left = ${left}; const __zuzu_right = ${right}; return __zuzu_truthy( __zuzu_left ) ? ( __zuzu_truthy( __zuzu_right ) ? false : __zuzu_right ) : ( __zuzu_truthy( __zuzu_right ) ? __zuzu_left : true ); } )()`;
|
|
9065
9821
|
case "xor":
|
|
9066
9822
|
case "\u22BB":
|
|
9067
9823
|
return `__zuzu_xor( ${left}, ${right} )`;
|
|
9824
|
+
case "xor?":
|
|
9825
|
+
case "\u22BB?":
|
|
9826
|
+
return `( () => { const __zuzu_left = ${left}; const __zuzu_right = ${right}; return __zuzu_truthy( __zuzu_left ) ? ( __zuzu_truthy( __zuzu_right ) ? false : __zuzu_left ) : ( __zuzu_truthy( __zuzu_right ) ? __zuzu_right : false ); } )()`;
|
|
9827
|
+
case "xnor":
|
|
9828
|
+
case "\u2194":
|
|
9829
|
+
return `( __zuzu_truthy( ${left} ) === __zuzu_truthy( ${right} ) )`;
|
|
9830
|
+
case "xnor?":
|
|
9831
|
+
case "\u2194?":
|
|
9832
|
+
return `( () => { const __zuzu_left = ${left}; const __zuzu_right = ${right}; return __zuzu_truthy( __zuzu_left ) ? __zuzu_right : ( __zuzu_truthy( __zuzu_right ) ? __zuzu_left : true ); } )()`;
|
|
9068
9833
|
case "nand":
|
|
9069
9834
|
case "\u22BC":
|
|
9070
9835
|
return `__zuzu_nand( ${left}, ${right} )`;
|
|
9836
|
+
case "nand?":
|
|
9837
|
+
case "\u22BC?":
|
|
9838
|
+
return `( () => { const __zuzu_left = ${left}; const __zuzu_right = ${right}; return __zuzu_truthy( __zuzu_left ) ? ( __zuzu_truthy( __zuzu_right ) ? false : true ) : ( __zuzu_truthy( __zuzu_right ) ? __zuzu_right : true ); } )()`;
|
|
9839
|
+
case "onlyif":
|
|
9840
|
+
case "\u22A8":
|
|
9841
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? __zuzu_truthy( ${right} ) : true; } )()`;
|
|
9842
|
+
case "onlyif?":
|
|
9843
|
+
case "\u22A8?":
|
|
9844
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? ${right} : true; } )()`;
|
|
9845
|
+
case "butnot":
|
|
9846
|
+
case "\u22AD":
|
|
9847
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? !__zuzu_truthy( ${right} ) : false; } )()`;
|
|
9848
|
+
case "butnot?":
|
|
9849
|
+
case "\u22AD?":
|
|
9850
|
+
return `( () => { const __zuzu_left = ${left}; return __zuzu_truthy( __zuzu_left ) ? ( __zuzu_truthy( ${right} ) ? false : __zuzu_left ) : __zuzu_left; } )()`;
|
|
9071
9851
|
case "eq":
|
|
9072
9852
|
return `__zuzu_str_eq( ${left}, ${right} )`;
|
|
9073
9853
|
case "ne":
|
|
@@ -9191,6 +9971,17 @@ ${cleanup}
|
|
|
9191
9971
|
return `__zuzu_bit_or( ${left}, ${right} )`;
|
|
9192
9972
|
case "^":
|
|
9193
9973
|
return `__zuzu_bit_xor( ${left}, ${right} )`;
|
|
9974
|
+
case "<<":
|
|
9975
|
+
case "\xAB":
|
|
9976
|
+
return `__zuzu_shift_left( ${left}, ${right} )`;
|
|
9977
|
+
case "\u2223":
|
|
9978
|
+
case "divides":
|
|
9979
|
+
return `__zuzu_divides( ${left}, ${right} )`;
|
|
9980
|
+
case "\u2224":
|
|
9981
|
+
return `__zuzu_ndivides( ${left}, ${right} )`;
|
|
9982
|
+
case ">>":
|
|
9983
|
+
case "\xBB":
|
|
9984
|
+
return `__zuzu_shift_right( ${left}, ${right} )`;
|
|
9194
9985
|
default:
|
|
9195
9986
|
return `( ${left} ${node.operator} ${right} )`;
|
|
9196
9987
|
}
|
|
@@ -9459,6 +10250,9 @@ ${cleanup}
|
|
|
9459
10250
|
function programNeedsAsyncWrapper(ast) {
|
|
9460
10251
|
return ast.body.some((stmt) => nodeContainsAsyncControl(stmt));
|
|
9461
10252
|
}
|
|
10253
|
+
function programContainsImport(ast) {
|
|
10254
|
+
return ast.body.some((stmt) => stmt && stmt.type === "ImportDeclaration");
|
|
10255
|
+
}
|
|
9462
10256
|
function nodeContainsAsyncControl(node) {
|
|
9463
10257
|
if (!node || typeof node !== "object") {
|
|
9464
10258
|
return false;
|
|
@@ -10746,7 +11540,7 @@ ${cleanup}
|
|
|
10746
11540
|
"package.json"(exports2, module2) {
|
|
10747
11541
|
module2.exports = {
|
|
10748
11542
|
name: "zuzu-js",
|
|
10749
|
-
version: "0.
|
|
11543
|
+
version: "0.5.0",
|
|
10750
11544
|
description: "JavaScript runtime, compiler, and browser bundle for ZuzuScript.",
|
|
10751
11545
|
main: "lib/zuzu.js",
|
|
10752
11546
|
bin: {
|
|
@@ -10794,6 +11588,7 @@ ${cleanup}
|
|
|
10794
11588
|
node: ">=16"
|
|
10795
11589
|
},
|
|
10796
11590
|
dependencies: {
|
|
11591
|
+
"@std-uritemplate/std-uritemplate": "^2.0.10",
|
|
10797
11592
|
"@xmldom/xmldom": "^0.9.10",
|
|
10798
11593
|
"adm-zip": "^0.5.17",
|
|
10799
11594
|
"better-sqlite3": "^11.10.0",
|
|
@@ -11328,7 +12123,9 @@ ${cleanup}
|
|
|
11328
12123
|
releaseCollectionValues,
|
|
11329
12124
|
addSetValue,
|
|
11330
12125
|
assignStrongValue,
|
|
11331
|
-
assignWeakValue
|
|
12126
|
+
assignWeakValue,
|
|
12127
|
+
codePointStringCompare,
|
|
12128
|
+
stringSortComparator
|
|
11332
12129
|
} = require_runtime_helpers();
|
|
11333
12130
|
var taskRuntime2 = require_task();
|
|
11334
12131
|
var textEncoder = new TextEncoder();
|
|
@@ -11397,6 +12194,12 @@ ${cleanup}
|
|
|
11397
12194
|
this.add(makeWeakValue(value));
|
|
11398
12195
|
return this;
|
|
11399
12196
|
});
|
|
12197
|
+
define(Set.prototype, "push_weak", function _pushWeak(...values) {
|
|
12198
|
+
for (const value of values) {
|
|
12199
|
+
this.add(makeWeakValue(value));
|
|
12200
|
+
}
|
|
12201
|
+
return this;
|
|
12202
|
+
});
|
|
11400
12203
|
define(Set.prototype, "copy", function _copy() {
|
|
11401
12204
|
return makeSet(this);
|
|
11402
12205
|
});
|
|
@@ -11514,10 +12317,16 @@ ${cleanup}
|
|
|
11514
12317
|
function stringCompare(left, right, options = {}) {
|
|
11515
12318
|
const l = options.insensitive ? zuzuOperatorString(left).toLowerCase() : zuzuOperatorString(left);
|
|
11516
12319
|
const r = options.insensitive ? zuzuOperatorString(right).toLowerCase() : zuzuOperatorString(right);
|
|
11517
|
-
return l
|
|
12320
|
+
return codePointStringCompare(l, r);
|
|
11518
12321
|
}
|
|
11519
12322
|
function parseNumericString(value) {
|
|
11520
12323
|
const text = String(value).trim();
|
|
12324
|
+
const radix = text.match(/^([+-]?)0([xX][0-9a-fA-F]+|[bB][01]+|[oO][0-7]+)$/);
|
|
12325
|
+
if (radix) {
|
|
12326
|
+
const base = "xX".includes(radix[2][0]) ? 16 : "bB".includes(radix[2][0]) ? 2 : 8;
|
|
12327
|
+
const magnitude = parseInt(radix[2].slice(1), base);
|
|
12328
|
+
return radix[1] === "-" ? -magnitude : magnitude;
|
|
12329
|
+
}
|
|
11521
12330
|
const match = text.match(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/);
|
|
11522
12331
|
if (!match) {
|
|
11523
12332
|
throw new Error(`TypeException: cannot coerce String to Number: ${JSON.stringify(String(value))}`);
|
|
@@ -11697,8 +12506,12 @@ ${cleanup}
|
|
|
11697
12506
|
switch (comparator) {
|
|
11698
12507
|
case "eq":
|
|
11699
12508
|
return stringCompare(left, right) === 0;
|
|
12509
|
+
case "eqi":
|
|
12510
|
+
return stringCompare(left, right, { insensitive: true }) === 0;
|
|
11700
12511
|
case "ne":
|
|
11701
12512
|
return stringCompare(left, right) !== 0;
|
|
12513
|
+
case "nei":
|
|
12514
|
+
return stringCompare(left, right, { insensitive: true }) !== 0;
|
|
11702
12515
|
case "=":
|
|
11703
12516
|
return numericEqual(zuzuToNumber(left), zuzuToNumber(right));
|
|
11704
12517
|
case "==":
|
|
@@ -11708,7 +12521,17 @@ ${cleanup}
|
|
|
11708
12521
|
};
|
|
11709
12522
|
let runNext = false;
|
|
11710
12523
|
for (const section of cases) {
|
|
11711
|
-
|
|
12524
|
+
let matched = false;
|
|
12525
|
+
if (Array.isArray(section.tests)) {
|
|
12526
|
+
for (const test of section.tests) {
|
|
12527
|
+
if (zuzuTruthy(await taskRuntime2.awaitValue(test(value)))) {
|
|
12528
|
+
matched = true;
|
|
12529
|
+
break;
|
|
12530
|
+
}
|
|
12531
|
+
}
|
|
12532
|
+
} else {
|
|
12533
|
+
matched = section.values.some((item) => cmp(value, item));
|
|
12534
|
+
}
|
|
11712
12535
|
if (matched || runNext) {
|
|
11713
12536
|
const result = await taskRuntime2.awaitValue(section.body());
|
|
11714
12537
|
runNext = result === true;
|
|
@@ -11816,6 +12639,46 @@ ${cleanup}
|
|
|
11816
12639
|
}
|
|
11817
12640
|
return ~(zuzuToNumber(value) >>> 0) >>> 0;
|
|
11818
12641
|
}
|
|
12642
|
+
function shiftBitstream(bytes, count, left) {
|
|
12643
|
+
const len = bytes.length;
|
|
12644
|
+
const out = new Uint8Array(len);
|
|
12645
|
+
if (len === 0 || count >= len * 8) {
|
|
12646
|
+
return out;
|
|
12647
|
+
}
|
|
12648
|
+
const byteShift = Math.floor(count / 8);
|
|
12649
|
+
const bitShift = count % 8;
|
|
12650
|
+
for (let i = 0; i < len; i++) {
|
|
12651
|
+
let value;
|
|
12652
|
+
if (left) {
|
|
12653
|
+
const src = i + byteShift;
|
|
12654
|
+
const hi = src < len ? bytes[src] : 0;
|
|
12655
|
+
const lo = src + 1 < len ? bytes[src + 1] : 0;
|
|
12656
|
+
value = (hi << 8 | lo) << bitShift >> 8;
|
|
12657
|
+
} else {
|
|
12658
|
+
if (i < byteShift) {
|
|
12659
|
+
continue;
|
|
12660
|
+
}
|
|
12661
|
+
const lo = bytes[i - byteShift];
|
|
12662
|
+
const hi = i > byteShift ? bytes[i - byteShift - 1] : 0;
|
|
12663
|
+
value = (hi << 8 | lo) >> bitShift;
|
|
12664
|
+
}
|
|
12665
|
+
out[i] = value & 255;
|
|
12666
|
+
}
|
|
12667
|
+
return out;
|
|
12668
|
+
}
|
|
12669
|
+
function shiftValue(left, right, leftward) {
|
|
12670
|
+
left = resolveWeakValue(left);
|
|
12671
|
+
const count = Math.trunc(zuzuToNumber(right));
|
|
12672
|
+
if (!(count >= 0) || !Number.isFinite(count)) {
|
|
12673
|
+
throw new Error("Exception: shift count must be a non-negative integer");
|
|
12674
|
+
}
|
|
12675
|
+
if (left instanceof ZuzuBinary) {
|
|
12676
|
+
return new BinaryString2(shiftBitstream(left.bytes, count, leftward));
|
|
12677
|
+
}
|
|
12678
|
+
const value = Math.trunc(zuzuToNumber(left));
|
|
12679
|
+
const factor = Math.pow(2, count);
|
|
12680
|
+
return leftward ? value * factor : Math.floor(value / factor);
|
|
12681
|
+
}
|
|
11819
12682
|
function zuzuComparableValue(value) {
|
|
11820
12683
|
value = resolveWeakValue(value);
|
|
11821
12684
|
if (typeof value === "function" && value.length === 0) {
|
|
@@ -11903,7 +12766,7 @@ ${cleanup}
|
|
|
11903
12766
|
return Object.prototype.toString.call(value) === "[object Object]" && !(value.constructor && value.constructor.__zuzu_class_name);
|
|
11904
12767
|
}
|
|
11905
12768
|
function isDictMethodReceiver(value) {
|
|
11906
|
-
return
|
|
12769
|
+
return isPlainObjectLike(value) && !isPairListLike(value) && !isSetLike(value) && !isBagLike(value);
|
|
11907
12770
|
}
|
|
11908
12771
|
function normalizeDictKey(key) {
|
|
11909
12772
|
key = resolveWeakValue(key);
|
|
@@ -11921,18 +12784,350 @@ ${cleanup}
|
|
|
11921
12784
|
}
|
|
11922
12785
|
return String(key);
|
|
11923
12786
|
}
|
|
12787
|
+
function arraySliceBounds(length, start, end = length) {
|
|
12788
|
+
let from = Number(start ?? 0);
|
|
12789
|
+
let to = Number(end ?? length);
|
|
12790
|
+
from = Number.isFinite(from) ? Math.trunc(from) : 0;
|
|
12791
|
+
to = Number.isFinite(to) ? Math.trunc(to) : length;
|
|
12792
|
+
if (from < 0) {
|
|
12793
|
+
from += length;
|
|
12794
|
+
}
|
|
12795
|
+
if (to < 0) {
|
|
12796
|
+
to += length;
|
|
12797
|
+
}
|
|
12798
|
+
from = Math.max(0, Math.min(length, from));
|
|
12799
|
+
to = Math.max(0, Math.min(length, to));
|
|
12800
|
+
return [Math.min(from, to), Math.max(from, to)];
|
|
12801
|
+
}
|
|
12802
|
+
function arrayMethodArity(name2, actual, min, max = min) {
|
|
12803
|
+
const count = actual - 1;
|
|
12804
|
+
if (count < min || count > max) {
|
|
12805
|
+
throw new Error(
|
|
12806
|
+
min === max ? `${name2} expects ${min} argument${min === 1 ? "" : "s"}` : `${name2} expects between ${min} and ${max} arguments`
|
|
12807
|
+
);
|
|
12808
|
+
}
|
|
12809
|
+
}
|
|
12810
|
+
function arrayIndex(length, idx) {
|
|
12811
|
+
let index = Number(idx);
|
|
12812
|
+
index = Number.isFinite(index) ? Math.trunc(index) : 0;
|
|
12813
|
+
if (index < 0) {
|
|
12814
|
+
index += length;
|
|
12815
|
+
}
|
|
12816
|
+
return index;
|
|
12817
|
+
}
|
|
12818
|
+
function shuffledArrayValues(self) {
|
|
12819
|
+
const out = self.slice();
|
|
12820
|
+
for (let idx = out.length - 1; idx > 0; idx--) {
|
|
12821
|
+
const swapIdx = Math.floor(Math.random() * (idx + 1));
|
|
12822
|
+
[out[idx], out[swapIdx]] = [out[swapIdx], out[idx]];
|
|
12823
|
+
}
|
|
12824
|
+
return out;
|
|
12825
|
+
}
|
|
12826
|
+
function arrayJoin(self, separator, fallback, hasFallback) {
|
|
12827
|
+
const sep = operatorString(separator);
|
|
12828
|
+
let fallbackString;
|
|
12829
|
+
const out = [];
|
|
12830
|
+
for (const value of self) {
|
|
12831
|
+
try {
|
|
12832
|
+
out.push(operatorString(value));
|
|
12833
|
+
} catch (err) {
|
|
12834
|
+
if (!hasFallback) {
|
|
12835
|
+
throw err;
|
|
12836
|
+
}
|
|
12837
|
+
if (typeof fallback === "function") {
|
|
12838
|
+
out.push(operatorString(fallback(value)));
|
|
12839
|
+
} else {
|
|
12840
|
+
if (fallbackString === void 0) {
|
|
12841
|
+
fallbackString = operatorString(fallback);
|
|
12842
|
+
}
|
|
12843
|
+
out.push(fallbackString);
|
|
12844
|
+
}
|
|
12845
|
+
}
|
|
12846
|
+
}
|
|
12847
|
+
return out.join(sep);
|
|
12848
|
+
}
|
|
12849
|
+
var ARRAY_METHODS = Object.freeze({
|
|
12850
|
+
append(self, ...values) {
|
|
12851
|
+
self.push(...values.map((value) => retainCollectionValue(self, value)));
|
|
12852
|
+
return self;
|
|
12853
|
+
},
|
|
12854
|
+
push(self, ...values) {
|
|
12855
|
+
return ARRAY_METHODS.append(self, ...values);
|
|
12856
|
+
},
|
|
12857
|
+
add(self, ...values) {
|
|
12858
|
+
return ARRAY_METHODS.append(self, ...values);
|
|
12859
|
+
},
|
|
12860
|
+
push_weak(self, ...values) {
|
|
12861
|
+
self.push(...values.map(makeWeakValue));
|
|
12862
|
+
return self;
|
|
12863
|
+
},
|
|
12864
|
+
pop(self) {
|
|
12865
|
+
return self.length ? self.pop() : null;
|
|
12866
|
+
},
|
|
12867
|
+
prepend(self, ...values) {
|
|
12868
|
+
self.unshift(...values.map((value) => retainCollectionValue(self, value)));
|
|
12869
|
+
return self;
|
|
12870
|
+
},
|
|
12871
|
+
unshift(self, ...values) {
|
|
12872
|
+
return ARRAY_METHODS.prepend(self, ...values);
|
|
12873
|
+
},
|
|
12874
|
+
unshift_weak(self, ...values) {
|
|
12875
|
+
self.unshift(...values.map(makeWeakValue));
|
|
12876
|
+
return self;
|
|
12877
|
+
},
|
|
12878
|
+
shift(self) {
|
|
12879
|
+
return self.length ? self.shift() : null;
|
|
12880
|
+
},
|
|
12881
|
+
length(self) {
|
|
12882
|
+
return self.length;
|
|
12883
|
+
},
|
|
12884
|
+
count(self) {
|
|
12885
|
+
return self.length;
|
|
12886
|
+
},
|
|
12887
|
+
empty(self) {
|
|
12888
|
+
return self.length === 0 ? 1 : 0;
|
|
12889
|
+
},
|
|
12890
|
+
is_empty(self) {
|
|
12891
|
+
return ARRAY_METHODS.empty(self);
|
|
12892
|
+
},
|
|
12893
|
+
copy(self) {
|
|
12894
|
+
return makeArray(self);
|
|
12895
|
+
},
|
|
12896
|
+
to_Array(self) {
|
|
12897
|
+
return makeArray(self);
|
|
12898
|
+
},
|
|
12899
|
+
get(self, idx, fallback = null) {
|
|
12900
|
+
arrayMethodArity("Array.get", arguments.length, 1, 2);
|
|
12901
|
+
const index = arrayIndex(self.length, idx);
|
|
12902
|
+
return index >= 0 && index < self.length ? self[index] : fallback;
|
|
12903
|
+
},
|
|
12904
|
+
set(self, idx, value) {
|
|
12905
|
+
arrayMethodArity("Array.set", arguments.length, 2);
|
|
12906
|
+
const index = arrayIndex(self.length, idx);
|
|
12907
|
+
if (index < 0) {
|
|
12908
|
+
throw new Error("Array index is out of range");
|
|
12909
|
+
}
|
|
12910
|
+
releaseCollectionValue(self, self[index]);
|
|
12911
|
+
self[index] = retainCollectionValue(self, value);
|
|
12912
|
+
return self;
|
|
12913
|
+
},
|
|
12914
|
+
set_weak(self, idx, value) {
|
|
12915
|
+
arrayMethodArity("Array.set_weak", arguments.length, 2);
|
|
12916
|
+
const index = arrayIndex(self.length, idx);
|
|
12917
|
+
if (index < 0) {
|
|
12918
|
+
throw new Error("Array index is out of range");
|
|
12919
|
+
}
|
|
12920
|
+
releaseCollectionValue(self, self[index]);
|
|
12921
|
+
self[index] = makeWeakValue(value);
|
|
12922
|
+
return self;
|
|
12923
|
+
},
|
|
12924
|
+
clear(self) {
|
|
12925
|
+
releaseCollectionValues(self);
|
|
12926
|
+
self.splice(0, self.length);
|
|
12927
|
+
return self;
|
|
12928
|
+
},
|
|
12929
|
+
join(self, separator, fallback) {
|
|
12930
|
+
return arrayJoin(self, separator, fallback, arguments.length > 2);
|
|
12931
|
+
},
|
|
12932
|
+
slice(self, start, end) {
|
|
12933
|
+
const [from, to] = arraySliceBounds(self.length, start, end);
|
|
12934
|
+
return makeArray(self.slice(from, to));
|
|
12935
|
+
},
|
|
12936
|
+
head(self, n = 1) {
|
|
12937
|
+
arrayMethodArity("Array.head", arguments.length, 0, 1);
|
|
12938
|
+
return makeArray(self.slice(0, Math.max(0, Number(n) || 0)));
|
|
12939
|
+
},
|
|
12940
|
+
tail(self, n = 1) {
|
|
12941
|
+
arrayMethodArity("Array.tail", arguments.length, 0, 1);
|
|
12942
|
+
const count = Math.max(0, Number(n) || 0);
|
|
12943
|
+
return makeArray(count === 0 ? [] : self.slice(-count));
|
|
12944
|
+
},
|
|
12945
|
+
to_Set(self) {
|
|
12946
|
+
return makeSet(self);
|
|
12947
|
+
},
|
|
12948
|
+
to_Bag(self) {
|
|
12949
|
+
return makeBag(self);
|
|
12950
|
+
},
|
|
12951
|
+
to_Iterator(self) {
|
|
12952
|
+
return self[Symbol.iterator]();
|
|
12953
|
+
},
|
|
12954
|
+
sort(self, fn2) {
|
|
12955
|
+
const out = self.slice();
|
|
12956
|
+
out.sort((left, right) => Number(fn2(left, right)) || 0);
|
|
12957
|
+
return makeArray(out);
|
|
12958
|
+
},
|
|
12959
|
+
sortstr(self) {
|
|
12960
|
+
return makeArray(self.slice().sort(stringSortComparator));
|
|
12961
|
+
},
|
|
12962
|
+
sortnum(self) {
|
|
12963
|
+
return makeArray(
|
|
12964
|
+
self.map((item) => Number(item)).sort((a, b) => a - b)
|
|
12965
|
+
);
|
|
12966
|
+
},
|
|
12967
|
+
reverse(self) {
|
|
12968
|
+
return makeArray(self.slice().reverse());
|
|
12969
|
+
},
|
|
12970
|
+
sum(self) {
|
|
12971
|
+
return self.reduce((a, b) => Number(a) + Number(b), 0);
|
|
12972
|
+
},
|
|
12973
|
+
product(self) {
|
|
12974
|
+
return self.reduce((a, b) => Number(a) * Number(b), 1);
|
|
12975
|
+
},
|
|
12976
|
+
shuffle(self) {
|
|
12977
|
+
arrayMethodArity("Array.shuffle", arguments.length, 0);
|
|
12978
|
+
return makeArray(shuffledArrayValues(self));
|
|
12979
|
+
},
|
|
12980
|
+
sample(self, n = 1) {
|
|
12981
|
+
arrayMethodArity("Array.sample", arguments.length, 0, 1);
|
|
12982
|
+
return makeArray(
|
|
12983
|
+
shuffledArrayValues(self).slice(0, Math.max(0, Number(n) || 0))
|
|
12984
|
+
);
|
|
12985
|
+
},
|
|
12986
|
+
contains(self, value) {
|
|
12987
|
+
return self.includes(value) ? 1 : 0;
|
|
12988
|
+
},
|
|
12989
|
+
map(self, fn2) {
|
|
12990
|
+
arrayMethodArity("Array.map", arguments.length, 1);
|
|
12991
|
+
return makeArray(self.map((value) => fn2(value)));
|
|
12992
|
+
},
|
|
12993
|
+
grep(self, fn2) {
|
|
12994
|
+
arrayMethodArity("Array.grep", arguments.length, 1);
|
|
12995
|
+
return makeArray(self.filter((value) => fn2(value)));
|
|
12996
|
+
},
|
|
12997
|
+
any(self, fn2) {
|
|
12998
|
+
arrayMethodArity("Array.any", arguments.length, 1);
|
|
12999
|
+
return self.some((value) => fn2(value)) ? 1 : 0;
|
|
13000
|
+
},
|
|
13001
|
+
all(self, fn2) {
|
|
13002
|
+
arrayMethodArity("Array.all", arguments.length, 1);
|
|
13003
|
+
return self.every((value) => fn2(value)) ? 1 : 0;
|
|
13004
|
+
},
|
|
13005
|
+
first(self, fn2) {
|
|
13006
|
+
arrayMethodArity("Array.first", arguments.length, 1);
|
|
13007
|
+
for (const value of self) {
|
|
13008
|
+
if (fn2(value)) {
|
|
13009
|
+
return value;
|
|
13010
|
+
}
|
|
13011
|
+
}
|
|
13012
|
+
return null;
|
|
13013
|
+
},
|
|
13014
|
+
remove(self, fn2) {
|
|
13015
|
+
for (let idx = self.length - 1; idx >= 0; idx--) {
|
|
13016
|
+
if (fn2(self[idx])) {
|
|
13017
|
+
releaseCollectionValue(self, self[idx]);
|
|
13018
|
+
self.splice(idx, 1);
|
|
13019
|
+
}
|
|
13020
|
+
}
|
|
13021
|
+
return self;
|
|
13022
|
+
},
|
|
13023
|
+
first_index(self, fn2) {
|
|
13024
|
+
for (let idx = 0; idx < self.length; idx++) {
|
|
13025
|
+
if (fn2(self[idx])) {
|
|
13026
|
+
return idx;
|
|
13027
|
+
}
|
|
13028
|
+
}
|
|
13029
|
+
return -1;
|
|
13030
|
+
},
|
|
13031
|
+
for_each_value(self, fn2) {
|
|
13032
|
+
for (const value of self) {
|
|
13033
|
+
fn2(value);
|
|
13034
|
+
}
|
|
13035
|
+
return self;
|
|
13036
|
+
},
|
|
13037
|
+
reduce(self, fn2) {
|
|
13038
|
+
if (self.length === 0) {
|
|
13039
|
+
return null;
|
|
13040
|
+
}
|
|
13041
|
+
let acc = self[0];
|
|
13042
|
+
for (let idx = 1; idx < self.length; idx++) {
|
|
13043
|
+
acc = fn2(acc, self[idx]);
|
|
13044
|
+
}
|
|
13045
|
+
return acc;
|
|
13046
|
+
},
|
|
13047
|
+
reductions(self, fn2) {
|
|
13048
|
+
if (self.length === 0) {
|
|
13049
|
+
return makeArray([]);
|
|
13050
|
+
}
|
|
13051
|
+
const out = [self[0]];
|
|
13052
|
+
for (let idx = 1; idx < self.length; idx++) {
|
|
13053
|
+
out.push(fn2(out[out.length - 1], self[idx]));
|
|
13054
|
+
}
|
|
13055
|
+
return makeArray(out);
|
|
13056
|
+
}
|
|
13057
|
+
});
|
|
13058
|
+
var ARRAY_ZERO_ARG_METHODS = /* @__PURE__ */ new Set([
|
|
13059
|
+
"copy",
|
|
13060
|
+
"count",
|
|
13061
|
+
"empty",
|
|
13062
|
+
"is_empty",
|
|
13063
|
+
"length",
|
|
13064
|
+
"pop",
|
|
13065
|
+
"reverse",
|
|
13066
|
+
"shift",
|
|
13067
|
+
"shuffle",
|
|
13068
|
+
"sortnum",
|
|
13069
|
+
"sortstr",
|
|
13070
|
+
"to_Array",
|
|
13071
|
+
"to_Bag",
|
|
13072
|
+
"to_Iterator",
|
|
13073
|
+
"to_Set"
|
|
13074
|
+
]);
|
|
13075
|
+
function getArrayMethod(object, property) {
|
|
13076
|
+
if (typeof property === "symbol") {
|
|
13077
|
+
return null;
|
|
13078
|
+
}
|
|
13079
|
+
const name2 = String(property);
|
|
13080
|
+
if (!Array.isArray(object) || !Object.prototype.hasOwnProperty.call(ARRAY_METHODS, name2)) {
|
|
13081
|
+
return null;
|
|
13082
|
+
}
|
|
13083
|
+
return function zuzuArrayMethod(...args) {
|
|
13084
|
+
return ARRAY_METHODS[name2](object, ...args);
|
|
13085
|
+
};
|
|
13086
|
+
}
|
|
13087
|
+
var SET_METHODS = Object.freeze({
|
|
13088
|
+
add_weak(self, ...values) {
|
|
13089
|
+
for (const value of values) {
|
|
13090
|
+
self.add(makeWeakValue(value));
|
|
13091
|
+
}
|
|
13092
|
+
return self;
|
|
13093
|
+
},
|
|
13094
|
+
push_weak(self, ...values) {
|
|
13095
|
+
return SET_METHODS.add_weak(self, ...values);
|
|
13096
|
+
},
|
|
13097
|
+
clear(self) {
|
|
13098
|
+
releaseCollectionValues(self);
|
|
13099
|
+
Set.prototype.clear.call(self);
|
|
13100
|
+
return self;
|
|
13101
|
+
}
|
|
13102
|
+
});
|
|
13103
|
+
var SET_ZERO_ARG_METHODS = /* @__PURE__ */ new Set(["clear"]);
|
|
13104
|
+
function getSetMethod(object, property) {
|
|
13105
|
+
if (typeof property === "symbol") {
|
|
13106
|
+
return null;
|
|
13107
|
+
}
|
|
13108
|
+
const name2 = String(property);
|
|
13109
|
+
if (!isSetLike(object) || !Object.prototype.hasOwnProperty.call(SET_METHODS, name2)) {
|
|
13110
|
+
return null;
|
|
13111
|
+
}
|
|
13112
|
+
return function zuzuSetMethod(...args) {
|
|
13113
|
+
return SET_METHODS[name2](object, ...args);
|
|
13114
|
+
};
|
|
13115
|
+
}
|
|
13116
|
+
function dictSortedKeys(self) {
|
|
13117
|
+
return isDictMethodReceiver(self) ? Object.keys(self).sort() : [];
|
|
13118
|
+
}
|
|
11924
13119
|
var DICT_METHODS = Object.freeze({
|
|
11925
13120
|
length(self) {
|
|
11926
13121
|
return isDictMethodReceiver(self) ? Object.keys(self).length : 0;
|
|
11927
13122
|
},
|
|
11928
13123
|
keys(self) {
|
|
11929
|
-
return
|
|
13124
|
+
return makeSet(dictSortedKeys(self));
|
|
11930
13125
|
},
|
|
11931
13126
|
values(self) {
|
|
11932
13127
|
if (!isDictMethodReceiver(self)) {
|
|
11933
|
-
return [];
|
|
13128
|
+
return makeBag([]);
|
|
11934
13129
|
}
|
|
11935
|
-
return
|
|
13130
|
+
return makeBag(dictSortedKeys(self).map((key) => resolveWeakValue(self[key])));
|
|
11936
13131
|
},
|
|
11937
13132
|
copy(self) {
|
|
11938
13133
|
if (!isDictMethodReceiver(self)) {
|
|
@@ -11946,11 +13141,11 @@ ${cleanup}
|
|
|
11946
13141
|
},
|
|
11947
13142
|
enumerate(self) {
|
|
11948
13143
|
if (!isDictMethodReceiver(self)) {
|
|
11949
|
-
return [];
|
|
13144
|
+
return makeBag([]);
|
|
11950
13145
|
}
|
|
11951
|
-
return
|
|
13146
|
+
return makeBag(dictSortedKeys(self).map(
|
|
11952
13147
|
(key) => new Pair({ pair: [key, resolveWeakValue(self[key])] })
|
|
11953
|
-
);
|
|
13148
|
+
));
|
|
11954
13149
|
},
|
|
11955
13150
|
has(self, key) {
|
|
11956
13151
|
return isDictMethodReceiver(self) && Object.prototype.hasOwnProperty.call(self, normalizeDictKey(key)) ? 1 : 0;
|
|
@@ -11998,13 +13193,13 @@ ${cleanup}
|
|
|
11998
13193
|
return [];
|
|
11999
13194
|
}
|
|
12000
13195
|
const out = [];
|
|
12001
|
-
for (const key of
|
|
13196
|
+
for (const key of dictSortedKeys(self)) {
|
|
12002
13197
|
out.push(key, resolveWeakValue(self[key]));
|
|
12003
13198
|
}
|
|
12004
13199
|
return out;
|
|
12005
13200
|
},
|
|
12006
13201
|
sorted_keys(self) {
|
|
12007
|
-
return
|
|
13202
|
+
return dictSortedKeys(self);
|
|
12008
13203
|
},
|
|
12009
13204
|
remove(self, key) {
|
|
12010
13205
|
if (!isDictMethodReceiver(self)) {
|
|
@@ -12037,26 +13232,31 @@ ${cleanup}
|
|
|
12037
13232
|
return DICT_METHODS.empty(self);
|
|
12038
13233
|
},
|
|
12039
13234
|
to_Array(self) {
|
|
12040
|
-
|
|
13235
|
+
if (!isDictMethodReceiver(self)) {
|
|
13236
|
+
return [];
|
|
13237
|
+
}
|
|
13238
|
+
return makeArray(dictSortedKeys(self).map(
|
|
13239
|
+
(key) => new Pair({ pair: [key, resolveWeakValue(self[key])] })
|
|
13240
|
+
));
|
|
12041
13241
|
},
|
|
12042
13242
|
to_Iterator(self) {
|
|
12043
|
-
return
|
|
13243
|
+
return dictSortedKeys(self)[Symbol.iterator]();
|
|
12044
13244
|
},
|
|
12045
13245
|
for_each_key(self, fn2) {
|
|
12046
|
-
for (const key of
|
|
13246
|
+
for (const key of dictSortedKeys(self)) {
|
|
12047
13247
|
fn2(key);
|
|
12048
13248
|
}
|
|
12049
13249
|
return self;
|
|
12050
13250
|
},
|
|
12051
13251
|
for_each_value(self, fn2) {
|
|
12052
|
-
for (const
|
|
12053
|
-
fn2(
|
|
13252
|
+
for (const key of dictSortedKeys(self)) {
|
|
13253
|
+
fn2(resolveWeakValue(self[key]));
|
|
12054
13254
|
}
|
|
12055
13255
|
return self;
|
|
12056
13256
|
},
|
|
12057
13257
|
for_each_pair(self, fn2) {
|
|
12058
|
-
for (const
|
|
12059
|
-
fn2(pair);
|
|
13258
|
+
for (const key of dictSortedKeys(self)) {
|
|
13259
|
+
fn2(new Pair({ pair: [key, resolveWeakValue(self[key])] }));
|
|
12060
13260
|
}
|
|
12061
13261
|
return self;
|
|
12062
13262
|
},
|
|
@@ -12090,6 +13290,12 @@ ${cleanup}
|
|
|
12090
13290
|
return null;
|
|
12091
13291
|
}
|
|
12092
13292
|
const name2 = String(property);
|
|
13293
|
+
for (let proto = Object.getPrototypeOf(object); proto; proto = Object.getPrototypeOf(proto)) {
|
|
13294
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, name2);
|
|
13295
|
+
if (descriptor && typeof descriptor.value === "function") {
|
|
13296
|
+
return null;
|
|
13297
|
+
}
|
|
13298
|
+
}
|
|
12093
13299
|
if (!isDictMethodReceiver(object) || Object.prototype.hasOwnProperty.call(object, name2) || !Object.prototype.hasOwnProperty.call(DICT_METHODS, name2)) {
|
|
12094
13300
|
return null;
|
|
12095
13301
|
}
|
|
@@ -12129,8 +13335,8 @@ ${cleanup}
|
|
|
12129
13335
|
enumerable: false,
|
|
12130
13336
|
configurable: true
|
|
12131
13337
|
});
|
|
12132
|
-
bound.invoke = function invoke(
|
|
12133
|
-
return fn2.apply(
|
|
13338
|
+
bound.invoke = function invoke(self, args = []) {
|
|
13339
|
+
return fn2.apply(self, args);
|
|
12134
13340
|
};
|
|
12135
13341
|
bound.to_String = function to_String() {
|
|
12136
13342
|
return methodName;
|
|
@@ -12581,6 +13787,22 @@ ${cleanup}
|
|
|
12581
13787
|
if (object == null) {
|
|
12582
13788
|
return null;
|
|
12583
13789
|
}
|
|
13790
|
+
if (property !== "length") {
|
|
13791
|
+
const arrayMethod = getArrayMethod(object, property);
|
|
13792
|
+
if (arrayMethod && ARRAY_ZERO_ARG_METHODS.has(String(property))) {
|
|
13793
|
+
return arrayMethod();
|
|
13794
|
+
}
|
|
13795
|
+
if (arrayMethod) {
|
|
13796
|
+
return arrayMethod;
|
|
13797
|
+
}
|
|
13798
|
+
}
|
|
13799
|
+
const setMethod = getSetMethod(object, property);
|
|
13800
|
+
if (setMethod && SET_ZERO_ARG_METHODS.has(String(property))) {
|
|
13801
|
+
return setMethod();
|
|
13802
|
+
}
|
|
13803
|
+
if (setMethod) {
|
|
13804
|
+
return setMethod;
|
|
13805
|
+
}
|
|
12584
13806
|
const value = resolveWeakValue(object[property]);
|
|
12585
13807
|
if (typeof value === "function" && value.length === 0 && !value.__zuzu_marshal_meta) {
|
|
12586
13808
|
return value.call(object);
|
|
@@ -12613,6 +13835,18 @@ ${cleanup}
|
|
|
12613
13835
|
if (property instanceof ZuzuMethod || property && property.__zuzu_method) {
|
|
12614
13836
|
return property.invoke(object, args);
|
|
12615
13837
|
}
|
|
13838
|
+
const arrayMethod = getArrayMethod(object, property);
|
|
13839
|
+
if (arrayMethod) {
|
|
13840
|
+
return arrayMethod(...args);
|
|
13841
|
+
}
|
|
13842
|
+
const setMethod = getSetMethod(object, property);
|
|
13843
|
+
if (setMethod) {
|
|
13844
|
+
return setMethod(...args);
|
|
13845
|
+
}
|
|
13846
|
+
const dictMethod = getDictMethod(object, property);
|
|
13847
|
+
if (dictMethod) {
|
|
13848
|
+
return dictMethod(...args);
|
|
13849
|
+
}
|
|
12616
13850
|
const value = resolveWeakValue(object[property]);
|
|
12617
13851
|
if (typeof value === "function") {
|
|
12618
13852
|
return value.apply(object, args);
|
|
@@ -12625,10 +13859,6 @@ ${cleanup}
|
|
|
12625
13859
|
}
|
|
12626
13860
|
proto = Object.getPrototypeOf(proto);
|
|
12627
13861
|
}
|
|
12628
|
-
const dictMethod = getDictMethod(object, property);
|
|
12629
|
-
if (dictMethod) {
|
|
12630
|
-
return dictMethod(...args);
|
|
12631
|
-
}
|
|
12632
13862
|
throw new TypeError(`${String(property)} is not a function`);
|
|
12633
13863
|
}
|
|
12634
13864
|
function zuzuMaybeDemolish(value) {
|
|
@@ -12647,6 +13877,12 @@ ${cleanup}
|
|
|
12647
13877
|
return 0;
|
|
12648
13878
|
}
|
|
12649
13879
|
const key = String(methodName || "");
|
|
13880
|
+
if (getArrayMethod(value, key)) {
|
|
13881
|
+
return 1;
|
|
13882
|
+
}
|
|
13883
|
+
if (getSetMethod(value, key)) {
|
|
13884
|
+
return 1;
|
|
13885
|
+
}
|
|
12650
13886
|
if (getDictMethod(value, key)) {
|
|
12651
13887
|
return 1;
|
|
12652
13888
|
}
|
|
@@ -13081,14 +14317,19 @@ ${cleanup}
|
|
|
13081
14317
|
this.transpiler = normalizeTranspilerName(
|
|
13082
14318
|
options.transpiler || DEFAULT_TRANSPILER
|
|
13083
14319
|
);
|
|
14320
|
+
this.asyncImports = options.asyncImports === true;
|
|
13084
14321
|
if (typeof this.host.loadJsModule !== "function") {
|
|
13085
14322
|
this.host.loadJsModule = (filename) => __require(filename);
|
|
13086
14323
|
}
|
|
13087
14324
|
}
|
|
14325
|
+
usesAsyncImports() {
|
|
14326
|
+
return this.asyncImports || typeof this.host.hasAsyncModules === "function" && this.host.hasAsyncModules();
|
|
14327
|
+
}
|
|
13088
14328
|
transpile(source, options = {}) {
|
|
13089
14329
|
return transpile(source, {
|
|
13090
14330
|
...options,
|
|
13091
|
-
transpiler: options.transpiler || this.transpiler
|
|
14331
|
+
transpiler: options.transpiler || this.transpiler,
|
|
14332
|
+
asyncImports: options.asyncImports ?? this.usesAsyncImports()
|
|
13092
14333
|
});
|
|
13093
14334
|
}
|
|
13094
14335
|
getModuleSearchRoots() {
|
|
@@ -13191,7 +14432,12 @@ ${cleanup}
|
|
|
13191
14432
|
}
|
|
13192
14433
|
const moduleSearchRoots = this.getModuleSearchRoots();
|
|
13193
14434
|
const emit = (value) => {
|
|
13194
|
-
|
|
14435
|
+
let line = String(value);
|
|
14436
|
+
if (line === "Infinity") {
|
|
14437
|
+
line = "Inf";
|
|
14438
|
+
} else if (line === "-Infinity") {
|
|
14439
|
+
line = "-Inf";
|
|
14440
|
+
}
|
|
13195
14441
|
if (this.outputLines) {
|
|
13196
14442
|
this.outputLines.push(line);
|
|
13197
14443
|
}
|
|
@@ -13422,6 +14668,12 @@ ${cleanup}
|
|
|
13422
14668
|
}
|
|
13423
14669
|
return this;
|
|
13424
14670
|
});
|
|
14671
|
+
defineRuntimeMethod(Set.prototype, "push_weak", function _pushWeakSet(...values) {
|
|
14672
|
+
for (const v of values) {
|
|
14673
|
+
this.add(makeWeakValue(v));
|
|
14674
|
+
}
|
|
14675
|
+
return this;
|
|
14676
|
+
});
|
|
13425
14677
|
defineRuntimeMethod(Set.prototype, "contains", function _containsSet(value) {
|
|
13426
14678
|
return contains(this, value);
|
|
13427
14679
|
});
|
|
@@ -13469,7 +14721,7 @@ ${cleanup}
|
|
|
13469
14721
|
return [...this].sort(fn2);
|
|
13470
14722
|
});
|
|
13471
14723
|
defineRuntimeMethod(Set.prototype, "sortstr", function _setSortstr() {
|
|
13472
|
-
return [...this].sort(
|
|
14724
|
+
return [...this].sort(stringSortComparator);
|
|
13473
14725
|
});
|
|
13474
14726
|
defineRuntimeMethod(Set.prototype, "sortnum", function _setSortnum() {
|
|
13475
14727
|
return [...this].map((item) => Number(item)).sort((a, b) => a - b);
|
|
@@ -13571,6 +14823,7 @@ ${cleanup}
|
|
|
13571
14823
|
__file__: this.fileValueForFilename(filename),
|
|
13572
14824
|
__zuzu_system_seed: systemGlobalSeed,
|
|
13573
14825
|
__zuzu_current_system: currentSystem,
|
|
14826
|
+
__zuzu_operator_string: zuzuOperatorString,
|
|
13574
14827
|
DEBUG: this.debugLevel,
|
|
13575
14828
|
__zuzu_host_capabilities: capabilityFlags,
|
|
13576
14829
|
has_capability(name2) {
|
|
@@ -13875,6 +15128,12 @@ ${cleanup}
|
|
|
13875
15128
|
if (input == null) {
|
|
13876
15129
|
return [];
|
|
13877
15130
|
}
|
|
15131
|
+
if (input instanceof ZuzuBinary) {
|
|
15132
|
+
return Array.from(input.bytes, (byte) => new BinaryString2([byte]));
|
|
15133
|
+
}
|
|
15134
|
+
if (typeof input === "string" || input instanceof String) {
|
|
15135
|
+
return Array.from(String(input));
|
|
15136
|
+
}
|
|
13878
15137
|
if (typeof input[Symbol.iterator] === "function") {
|
|
13879
15138
|
return input;
|
|
13880
15139
|
}
|
|
@@ -13925,13 +15184,13 @@ ${cleanup}
|
|
|
13925
15184
|
return zuzuTruthy(value);
|
|
13926
15185
|
},
|
|
13927
15186
|
__zuzu_not(value) {
|
|
13928
|
-
return zuzuTruthy(value)
|
|
15187
|
+
return !zuzuTruthy(value);
|
|
13929
15188
|
},
|
|
13930
15189
|
__zuzu_and(left, right) {
|
|
13931
|
-
return zuzuTruthy(left) && zuzuTruthy(right)
|
|
15190
|
+
return zuzuTruthy(left) && zuzuTruthy(right);
|
|
13932
15191
|
},
|
|
13933
15192
|
__zuzu_or(left, right) {
|
|
13934
|
-
return zuzuTruthy(left) || zuzuTruthy(right)
|
|
15193
|
+
return zuzuTruthy(left) || zuzuTruthy(right);
|
|
13935
15194
|
},
|
|
13936
15195
|
__zuzu_typeof(value) {
|
|
13937
15196
|
return zuzuTypeof(value);
|
|
@@ -14024,6 +15283,19 @@ ${cleanup}
|
|
|
14024
15283
|
__zuzu_bit_and(left, right) {
|
|
14025
15284
|
return bitwiseAnd(left, right);
|
|
14026
15285
|
},
|
|
15286
|
+
__zuzu_shift_left(left, right) {
|
|
15287
|
+
return shiftValue(left, right, true);
|
|
15288
|
+
},
|
|
15289
|
+
// The left operand is the divisor: a ∣ b tests b mod a.
|
|
15290
|
+
__zuzu_divides(left, right) {
|
|
15291
|
+
return zuzuToNumber(right) % zuzuToNumber(left) === 0;
|
|
15292
|
+
},
|
|
15293
|
+
__zuzu_ndivides(left, right) {
|
|
15294
|
+
return zuzuToNumber(right) % zuzuToNumber(left);
|
|
15295
|
+
},
|
|
15296
|
+
__zuzu_shift_right(left, right) {
|
|
15297
|
+
return shiftValue(left, right, false);
|
|
15298
|
+
},
|
|
14027
15299
|
__zuzu_bit_or(left, right) {
|
|
14028
15300
|
return bitwiseOr(left, right);
|
|
14029
15301
|
},
|
|
@@ -14168,10 +15440,10 @@ ${cleanup}
|
|
|
14168
15440
|
return zuzuMaybeDemolish(value);
|
|
14169
15441
|
},
|
|
14170
15442
|
__zuzu_xor(left, right) {
|
|
14171
|
-
return zuzuTruthy(left) !== zuzuTruthy(right)
|
|
15443
|
+
return zuzuTruthy(left) !== zuzuTruthy(right);
|
|
14172
15444
|
},
|
|
14173
15445
|
__zuzu_nand(left, right) {
|
|
14174
|
-
return zuzuTruthy(left) && zuzuTruthy(right)
|
|
15446
|
+
return !(zuzuTruthy(left) && zuzuTruthy(right));
|
|
14175
15447
|
},
|
|
14176
15448
|
__zuzu_num_eq(left, right) {
|
|
14177
15449
|
if (!isNumericComparable(left) || !isNumericComparable(right)) {
|
|
@@ -14277,6 +15549,9 @@ ${cleanup}
|
|
|
14277
15549
|
if (name2 === "std/eval") {
|
|
14278
15550
|
return { eval: context.__zuzu_native_eval };
|
|
14279
15551
|
}
|
|
15552
|
+
if (this.usesAsyncImports()) {
|
|
15553
|
+
return this.loadModuleAsync(name2, filename, context);
|
|
15554
|
+
}
|
|
14280
15555
|
return this.loadModule(name2, filename, context);
|
|
14281
15556
|
};
|
|
14282
15557
|
return context;
|
|
@@ -14353,6 +15628,41 @@ ${cleanup}
|
|
|
14353
15628
|
Object.defineProperty( proto, name, desc );
|
|
14354
15629
|
}
|
|
14355
15630
|
};
|
|
15631
|
+
if ( Array.prototype.join.__zuzu_array_join !== true ) {
|
|
15632
|
+
const __zuzu_native_array_join = Array.prototype.join;
|
|
15633
|
+
const joinDesc = Object.create( null );
|
|
15634
|
+
joinDesc.value = function _join( separator, fallback ) {
|
|
15635
|
+
const hasFallback = arguments.length > 1;
|
|
15636
|
+
let fallbackString;
|
|
15637
|
+
const sep = __zuzu_operator_string( separator );
|
|
15638
|
+
const out = [];
|
|
15639
|
+
for ( const value of this ) {
|
|
15640
|
+
try {
|
|
15641
|
+
out.push( __zuzu_operator_string( value ) );
|
|
15642
|
+
}
|
|
15643
|
+
catch ( err ) {
|
|
15644
|
+
if ( !hasFallback ) {
|
|
15645
|
+
throw err;
|
|
15646
|
+
}
|
|
15647
|
+
if ( typeof fallback === 'function' ) {
|
|
15648
|
+
out.push( __zuzu_operator_string( fallback( value ) ) );
|
|
15649
|
+
}
|
|
15650
|
+
else {
|
|
15651
|
+
if ( fallbackString === undefined ) {
|
|
15652
|
+
fallbackString = __zuzu_operator_string( fallback );
|
|
15653
|
+
}
|
|
15654
|
+
out.push( fallbackString );
|
|
15655
|
+
}
|
|
15656
|
+
}
|
|
15657
|
+
}
|
|
15658
|
+
return __zuzu_native_array_join.call( out, sep );
|
|
15659
|
+
};
|
|
15660
|
+
joinDesc.value.__zuzu_array_join = true;
|
|
15661
|
+
joinDesc.enumerable = false;
|
|
15662
|
+
joinDesc.configurable = true;
|
|
15663
|
+
joinDesc.writable = true;
|
|
15664
|
+
Object.defineProperty( Array.prototype, 'join', joinDesc );
|
|
15665
|
+
}
|
|
14356
15666
|
define( Array.prototype, 'length', function _length() { return this.length; } );
|
|
14357
15667
|
define( Array.prototype, 'count', function _count() { return this.length; } );
|
|
14358
15668
|
define( Array.prototype, 'empty', function _empty() { return this.length === 0 ? 1 : 0; } );
|
|
@@ -14380,7 +15690,7 @@ ${cleanup}
|
|
|
14380
15690
|
define( Array.prototype, 'shuffle', function _shuffle() { return this.slice(); } );
|
|
14381
15691
|
define( Array.prototype, 'sample', function _sample( n ) { return this.slice( 0, n ); } );
|
|
14382
15692
|
define( Array.prototype, 'for_each_value', function _for_each_value( fn ) { this.forEach( fn ); return this; } );
|
|
14383
|
-
define( Array.prototype, 'sortstr', function _sortstr() { return this.slice().sort(
|
|
15693
|
+
define( Array.prototype, 'sortstr', function _sortstr() { return this.slice().sort( stringSortComparator ); } );
|
|
14384
15694
|
define( Array.prototype, 'sortnum', function _sortnum() { return this.map( (item) => Number( item ) ).sort( (a, b) => a - b ); } );
|
|
14385
15695
|
define( Array.prototype, 'to_Array', function _to_array() { return __zuzu_array( this ); } );
|
|
14386
15696
|
define( Array.prototype, 'to_Set', function _to_set() { return __zuzu_set( this ); } );
|
|
@@ -14395,6 +15705,7 @@ ${cleanup}
|
|
|
14395
15705
|
define( Set.prototype, 'is_empty', function _is_empty() { return this.empty(); } );
|
|
14396
15706
|
define( Set.prototype, 'push', function _push( ...values ) { for ( const v of values ) { __zuzu_add_set_value( this, v ); } return this; } );
|
|
14397
15707
|
define( Set.prototype, 'add_weak', function _add_weak( value ) { this.add( __zuzu_make_weak_value( value ) ); return this; } );
|
|
15708
|
+
define( Set.prototype, 'push_weak', function _push_weak( ...values ) { for ( const v of values ) { this.add( __zuzu_make_weak_value( v ) ); } return this; } );
|
|
14398
15709
|
define( Set.prototype, 'contains', function _contains( value ) { return __zuzu_contains( this, value ); } );
|
|
14399
15710
|
define( Set.prototype, 'remove', function _remove( value ) { const resolved = __zuzu_resolve_weak_value( value ); if ( this.delete( resolved ) ) { __zuzu_release_collection_value( this, resolved ); } return this; } );
|
|
14400
15711
|
define( Set.prototype, 'to_Array', function _to_array() { return __zuzu_array( this ); } );
|
|
@@ -14410,7 +15721,7 @@ ${cleanup}
|
|
|
14410
15721
|
define( Set.prototype, 'is_disjoint', function _is_disjoint( other ) { return this.intersection( other ).size === 0 ? 1 : 0; } );
|
|
14411
15722
|
define( Set.prototype, 'equals', function _equals( other ) { return __zuzu_equivalentof( this, other ); } );
|
|
14412
15723
|
define( Set.prototype, 'sort', function _sort( fn ) { return [ ...this ].sort( fn ); } );
|
|
14413
|
-
define( Set.prototype, 'sortstr', function _sortstr() { return [ ...this ].sort(
|
|
15724
|
+
define( Set.prototype, 'sortstr', function _sortstr() { return [ ...this ].sort( stringSortComparator ); } );
|
|
14414
15725
|
define( Set.prototype, 'sortnum', function _sortnum() { return [ ...this ].map( (item) => Number( item ) ).sort( (a, b) => a - b ); } );
|
|
14415
15726
|
define( Set.prototype, 'map', function _map( fn ) { return new Set( [ ...this ].map( fn ) ); } );
|
|
14416
15727
|
define( Set.prototype, 'grep', function _grep( fn ) { return new Set( [ ...this ].filter( fn ) ); } );
|
|
@@ -14626,6 +15937,68 @@ ${exportBridge}
|
|
|
14626
15937
|
}
|
|
14627
15938
|
return moduleObj.exports;
|
|
14628
15939
|
}
|
|
15940
|
+
async loadModuleAsync(moduleName, fromFile, contextForPolicy = null) {
|
|
15941
|
+
if (/(^|\/)\.\.(\/|$)/.test(moduleName)) {
|
|
15942
|
+
throw new Error("Import module path cannot contain '..' segments");
|
|
15943
|
+
}
|
|
15944
|
+
this.enforceModulePolicy(moduleName);
|
|
15945
|
+
const resolved = this.resolveModulePath(moduleName, fromFile);
|
|
15946
|
+
const cacheable = moduleName !== "test/more" && this.evalCapabilityOverrides == null;
|
|
15947
|
+
if (cacheable && this.moduleCache.has(resolved)) {
|
|
15948
|
+
return this.moduleCache.get(resolved);
|
|
15949
|
+
}
|
|
15950
|
+
if (resolved.endsWith(".js")) {
|
|
15951
|
+
return this.loadModule(moduleName, fromFile, contextForPolicy);
|
|
15952
|
+
}
|
|
15953
|
+
if (this.moduleLoading.has(resolved)) {
|
|
15954
|
+
throw new Error("Circular module loading detected");
|
|
15955
|
+
}
|
|
15956
|
+
this.moduleLoading.add(resolved);
|
|
15957
|
+
try {
|
|
15958
|
+
const source = typeof this.host.readFileTextAsync === "function" ? await this.host.readFileTextAsync(resolved) : this.host.readFileText(resolved);
|
|
15959
|
+
let js = this.transpile(source, {
|
|
15960
|
+
asyncImports: true,
|
|
15961
|
+
deferAsyncWrapper: true
|
|
15962
|
+
});
|
|
15963
|
+
const exportNames = resolved.endsWith(".zzm") ? collectTopLevelDeclarations(source, stripPod) : [];
|
|
15964
|
+
let exportBridge = "";
|
|
15965
|
+
if (exportNames.length > 0) {
|
|
15966
|
+
exportBridge = exportNames.map((name2) => {
|
|
15967
|
+
if (name2.startsWith("_")) {
|
|
15968
|
+
return `if ( typeof ${name2} !== "undefined" ) { const __zuzu_desc = Object.create( null ); __zuzu_desc.get = function() { return ${name2}; }; __zuzu_desc.set = function( value ) { ${name2} = value; }; __zuzu_desc.enumerable = false; __zuzu_desc.configurable = true; Object.defineProperty( module.exports, ${JSON.stringify(name2)}, __zuzu_desc ); }`;
|
|
15969
|
+
}
|
|
15970
|
+
return `if ( typeof ${name2} !== "undefined" ) { const __zuzu_desc = Object.create( null ); __zuzu_desc.get = function() { return ${name2}; }; __zuzu_desc.set = function( value ) { ${name2} = value; }; __zuzu_desc.enumerable = true; __zuzu_desc.configurable = true; Object.defineProperty( module.exports, ${JSON.stringify(name2)}, __zuzu_desc ); }`;
|
|
15971
|
+
}).join("\n");
|
|
15972
|
+
}
|
|
15973
|
+
js = `( async () => {
|
|
15974
|
+
${js}
|
|
15975
|
+
${exportBridge}
|
|
15976
|
+
} )()`;
|
|
15977
|
+
setCompiledSource(resolved, js);
|
|
15978
|
+
const moduleObj = { exports: {} };
|
|
15979
|
+
const context = this.buildContext({
|
|
15980
|
+
exports: moduleObj.exports,
|
|
15981
|
+
module: moduleObj,
|
|
15982
|
+
filename: resolved
|
|
15983
|
+
});
|
|
15984
|
+
context.__global__ = /* @__PURE__ */ Object.create(null);
|
|
15985
|
+
this.installCollectionMethods(context);
|
|
15986
|
+
const moduleRunOptions = { filename: resolved };
|
|
15987
|
+
if (this.executionTimeoutMs != null) {
|
|
15988
|
+
moduleRunOptions.timeout = this.executionTimeoutMs;
|
|
15989
|
+
}
|
|
15990
|
+
const result = this.host.runInContext(js, context, moduleRunOptions);
|
|
15991
|
+
if (result && typeof result.then === "function") {
|
|
15992
|
+
await result;
|
|
15993
|
+
}
|
|
15994
|
+
if (cacheable) {
|
|
15995
|
+
this.moduleCache.set(resolved, moduleObj.exports);
|
|
15996
|
+
}
|
|
15997
|
+
return moduleObj.exports;
|
|
15998
|
+
} finally {
|
|
15999
|
+
this.moduleLoading.delete(resolved);
|
|
16000
|
+
}
|
|
16001
|
+
}
|
|
14629
16002
|
runSource(source, options = {}) {
|
|
14630
16003
|
const filename = options.filename || this.host.join(this.repoRoot, "<inline>.zzs");
|
|
14631
16004
|
let js;
|
|
@@ -15263,7 +16636,9 @@ ${" ".repeat(Math.max(0, caretColumn - 1))}^`;
|
|
|
15263
16636
|
const bindingName = marshalBindingName(preferredName || meta.name, id);
|
|
15264
16637
|
const captures = [];
|
|
15265
16638
|
const dependencies = [];
|
|
15266
|
-
for (const [name2, captured] of Object.entries(meta.captures || {}).sort(
|
|
16639
|
+
for (const [name2, captured] of Object.entries(meta.captures || {}).sort(
|
|
16640
|
+
(left, right) => left[0].localeCompare(right[0])
|
|
16641
|
+
)) {
|
|
15267
16642
|
if (isFunctionValue(captured)) {
|
|
15268
16643
|
dependencies.push([0, encodeFunctionCode(captured, state, name2)]);
|
|
15269
16644
|
} else if (isUserClassValue(captured)) {
|
|
@@ -37312,7 +38687,9 @@ ${lines.join("\n")}
|
|
|
37312
38687
|
return values;
|
|
37313
38688
|
}
|
|
37314
38689
|
var ZMath = {
|
|
37315
|
-
pi
|
|
38690
|
+
pi() {
|
|
38691
|
+
return PI;
|
|
38692
|
+
},
|
|
37316
38693
|
sin(value) {
|
|
37317
38694
|
return Math.sin(Number(value ?? 0));
|
|
37318
38695
|
},
|
|
@@ -37443,6 +38820,12 @@ ${lines.join("\n")}
|
|
|
37443
38820
|
"use strict";
|
|
37444
38821
|
var BigNum = class _BigNum {
|
|
37445
38822
|
constructor(value, text = null, isInt = null) {
|
|
38823
|
+
if (typeof value === "bigint") {
|
|
38824
|
+
this._value = value;
|
|
38825
|
+
this._text = text == null ? String(value) : String(text);
|
|
38826
|
+
this._isInt = isInt == null ? true : Boolean(isInt);
|
|
38827
|
+
return;
|
|
38828
|
+
}
|
|
37446
38829
|
this._value = Number(value ?? 0);
|
|
37447
38830
|
this._text = text == null ? String(this._value) : String(text);
|
|
37448
38831
|
this._isInt = isInt == null ? Number.isInteger(this._value) : Boolean(isInt);
|
|
@@ -37458,19 +38841,46 @@ ${lines.join("\n")}
|
|
|
37458
38841
|
}
|
|
37459
38842
|
static from_dec(value) {
|
|
37460
38843
|
const text = String(value ?? "0").trim();
|
|
37461
|
-
|
|
38844
|
+
const safeText = text || "0";
|
|
38845
|
+
if (_BigNum._isIntegerText(safeText)) {
|
|
38846
|
+
return new _BigNum(BigInt(safeText), safeText, true);
|
|
38847
|
+
}
|
|
38848
|
+
return new _BigNum(Number(safeText), safeText, !/[.eE]/.test(safeText));
|
|
37462
38849
|
}
|
|
37463
38850
|
static from_hex(value) {
|
|
37464
|
-
const text = String(value ?? "0").trim().
|
|
37465
|
-
const
|
|
38851
|
+
const text = String(value ?? "0").trim().replace(/^0x/u, "").toLowerCase() || "0";
|
|
38852
|
+
const negative = text.startsWith("-");
|
|
38853
|
+
const digits = text.replace(/^[+-]/u, "");
|
|
38854
|
+
const parsed = BigInt(`0x${digits}`) * (negative ? -1n : 1n);
|
|
37466
38855
|
return new _BigNum(parsed, String(parsed), true);
|
|
37467
38856
|
}
|
|
37468
|
-
|
|
38857
|
+
is_int() {
|
|
37469
38858
|
return this._isInt;
|
|
37470
38859
|
}
|
|
38860
|
+
_toBigInt() {
|
|
38861
|
+
if (!this._isInt) {
|
|
38862
|
+
return null;
|
|
38863
|
+
}
|
|
38864
|
+
if (typeof this._value === "bigint") {
|
|
38865
|
+
return this._value;
|
|
38866
|
+
}
|
|
38867
|
+
try {
|
|
38868
|
+
return BigInt(this._text);
|
|
38869
|
+
} catch {
|
|
38870
|
+
return null;
|
|
38871
|
+
}
|
|
38872
|
+
}
|
|
38873
|
+
_toNumber() {
|
|
38874
|
+
return typeof this._value === "bigint" ? Number(this._value) : this._value;
|
|
38875
|
+
}
|
|
37471
38876
|
bcmp(other) {
|
|
37472
|
-
const rhs = _BigNum._coerce(other)
|
|
37473
|
-
|
|
38877
|
+
const rhs = _BigNum._coerce(other);
|
|
38878
|
+
const lhsBigInt = this._toBigInt();
|
|
38879
|
+
const rhsBigInt = rhs._toBigInt();
|
|
38880
|
+
if (lhsBigInt !== null && rhsBigInt !== null) {
|
|
38881
|
+
return lhsBigInt < rhsBigInt ? -1 : lhsBigInt > rhsBigInt ? 1 : 0;
|
|
38882
|
+
}
|
|
38883
|
+
return this._toNumber() < rhs._toNumber() ? -1 : this._toNumber() > rhs._toNumber() ? 1 : 0;
|
|
37474
38884
|
}
|
|
37475
38885
|
beq(other) {
|
|
37476
38886
|
return this.bcmp(other) === 0;
|
|
@@ -37490,71 +38900,136 @@ ${lines.join("\n")}
|
|
|
37490
38900
|
bge(other) {
|
|
37491
38901
|
return this.bcmp(other) >= 0;
|
|
37492
38902
|
}
|
|
37493
|
-
|
|
37494
|
-
|
|
38903
|
+
babs() {
|
|
38904
|
+
const value = this._toBigInt();
|
|
38905
|
+
if (value !== null) {
|
|
38906
|
+
return new _BigNum(value < 0n ? -value : value, String(value < 0n ? -value : value), this._isInt);
|
|
38907
|
+
}
|
|
38908
|
+
return new _BigNum(Math.abs(this._toNumber()), String(Math.abs(this._toNumber())), this._isInt);
|
|
37495
38909
|
}
|
|
37496
|
-
|
|
37497
|
-
|
|
38910
|
+
bneg() {
|
|
38911
|
+
const value = this._toBigInt();
|
|
38912
|
+
if (value !== null) {
|
|
38913
|
+
return new _BigNum(-value, String(-value), this._isInt);
|
|
38914
|
+
}
|
|
38915
|
+
return new _BigNum(-this._toNumber(), String(-this._toNumber()), this._isInt);
|
|
37498
38916
|
}
|
|
37499
|
-
|
|
37500
|
-
return new _BigNum(1 / this.
|
|
38917
|
+
binv() {
|
|
38918
|
+
return new _BigNum(1 / this._toNumber());
|
|
37501
38919
|
}
|
|
37502
|
-
|
|
37503
|
-
return new _BigNum(Math.sin(this.
|
|
38920
|
+
bsin() {
|
|
38921
|
+
return new _BigNum(Math.sin(this._toNumber()), String(Math.sin(this._toNumber())), false);
|
|
37504
38922
|
}
|
|
37505
|
-
|
|
37506
|
-
return new _BigNum(Math.cos(this.
|
|
38923
|
+
bcos() {
|
|
38924
|
+
return new _BigNum(Math.cos(this._toNumber()));
|
|
37507
38925
|
}
|
|
37508
|
-
|
|
37509
|
-
return new _BigNum(Math.tan(this.
|
|
38926
|
+
btan() {
|
|
38927
|
+
return new _BigNum(Math.tan(this._toNumber()), String(Math.tan(this._toNumber())), false);
|
|
37510
38928
|
}
|
|
37511
|
-
|
|
37512
|
-
return new _BigNum(Math.sqrt(this.
|
|
38929
|
+
bsqrt() {
|
|
38930
|
+
return new _BigNum(Math.sqrt(this._toNumber()));
|
|
37513
38931
|
}
|
|
37514
|
-
|
|
37515
|
-
return new _BigNum(Math.round(this.
|
|
38932
|
+
bround() {
|
|
38933
|
+
return new _BigNum(Math.round(this._toNumber()));
|
|
37516
38934
|
}
|
|
37517
|
-
|
|
37518
|
-
return new _BigNum(Math.floor(this.
|
|
38935
|
+
bfloor() {
|
|
38936
|
+
return new _BigNum(Math.floor(this._toNumber()));
|
|
37519
38937
|
}
|
|
37520
|
-
|
|
37521
|
-
return new _BigNum(Math.ceil(this.
|
|
38938
|
+
bceil() {
|
|
38939
|
+
return new _BigNum(Math.ceil(this._toNumber()));
|
|
37522
38940
|
}
|
|
37523
38941
|
badd(other) {
|
|
37524
|
-
|
|
38942
|
+
const rhs = _BigNum._coerce(other);
|
|
38943
|
+
const lhsInt = this._toBigInt();
|
|
38944
|
+
const rhsInt = rhs._toBigInt();
|
|
38945
|
+
if (lhsInt !== null && rhsInt !== null) {
|
|
38946
|
+
return new _BigNum(lhsInt + rhsInt, String(lhsInt + rhsInt), false);
|
|
38947
|
+
}
|
|
38948
|
+
return new _BigNum(this._toNumber() + rhs._toNumber(), String(this._toNumber() + rhs._toNumber()), false);
|
|
37525
38949
|
}
|
|
37526
38950
|
bsub(other) {
|
|
37527
|
-
|
|
38951
|
+
const rhs = _BigNum._coerce(other);
|
|
38952
|
+
const lhsInt = this._toBigInt();
|
|
38953
|
+
const rhsInt = rhs._toBigInt();
|
|
38954
|
+
if (lhsInt !== null && rhsInt !== null) {
|
|
38955
|
+
return new _BigNum(lhsInt - rhsInt, String(lhsInt - rhsInt), false);
|
|
38956
|
+
}
|
|
38957
|
+
return new _BigNum(this._toNumber() - rhs._toNumber(), String(this._toNumber() - rhs._toNumber()), false);
|
|
37528
38958
|
}
|
|
37529
38959
|
bmul(other) {
|
|
37530
|
-
|
|
38960
|
+
const rhs = _BigNum._coerce(other);
|
|
38961
|
+
const lhsInt = this._toBigInt();
|
|
38962
|
+
const rhsInt = rhs._toBigInt();
|
|
38963
|
+
if (lhsInt !== null && rhsInt !== null) {
|
|
38964
|
+
return new _BigNum(lhsInt * rhsInt, String(lhsInt * rhsInt), false);
|
|
38965
|
+
}
|
|
38966
|
+
return new _BigNum(this._toNumber() * rhs._toNumber(), String(this._toNumber() * rhs._toNumber()), false);
|
|
37531
38967
|
}
|
|
37532
38968
|
bdiv(other) {
|
|
37533
|
-
|
|
38969
|
+
const rhs = _BigNum._coerce(other);
|
|
38970
|
+
return new _BigNum(this._toNumber() / rhs._toNumber());
|
|
37534
38971
|
}
|
|
37535
38972
|
bmod(other) {
|
|
37536
|
-
|
|
38973
|
+
const rhs = _BigNum._coerce(other);
|
|
38974
|
+
const lhsInt = this._toBigInt();
|
|
38975
|
+
const rhsInt = rhs._toBigInt();
|
|
38976
|
+
if (lhsInt !== null && rhsInt !== null && rhsInt !== 0n) {
|
|
38977
|
+
return new _BigNum(lhsInt % rhsInt, String(lhsInt % rhsInt), true);
|
|
38978
|
+
}
|
|
38979
|
+
return new _BigNum(this._toNumber() % rhs._toNumber());
|
|
37537
38980
|
}
|
|
37538
38981
|
bpow(other) {
|
|
37539
|
-
|
|
38982
|
+
const rhs = _BigNum._coerce(other);
|
|
38983
|
+
const lhsInt = this._toBigInt();
|
|
38984
|
+
const rhsInt = rhs._toBigInt();
|
|
38985
|
+
if (lhsInt !== null && rhsInt !== null && rhsInt >= 0n) {
|
|
38986
|
+
let base = lhsInt;
|
|
38987
|
+
let power = rhsInt;
|
|
38988
|
+
let result = 1n;
|
|
38989
|
+
while (power > 0n) {
|
|
38990
|
+
if (power & 1n) {
|
|
38991
|
+
result *= base;
|
|
38992
|
+
}
|
|
38993
|
+
power >>= 1n;
|
|
38994
|
+
if (power > 0n) {
|
|
38995
|
+
base *= base;
|
|
38996
|
+
}
|
|
38997
|
+
}
|
|
38998
|
+
return new _BigNum(result, String(result), true);
|
|
38999
|
+
}
|
|
39000
|
+
return new _BigNum(this._toNumber() ** rhs._toNumber());
|
|
39001
|
+
}
|
|
39002
|
+
to_hex() {
|
|
39003
|
+
const value = this._toBigInt();
|
|
39004
|
+
if (value === null) {
|
|
39005
|
+
return `0x${Math.trunc(this._toNumber()).toString(16)}`;
|
|
39006
|
+
}
|
|
39007
|
+
if (value === 0n) {
|
|
39008
|
+
return "0x0";
|
|
39009
|
+
}
|
|
39010
|
+
const absolute = value < 0n ? -value : value;
|
|
39011
|
+
return value < 0n ? `-0x${absolute.toString(16)}` : `0x${absolute.toString(16)}`;
|
|
39012
|
+
}
|
|
39013
|
+
to_dec() {
|
|
39014
|
+
return this._textify();
|
|
37540
39015
|
}
|
|
37541
|
-
|
|
37542
|
-
return
|
|
39016
|
+
to_String() {
|
|
39017
|
+
return this.to_dec();
|
|
37543
39018
|
}
|
|
37544
|
-
|
|
37545
|
-
return
|
|
39019
|
+
toString() {
|
|
39020
|
+
return String(this.to_String());
|
|
37546
39021
|
}
|
|
37547
|
-
|
|
37548
|
-
return this.
|
|
39022
|
+
to_Number() {
|
|
39023
|
+
return this._toNumber();
|
|
37549
39024
|
}
|
|
37550
|
-
|
|
37551
|
-
return
|
|
39025
|
+
static _isIntegerText(text) {
|
|
39026
|
+
return /^[+-]?(?:\d+)$/u.test(text);
|
|
37552
39027
|
}
|
|
37553
39028
|
_textify() {
|
|
37554
39029
|
if (this._text != null && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/u.test(this._text)) {
|
|
37555
39030
|
return this._text.replace(/\.0+$/u, "").replace(/(\.\d*?)0+$/u, "$1").replace(/\.$/u, "");
|
|
37556
39031
|
}
|
|
37557
|
-
return String(this._value);
|
|
39032
|
+
return this._toBigInt() !== null ? this._toBigInt().toString() : String(this._value);
|
|
37558
39033
|
}
|
|
37559
39034
|
};
|
|
37560
39035
|
module2.exports = {
|
|
@@ -39529,6 +41004,436 @@ ${lines.join("\n")}
|
|
|
39529
41004
|
}
|
|
39530
41005
|
});
|
|
39531
41006
|
|
|
41007
|
+
// node_modules/@std-uritemplate/std-uritemplate/dist/index.cjs
|
|
41008
|
+
var require_dist = __commonJS({
|
|
41009
|
+
"node_modules/@std-uritemplate/std-uritemplate/dist/index.cjs"(exports2) {
|
|
41010
|
+
"use strict";
|
|
41011
|
+
var StdUriTemplate = class _StdUriTemplate {
|
|
41012
|
+
static expand(template, substitutions) {
|
|
41013
|
+
return _StdUriTemplate.expandImpl(template, substitutions);
|
|
41014
|
+
}
|
|
41015
|
+
static validateLiteral(c, col) {
|
|
41016
|
+
switch (c) {
|
|
41017
|
+
case "+":
|
|
41018
|
+
case "#":
|
|
41019
|
+
case "/":
|
|
41020
|
+
case ";":
|
|
41021
|
+
case "?":
|
|
41022
|
+
case "&":
|
|
41023
|
+
case " ":
|
|
41024
|
+
case "!":
|
|
41025
|
+
case "=":
|
|
41026
|
+
case "$":
|
|
41027
|
+
case "|":
|
|
41028
|
+
case "*":
|
|
41029
|
+
case ":":
|
|
41030
|
+
case "~":
|
|
41031
|
+
case "-":
|
|
41032
|
+
throw new Error(`Illegal character identified in the token at col: ${col}`);
|
|
41033
|
+
}
|
|
41034
|
+
}
|
|
41035
|
+
static getMaxChar(buffer, col) {
|
|
41036
|
+
if (!buffer) {
|
|
41037
|
+
return -1;
|
|
41038
|
+
} else {
|
|
41039
|
+
const value = buffer.join("");
|
|
41040
|
+
if (value.length === 0) {
|
|
41041
|
+
return -1;
|
|
41042
|
+
} else {
|
|
41043
|
+
try {
|
|
41044
|
+
return parseInt(value, 10);
|
|
41045
|
+
} catch (e) {
|
|
41046
|
+
throw new Error(`Cannot parse max chars at col: ${col}`);
|
|
41047
|
+
}
|
|
41048
|
+
}
|
|
41049
|
+
}
|
|
41050
|
+
}
|
|
41051
|
+
static getOperator(c, token, col) {
|
|
41052
|
+
switch (c) {
|
|
41053
|
+
case "+":
|
|
41054
|
+
return 1;
|
|
41055
|
+
case "#":
|
|
41056
|
+
return 2;
|
|
41057
|
+
case ".":
|
|
41058
|
+
return 3;
|
|
41059
|
+
case "/":
|
|
41060
|
+
return 4;
|
|
41061
|
+
case ";":
|
|
41062
|
+
return 5;
|
|
41063
|
+
case "?":
|
|
41064
|
+
return 6;
|
|
41065
|
+
case "&":
|
|
41066
|
+
return 7;
|
|
41067
|
+
default:
|
|
41068
|
+
_StdUriTemplate.validateLiteral(c, col);
|
|
41069
|
+
token.push(c);
|
|
41070
|
+
return 0;
|
|
41071
|
+
}
|
|
41072
|
+
}
|
|
41073
|
+
static expandImpl(str, substitutions) {
|
|
41074
|
+
const result = [];
|
|
41075
|
+
let token = null;
|
|
41076
|
+
let operator = null;
|
|
41077
|
+
let composite = false;
|
|
41078
|
+
let maxCharBuffer = null;
|
|
41079
|
+
let firstToken = true;
|
|
41080
|
+
for (let i = 0; i < str.length; i++) {
|
|
41081
|
+
const character = str.charAt(i);
|
|
41082
|
+
switch (character) {
|
|
41083
|
+
case "{":
|
|
41084
|
+
token = [];
|
|
41085
|
+
firstToken = true;
|
|
41086
|
+
break;
|
|
41087
|
+
case "}":
|
|
41088
|
+
if (token !== null) {
|
|
41089
|
+
const expanded = _StdUriTemplate.expandToken(
|
|
41090
|
+
operator,
|
|
41091
|
+
token.join(""),
|
|
41092
|
+
composite,
|
|
41093
|
+
_StdUriTemplate.getMaxChar(maxCharBuffer, i),
|
|
41094
|
+
firstToken,
|
|
41095
|
+
substitutions,
|
|
41096
|
+
result,
|
|
41097
|
+
i
|
|
41098
|
+
);
|
|
41099
|
+
if (expanded && firstToken) {
|
|
41100
|
+
firstToken = false;
|
|
41101
|
+
}
|
|
41102
|
+
token = null;
|
|
41103
|
+
operator = null;
|
|
41104
|
+
composite = false;
|
|
41105
|
+
maxCharBuffer = null;
|
|
41106
|
+
} else {
|
|
41107
|
+
throw new Error(`Failed to expand token, invalid at col: ${i}`);
|
|
41108
|
+
}
|
|
41109
|
+
break;
|
|
41110
|
+
case ",":
|
|
41111
|
+
if (token !== null) {
|
|
41112
|
+
const expanded = _StdUriTemplate.expandToken(
|
|
41113
|
+
operator,
|
|
41114
|
+
token.join(""),
|
|
41115
|
+
composite,
|
|
41116
|
+
_StdUriTemplate.getMaxChar(maxCharBuffer, i),
|
|
41117
|
+
firstToken,
|
|
41118
|
+
substitutions,
|
|
41119
|
+
result,
|
|
41120
|
+
i
|
|
41121
|
+
);
|
|
41122
|
+
if (expanded && firstToken) {
|
|
41123
|
+
firstToken = false;
|
|
41124
|
+
}
|
|
41125
|
+
token = [];
|
|
41126
|
+
composite = false;
|
|
41127
|
+
maxCharBuffer = null;
|
|
41128
|
+
break;
|
|
41129
|
+
}
|
|
41130
|
+
// Intentional fall-through for commas outside the {}
|
|
41131
|
+
default:
|
|
41132
|
+
if (token !== null) {
|
|
41133
|
+
if (operator === null) {
|
|
41134
|
+
operator = _StdUriTemplate.getOperator(character, token, i);
|
|
41135
|
+
} else if (maxCharBuffer !== null) {
|
|
41136
|
+
if (character.match(/^\d$/)) {
|
|
41137
|
+
maxCharBuffer.push(character);
|
|
41138
|
+
} else {
|
|
41139
|
+
throw new Error(`Illegal character identified in the token at col: ${i}`);
|
|
41140
|
+
}
|
|
41141
|
+
} else {
|
|
41142
|
+
if (character === ":") {
|
|
41143
|
+
maxCharBuffer = [];
|
|
41144
|
+
} else if (character === "*") {
|
|
41145
|
+
composite = true;
|
|
41146
|
+
} else {
|
|
41147
|
+
_StdUriTemplate.validateLiteral(character, i);
|
|
41148
|
+
token.push(character);
|
|
41149
|
+
}
|
|
41150
|
+
}
|
|
41151
|
+
} else {
|
|
41152
|
+
result.push(character);
|
|
41153
|
+
}
|
|
41154
|
+
break;
|
|
41155
|
+
}
|
|
41156
|
+
}
|
|
41157
|
+
if (token === null) {
|
|
41158
|
+
return result.join("");
|
|
41159
|
+
} else {
|
|
41160
|
+
throw new Error("Unterminated token");
|
|
41161
|
+
}
|
|
41162
|
+
}
|
|
41163
|
+
static addPrefix(op, result) {
|
|
41164
|
+
switch (op) {
|
|
41165
|
+
case 2:
|
|
41166
|
+
result.push("#");
|
|
41167
|
+
break;
|
|
41168
|
+
case 3:
|
|
41169
|
+
result.push(".");
|
|
41170
|
+
break;
|
|
41171
|
+
case 4:
|
|
41172
|
+
result.push("/");
|
|
41173
|
+
break;
|
|
41174
|
+
case 5:
|
|
41175
|
+
result.push(";");
|
|
41176
|
+
break;
|
|
41177
|
+
case 6:
|
|
41178
|
+
result.push("?");
|
|
41179
|
+
break;
|
|
41180
|
+
case 7:
|
|
41181
|
+
result.push("&");
|
|
41182
|
+
break;
|
|
41183
|
+
default:
|
|
41184
|
+
return;
|
|
41185
|
+
}
|
|
41186
|
+
}
|
|
41187
|
+
static addSeparator(op, result) {
|
|
41188
|
+
switch (op) {
|
|
41189
|
+
case 3:
|
|
41190
|
+
result.push(".");
|
|
41191
|
+
break;
|
|
41192
|
+
case 4:
|
|
41193
|
+
result.push("/");
|
|
41194
|
+
break;
|
|
41195
|
+
case 5:
|
|
41196
|
+
result.push(";");
|
|
41197
|
+
break;
|
|
41198
|
+
case 6:
|
|
41199
|
+
case 7:
|
|
41200
|
+
result.push("&");
|
|
41201
|
+
break;
|
|
41202
|
+
default:
|
|
41203
|
+
result.push(",");
|
|
41204
|
+
return;
|
|
41205
|
+
}
|
|
41206
|
+
}
|
|
41207
|
+
static addValue(op, token, value, result, maxChar) {
|
|
41208
|
+
switch (op) {
|
|
41209
|
+
case 1:
|
|
41210
|
+
case 2:
|
|
41211
|
+
_StdUriTemplate.addExpandedValue(null, value, result, maxChar, false);
|
|
41212
|
+
break;
|
|
41213
|
+
case 6:
|
|
41214
|
+
case 7:
|
|
41215
|
+
result.push(`${token}=`);
|
|
41216
|
+
_StdUriTemplate.addExpandedValue(null, value, result, maxChar, true);
|
|
41217
|
+
break;
|
|
41218
|
+
case 5:
|
|
41219
|
+
result.push(token);
|
|
41220
|
+
_StdUriTemplate.addExpandedValue("=", value, result, maxChar, true);
|
|
41221
|
+
break;
|
|
41222
|
+
case 3:
|
|
41223
|
+
case 4:
|
|
41224
|
+
case 0:
|
|
41225
|
+
_StdUriTemplate.addExpandedValue(null, value, result, maxChar, true);
|
|
41226
|
+
break;
|
|
41227
|
+
}
|
|
41228
|
+
}
|
|
41229
|
+
static addValueElement(op, token, value, result, maxChar) {
|
|
41230
|
+
switch (op) {
|
|
41231
|
+
case 1:
|
|
41232
|
+
case 2:
|
|
41233
|
+
_StdUriTemplate.addExpandedValue(null, value, result, maxChar, false);
|
|
41234
|
+
break;
|
|
41235
|
+
case 6:
|
|
41236
|
+
case 7:
|
|
41237
|
+
case 5:
|
|
41238
|
+
case 3:
|
|
41239
|
+
case 4:
|
|
41240
|
+
case 0:
|
|
41241
|
+
_StdUriTemplate.addExpandedValue(null, value, result, maxChar, true);
|
|
41242
|
+
break;
|
|
41243
|
+
}
|
|
41244
|
+
}
|
|
41245
|
+
static isSurrogate(cp) {
|
|
41246
|
+
const codeUnit = cp.charCodeAt(0);
|
|
41247
|
+
return codeUnit >= 55296 && codeUnit <= 56319;
|
|
41248
|
+
}
|
|
41249
|
+
static isIprivate(cp) {
|
|
41250
|
+
return 57344 <= cp.charCodeAt(0) && cp.charCodeAt(0) <= 63743;
|
|
41251
|
+
}
|
|
41252
|
+
static isUcschar(cp) {
|
|
41253
|
+
const codePoint = cp.codePointAt(0) || 0;
|
|
41254
|
+
return 160 <= codePoint && codePoint <= 55295 || 63744 <= codePoint && codePoint <= 64975 || 65008 <= codePoint && codePoint <= 65519;
|
|
41255
|
+
}
|
|
41256
|
+
static addExpandedValue(prefix, value, result, maxChar, replaceReserved) {
|
|
41257
|
+
const stringValue = _StdUriTemplate.convertNativeTypes(value);
|
|
41258
|
+
const max = maxChar !== -1 ? Math.min(maxChar, stringValue.length) : stringValue.length;
|
|
41259
|
+
let reservedBuffer = void 0;
|
|
41260
|
+
if (max > 0 && prefix != null) {
|
|
41261
|
+
result.push(prefix);
|
|
41262
|
+
}
|
|
41263
|
+
for (let i = 0; i < max; i++) {
|
|
41264
|
+
const character = stringValue.charAt(i);
|
|
41265
|
+
if (character === "%" && !replaceReserved) {
|
|
41266
|
+
reservedBuffer = [];
|
|
41267
|
+
}
|
|
41268
|
+
let toAppend = character;
|
|
41269
|
+
if (_StdUriTemplate.isSurrogate(character)) {
|
|
41270
|
+
toAppend = encodeURIComponent(stringValue.charAt(i) + stringValue.charAt(i + 1));
|
|
41271
|
+
i++;
|
|
41272
|
+
} else if (replaceReserved || _StdUriTemplate.isUcschar(character) || _StdUriTemplate.isIprivate(character)) {
|
|
41273
|
+
if (character === "!") {
|
|
41274
|
+
toAppend = "%21";
|
|
41275
|
+
} else {
|
|
41276
|
+
toAppend = encodeURIComponent(toAppend);
|
|
41277
|
+
}
|
|
41278
|
+
}
|
|
41279
|
+
if (reservedBuffer) {
|
|
41280
|
+
reservedBuffer.push(toAppend);
|
|
41281
|
+
if (reservedBuffer.length === 3) {
|
|
41282
|
+
let isEncoded = false;
|
|
41283
|
+
try {
|
|
41284
|
+
const reserved = reservedBuffer.join("");
|
|
41285
|
+
const decoded = decodeURIComponent(reservedBuffer.join(""));
|
|
41286
|
+
isEncoded = reserved !== decoded;
|
|
41287
|
+
} catch (e) {
|
|
41288
|
+
}
|
|
41289
|
+
if (isEncoded) {
|
|
41290
|
+
result.push(reservedBuffer.join(""));
|
|
41291
|
+
} else {
|
|
41292
|
+
result.push("%25");
|
|
41293
|
+
result.push(reservedBuffer.slice(1).join(""));
|
|
41294
|
+
}
|
|
41295
|
+
reservedBuffer = void 0;
|
|
41296
|
+
}
|
|
41297
|
+
} else {
|
|
41298
|
+
if (character === " ") {
|
|
41299
|
+
result.push("%20");
|
|
41300
|
+
} else if (character === "%") {
|
|
41301
|
+
result.push("%25");
|
|
41302
|
+
} else {
|
|
41303
|
+
result.push(toAppend);
|
|
41304
|
+
}
|
|
41305
|
+
}
|
|
41306
|
+
}
|
|
41307
|
+
if (reservedBuffer) {
|
|
41308
|
+
result.push("%25");
|
|
41309
|
+
result.push(reservedBuffer.slice(1).join(""));
|
|
41310
|
+
}
|
|
41311
|
+
}
|
|
41312
|
+
static isList(value) {
|
|
41313
|
+
return Array.isArray(value) || value instanceof Set;
|
|
41314
|
+
}
|
|
41315
|
+
static isMap(value) {
|
|
41316
|
+
return value instanceof Map || typeof value === "object";
|
|
41317
|
+
}
|
|
41318
|
+
static getSubstitutionType(value, col) {
|
|
41319
|
+
if (value === void 0 || value === null) {
|
|
41320
|
+
return 0;
|
|
41321
|
+
} else if (_StdUriTemplate.isNativeType(value)) {
|
|
41322
|
+
return 1;
|
|
41323
|
+
} else if (_StdUriTemplate.isList(value)) {
|
|
41324
|
+
return 2;
|
|
41325
|
+
} else if (_StdUriTemplate.isMap(value)) {
|
|
41326
|
+
return 3;
|
|
41327
|
+
} else {
|
|
41328
|
+
throw new Error(`Illegal class passed as substitution, found ${typeof value} at col: ${col}`);
|
|
41329
|
+
}
|
|
41330
|
+
}
|
|
41331
|
+
static isEmpty(substType, value) {
|
|
41332
|
+
if (value === void 0 || value === null) {
|
|
41333
|
+
return true;
|
|
41334
|
+
} else {
|
|
41335
|
+
switch (substType) {
|
|
41336
|
+
case 1:
|
|
41337
|
+
return false;
|
|
41338
|
+
case 2:
|
|
41339
|
+
return value.length === 0;
|
|
41340
|
+
case 3:
|
|
41341
|
+
return Object.keys(value).length === 0;
|
|
41342
|
+
default:
|
|
41343
|
+
return true;
|
|
41344
|
+
}
|
|
41345
|
+
}
|
|
41346
|
+
}
|
|
41347
|
+
static isNativeType(value) {
|
|
41348
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
41349
|
+
}
|
|
41350
|
+
static convertNativeTypes(value) {
|
|
41351
|
+
if (typeof value === "string") {
|
|
41352
|
+
return value;
|
|
41353
|
+
} else if (typeof value === "number" || typeof value === "boolean") {
|
|
41354
|
+
return value.toString();
|
|
41355
|
+
} else {
|
|
41356
|
+
throw new Error(`Illegal class passed as substitution, found ${typeof value}`);
|
|
41357
|
+
}
|
|
41358
|
+
}
|
|
41359
|
+
static expandToken(operator, token, composite, maxChar, firstToken, substitutions, result, col) {
|
|
41360
|
+
if (token.length === 0) {
|
|
41361
|
+
throw new Error(`Found an empty token at col: ${col}`);
|
|
41362
|
+
}
|
|
41363
|
+
const value = substitutions[token];
|
|
41364
|
+
const substType = _StdUriTemplate.getSubstitutionType(value, col);
|
|
41365
|
+
if (substType === 0 || _StdUriTemplate.isEmpty(substType, value)) {
|
|
41366
|
+
return false;
|
|
41367
|
+
}
|
|
41368
|
+
if (firstToken) {
|
|
41369
|
+
_StdUriTemplate.addPrefix(operator, result);
|
|
41370
|
+
} else {
|
|
41371
|
+
_StdUriTemplate.addSeparator(operator, result);
|
|
41372
|
+
}
|
|
41373
|
+
switch (substType) {
|
|
41374
|
+
case 1:
|
|
41375
|
+
_StdUriTemplate.addStringValue(operator, token, value, result, maxChar);
|
|
41376
|
+
break;
|
|
41377
|
+
case 2:
|
|
41378
|
+
_StdUriTemplate.addListValue(operator, token, value, result, maxChar, composite);
|
|
41379
|
+
break;
|
|
41380
|
+
case 3:
|
|
41381
|
+
_StdUriTemplate.addMapValue(operator, token, value, result, maxChar, composite);
|
|
41382
|
+
break;
|
|
41383
|
+
}
|
|
41384
|
+
return true;
|
|
41385
|
+
}
|
|
41386
|
+
static addStringValue(operator, token, value, result, maxChar) {
|
|
41387
|
+
_StdUriTemplate.addValue(operator, token, value, result, maxChar);
|
|
41388
|
+
}
|
|
41389
|
+
static addListValue(operator, token, value, result, maxChar, composite) {
|
|
41390
|
+
let first = true;
|
|
41391
|
+
for (const v of value) {
|
|
41392
|
+
if (first) {
|
|
41393
|
+
_StdUriTemplate.addValue(operator, token, v, result, maxChar);
|
|
41394
|
+
first = false;
|
|
41395
|
+
} else {
|
|
41396
|
+
if (composite) {
|
|
41397
|
+
_StdUriTemplate.addSeparator(operator, result);
|
|
41398
|
+
_StdUriTemplate.addValue(operator, token, v, result, maxChar);
|
|
41399
|
+
} else {
|
|
41400
|
+
result.push(",");
|
|
41401
|
+
_StdUriTemplate.addValueElement(operator, token, v, result, maxChar);
|
|
41402
|
+
}
|
|
41403
|
+
}
|
|
41404
|
+
}
|
|
41405
|
+
}
|
|
41406
|
+
static addMapValue(operator, token, value, result, maxChar, composite) {
|
|
41407
|
+
let first = true;
|
|
41408
|
+
if (maxChar !== -1) {
|
|
41409
|
+
throw new Error("Value trimming is not allowed on Maps");
|
|
41410
|
+
}
|
|
41411
|
+
for (const key in value) {
|
|
41412
|
+
const v = value[key];
|
|
41413
|
+
if (composite) {
|
|
41414
|
+
if (!first) {
|
|
41415
|
+
_StdUriTemplate.addSeparator(operator, result);
|
|
41416
|
+
}
|
|
41417
|
+
_StdUriTemplate.addValueElement(operator, token, key, result, maxChar);
|
|
41418
|
+
result.push("=");
|
|
41419
|
+
} else {
|
|
41420
|
+
if (first) {
|
|
41421
|
+
_StdUriTemplate.addValue(operator, token, key, result, maxChar);
|
|
41422
|
+
} else {
|
|
41423
|
+
result.push(",");
|
|
41424
|
+
_StdUriTemplate.addValueElement(operator, token, key, result, maxChar);
|
|
41425
|
+
}
|
|
41426
|
+
result.push(",");
|
|
41427
|
+
}
|
|
41428
|
+
_StdUriTemplate.addValueElement(operator, token, v, result, maxChar);
|
|
41429
|
+
first = false;
|
|
41430
|
+
}
|
|
41431
|
+
}
|
|
41432
|
+
};
|
|
41433
|
+
exports2.StdUriTemplate = StdUriTemplate;
|
|
41434
|
+
}
|
|
41435
|
+
});
|
|
41436
|
+
|
|
39532
41437
|
// modules/std/net/url.js
|
|
39533
41438
|
var require_url = __commonJS({
|
|
39534
41439
|
"modules/std/net/url.js"(exports2, module2) {
|
|
@@ -39595,29 +41500,42 @@ ${lines.join("\n")}
|
|
|
39595
41500
|
}
|
|
39596
41501
|
return out;
|
|
39597
41502
|
}
|
|
39598
|
-
|
|
39599
|
-
|
|
39600
|
-
|
|
41503
|
+
var { StdUriTemplate } = require_dist();
|
|
41504
|
+
function _templateValue(value) {
|
|
41505
|
+
if (value == null) {
|
|
41506
|
+
return null;
|
|
39601
41507
|
}
|
|
39602
|
-
|
|
39603
|
-
|
|
39604
|
-
|
|
39605
|
-
|
|
39606
|
-
|
|
39607
|
-
|
|
39608
|
-
|
|
39609
|
-
|
|
41508
|
+
if (Array.isArray(value)) {
|
|
41509
|
+
return value.map((item) => _str(item));
|
|
41510
|
+
}
|
|
41511
|
+
if (typeof value === "boolean") {
|
|
41512
|
+
return value ? "true" : "false";
|
|
41513
|
+
}
|
|
41514
|
+
if (typeof value === "object" && !(value.bytes instanceof Uint8Array)) {
|
|
41515
|
+
const out = {};
|
|
41516
|
+
for (const key of Object.keys(value).sort()) {
|
|
41517
|
+
out[key] = _str(value[key]);
|
|
39610
41518
|
}
|
|
39611
|
-
|
|
39612
|
-
const val = encodeURIComponent(_str(values[name2]));
|
|
39613
|
-
parts.push(`${key}=${val}`);
|
|
41519
|
+
return out;
|
|
39614
41520
|
}
|
|
39615
|
-
return
|
|
41521
|
+
return _str(value);
|
|
39616
41522
|
}
|
|
39617
41523
|
function fill_template(template, values) {
|
|
39618
41524
|
const source = _str(template);
|
|
39619
|
-
const data =
|
|
39620
|
-
|
|
41525
|
+
const data = {};
|
|
41526
|
+
if (values && typeof values === "object" && !Array.isArray(values)) {
|
|
41527
|
+
for (const key of Object.keys(values)) {
|
|
41528
|
+
const converted = _templateValue(values[key]);
|
|
41529
|
+
if (converted != null) {
|
|
41530
|
+
data[key] = converted;
|
|
41531
|
+
}
|
|
41532
|
+
}
|
|
41533
|
+
}
|
|
41534
|
+
try {
|
|
41535
|
+
return StdUriTemplate.expand(source, data);
|
|
41536
|
+
} catch (err) {
|
|
41537
|
+
throw new Error(`Exception: invalid URL template: ${source}`);
|
|
41538
|
+
}
|
|
39621
41539
|
}
|
|
39622
41540
|
module2.exports = {
|
|
39623
41541
|
escape,
|
|
@@ -39628,15 +41546,16 @@ ${lines.join("\n")}
|
|
|
39628
41546
|
}
|
|
39629
41547
|
});
|
|
39630
41548
|
|
|
39631
|
-
// ../../../../../tmp/zuzu-browser-build.
|
|
41549
|
+
// ../../../../../tmp/zuzu-browser-build.gMJDcc/browser-stdlib.generated.js
|
|
39632
41550
|
var require_browser_stdlib_generated = __commonJS({
|
|
39633
|
-
"../../../../../tmp/zuzu-browser-build.
|
|
41551
|
+
"../../../../../tmp/zuzu-browser-build.gMJDcc/browser-stdlib.generated.js"(exports2, module2) {
|
|
39634
41552
|
"use strict";
|
|
39635
41553
|
function createBrowserStdlib2() {
|
|
39636
41554
|
const jsModules = /* @__PURE__ */ Object.create(null);
|
|
39637
41555
|
jsModules["/modules/javascript.js"] = require_javascript();
|
|
39638
41556
|
jsModules["/modules/std/string.js"] = require_string();
|
|
39639
41557
|
jsModules["/modules/std/string/base64.js"] = require_base64();
|
|
41558
|
+
jsModules["/modules/std/string/encode.js"] = require_encode();
|
|
39640
41559
|
jsModules["/modules/std/time.js"] = require_time();
|
|
39641
41560
|
jsModules["/modules/std/marshal.js"] = require_marshal();
|
|
39642
41561
|
jsModules["/modules/std/task.js"] = require_task();
|
|
@@ -39657,12 +41576,12 @@ ${lines.join("\n")}
|
|
|
39657
41576
|
jsModules["/modules/std/internals.js"] = require_internals();
|
|
39658
41577
|
jsModules["/modules/std/net/url.js"] = require_url();
|
|
39659
41578
|
const virtualFiles = /* @__PURE__ */ Object.create(null);
|
|
39660
|
-
virtualFiles["/modules/std/colour.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/colour - Colour parsing helpers.\n\n=head1 SYNOPSIS\n\n from std/colour import parse_colour;\n\n say( parse_colour("red") ); # #ff0000\n say( parse_colour("#abc") ); # #aabbcc\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nC<parse_colour> accepts three- and six-digit hexadecimal colours and the\nCSS3 extended colour keywords. It returns a lowercase six-digit\nhexadecimal colour string.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item C<< parse_colour(String x) >>\n\nParameters: C<x> is a CSS colour keyword or a three- or six-digit\nhexadecimal colour string. Returns: C<String>. Returns the normalized\nlowercase C<#rrggbb> colour string, or throws if C<x> is not recognised.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/colour >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/string import trim;\n\nconst _COLOUR_KEYWORDS := {\n aliceblue: "#f0f8ff",\n antiquewhite: "#faebd7",\n aqua: "#00ffff",\n aquamarine: "#7fffd4",\n azure: "#f0ffff",\n beige: "#f5f5dc",\n bisque: "#ffe4c4",\n black: "#000000",\n blanchedalmond: "#ffebcd",\n blue: "#0000ff",\n blueviolet: "#8a2be2",\n brown: "#a52a2a",\n burlywood: "#deb887",\n cadetblue: "#5f9ea0",\n chartreuse: "#7fff00",\n chocolate: "#d2691e",\n coral: "#ff7f50",\n cornflowerblue: "#6495ed",\n cornsilk: "#fff8dc",\n crimson: "#dc143c",\n cyan: "#00ffff",\n darkblue: "#00008b",\n darkcyan: "#008b8b",\n darkgoldenrod: "#b8860b",\n darkgray: "#a9a9a9",\n darkgreen: "#006400",\n darkgrey: "#a9a9a9",\n darkkhaki: "#bdb76b",\n darkmagenta: "#8b008b",\n darkolivegreen: "#556b2f",\n darkorange: "#ff8c00",\n darkorchid: "#9932cc",\n darkred: "#8b0000",\n darksalmon: "#e9967a",\n darkseagreen: "#8fbc8f",\n darkslateblue: "#483d8b",\n darkslategray: "#2f4f4f",\n darkslategrey: "#2f4f4f",\n darkturquoise: "#00ced1",\n darkviolet: "#9400d3",\n deeppink: "#ff1493",\n deepskyblue: "#00bfff",\n dimgray: "#696969",\n dimgrey: "#696969",\n dodgerblue: "#1e90ff",\n firebrick: "#b22222",\n floralwhite: "#fffaf0",\n forestgreen: "#228b22",\n fuchsia: "#ff00ff",\n gainsboro: "#dcdcdc",\n ghostwhite: "#f8f8ff",\n gold: "#ffd700",\n goldenrod: "#daa520",\n gray: "#808080",\n green: "#008000",\n greenyellow: "#adff2f",\n grey: "#808080",\n honeydew: "#f0fff0",\n hotpink: "#ff69b4",\n indianred: "#cd5c5c",\n indigo: "#4b0082",\n ivory: "#fffff0",\n khaki: "#f0e68c",\n lavender: "#e6e6fa",\n lavenderblush: "#fff0f5",\n lawngreen: "#7cfc00",\n lemonchiffon: "#fffacd",\n lightblue: "#add8e6",\n lightcoral: "#f08080",\n lightcyan: "#e0ffff",\n lightgoldenrodyellow: "#fafad2",\n lightgray: "#d3d3d3",\n lightgreen: "#90ee90",\n lightgrey: "#d3d3d3",\n lightpink: "#ffb6c1",\n lightsalmon: "#ffa07a",\n lightseagreen: "#20b2aa",\n lightskyblue: "#87cefa",\n lightslategray: "#778899",\n lightslategrey: "#778899",\n lightsteelblue: "#b0c4de",\n lightyellow: "#ffffe0",\n lime: "#00ff00",\n limegreen: "#32cd32",\n linen: "#faf0e6",\n magenta: "#ff00ff",\n maroon: "#800000",\n mediumaquamarine: "#66cdaa",\n mediumblue: "#0000cd",\n mediumorchid: "#ba55d3",\n mediumpurple: "#9370db",\n mediumseagreen: "#3cb371",\n mediumslateblue: "#7b68ee",\n mediumspringgreen: "#00fa9a",\n mediumturquoise: "#48d1cc",\n mediumvioletred: "#c71585",\n midnightblue: "#191970",\n mintcream: "#f5fffa",\n mistyrose: "#ffe4e1",\n moccasin: "#ffe4b5",\n navajowhite: "#ffdead",\n navy: "#000080",\n oldlace: "#fdf5e6",\n olive: "#808000",\n olivedrab: "#6b8e23",\n orange: "#ffa500",\n orangered: "#ff4500",\n orchid: "#da70d6",\n palegoldenrod: "#eee8aa",\n palegreen: "#98fb98",\n paleturquoise: "#afeeee",\n palevioletred: "#db7093",\n papayawhip: "#ffefd5",\n peachpuff: "#ffdab9",\n peru: "#cd853f",\n pink: "#ffc0cb",\n plum: "#dda0dd",\n powderblue: "#b0e0e6",\n purple: "#800080",\n red: "#ff0000",\n rosybrown: "#bc8f8f",\n royalblue: "#4169e1",\n saddlebrown: "#8b4513",\n salmon: "#fa8072",\n sandybrown: "#f4a460",\n seagreen: "#2e8b57",\n seashell: "#fff5ee",\n sienna: "#a0522d",\n silver: "#c0c0c0",\n skyblue: "#87ceeb",\n slateblue: "#6a5acd",\n slategray: "#708090",\n slategrey: "#708090",\n snow: "#fffafa",\n springgreen: "#00ff7f",\n steelblue: "#4682b4",\n tan: "#d2b48c",\n teal: "#008080",\n thistle: "#d8bfd8",\n tomato: "#ff6347",\n turquoise: "#40e0d0",\n violet: "#ee82ee",\n wheat: "#f5deb3",\n white: "#ffffff",\n whitesmoke: "#f5f5f5",\n yellow: "#ffff00",\n yellowgreen: "#9acd32",\n};\n\nfunction parse_colour ( String x ) {\n let text := lc( trim(x) );\n\n if ( text ~ /^#[0-9a-f]{6}$/ ) {\n return text;\n }\n\n let short := text ~ /^#([0-9a-f])([0-9a-f])([0-9a-f])$/;\n if ( short ) {\n return "#"\n _ short[1] _ short[1]\n _ short[2] _ short[2]\n _ short[3] _ short[3];\n }\n\n if ( _COLOUR_KEYWORDS.exists(text) ) {\n return _COLOUR_KEYWORDS.get(text);\n }\n\n die `Invalid colour: ${x}`;\n}\n';
|
|
41579
|
+
virtualFiles["/modules/std/colour.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/colour - Colour parsing helpers.\n\n=head1 SYNOPSIS\n\n from std/colour import parse_colour;\n\n say( parse_colour("red") ); # #ff0000\n say( parse_colour("#abc") ); # #aabbcc\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nC<parse_colour> accepts three- and six-digit hexadecimal colours and the\nCSS3 extended colour keywords. It returns a lowercase six-digit\nhexadecimal colour string.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item C<< parse_colour(String x) >>\n\nParameters: C<x> is a CSS colour keyword or a three- or six-digit\nhexadecimal colour string. Returns: C<String>. Returns the normalized\nlowercase C<#rrggbb> colour string, or throws if C<x> is not recognised.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/colour >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/string import trim;\n\nconst _COLOUR_KEYWORDS := {\n aliceblue: "#f0f8ff",\n antiquewhite: "#faebd7",\n aqua: "#00ffff",\n aquamarine: "#7fffd4",\n azure: "#f0ffff",\n beige: "#f5f5dc",\n bisque: "#ffe4c4",\n black: "#000000",\n blanchedalmond: "#ffebcd",\n blue: "#0000ff",\n blueviolet: "#8a2be2",\n brown: "#a52a2a",\n burlywood: "#deb887",\n cadetblue: "#5f9ea0",\n chartreuse: "#7fff00",\n chocolate: "#d2691e",\n coral: "#ff7f50",\n cornflowerblue: "#6495ed",\n cornsilk: "#fff8dc",\n crimson: "#dc143c",\n cyan: "#00ffff",\n darkblue: "#00008b",\n darkcyan: "#008b8b",\n darkgoldenrod: "#b8860b",\n darkgray: "#a9a9a9",\n darkgreen: "#006400",\n darkgrey: "#a9a9a9",\n darkkhaki: "#bdb76b",\n darkmagenta: "#8b008b",\n darkolivegreen: "#556b2f",\n darkorange: "#ff8c00",\n darkorchid: "#9932cc",\n darkred: "#8b0000",\n darksalmon: "#e9967a",\n darkseagreen: "#8fbc8f",\n darkslateblue: "#483d8b",\n darkslategray: "#2f4f4f",\n darkslategrey: "#2f4f4f",\n darkturquoise: "#00ced1",\n darkviolet: "#9400d3",\n deeppink: "#ff1493",\n deepskyblue: "#00bfff",\n dimgray: "#696969",\n dimgrey: "#696969",\n dodgerblue: "#1e90ff",\n firebrick: "#b22222",\n floralwhite: "#fffaf0",\n forestgreen: "#228b22",\n fuchsia: "#ff00ff",\n gainsboro: "#dcdcdc",\n ghostwhite: "#f8f8ff",\n gold: "#ffd700",\n goldenrod: "#daa520",\n gray: "#808080",\n green: "#008000",\n greenyellow: "#adff2f",\n grey: "#808080",\n honeydew: "#f0fff0",\n hotpink: "#ff69b4",\n indianred: "#cd5c5c",\n indigo: "#4b0082",\n ivory: "#fffff0",\n khaki: "#f0e68c",\n lavender: "#e6e6fa",\n lavenderblush: "#fff0f5",\n lawngreen: "#7cfc00",\n lemonchiffon: "#fffacd",\n lightblue: "#add8e6",\n lightcoral: "#f08080",\n lightcyan: "#e0ffff",\n lightgoldenrodyellow: "#fafad2",\n lightgray: "#d3d3d3",\n lightgreen: "#90ee90",\n lightgrey: "#d3d3d3",\n lightpink: "#ffb6c1",\n lightsalmon: "#ffa07a",\n lightseagreen: "#20b2aa",\n lightskyblue: "#87cefa",\n lightslategray: "#778899",\n lightslategrey: "#778899",\n lightsteelblue: "#b0c4de",\n lightyellow: "#ffffe0",\n lime: "#00ff00",\n limegreen: "#32cd32",\n linen: "#faf0e6",\n magenta: "#ff00ff",\n maroon: "#800000",\n mediumaquamarine: "#66cdaa",\n mediumblue: "#0000cd",\n mediumorchid: "#ba55d3",\n mediumpurple: "#9370db",\n mediumseagreen: "#3cb371",\n mediumslateblue: "#7b68ee",\n mediumspringgreen: "#00fa9a",\n mediumturquoise: "#48d1cc",\n mediumvioletred: "#c71585",\n midnightblue: "#191970",\n mintcream: "#f5fffa",\n mistyrose: "#ffe4e1",\n moccasin: "#ffe4b5",\n navajowhite: "#ffdead",\n navy: "#000080",\n oldlace: "#fdf5e6",\n olive: "#808000",\n olivedrab: "#6b8e23",\n orange: "#ffa500",\n orangered: "#ff4500",\n orchid: "#da70d6",\n palegoldenrod: "#eee8aa",\n palegreen: "#98fb98",\n paleturquoise: "#afeeee",\n palevioletred: "#db7093",\n papayawhip: "#ffefd5",\n peachpuff: "#ffdab9",\n peru: "#cd853f",\n pink: "#ffc0cb",\n plum: "#dda0dd",\n powderblue: "#b0e0e6",\n purple: "#800080",\n rebeccapurple: "#663399",\n red: "#ff0000",\n rosybrown: "#bc8f8f",\n royalblue: "#4169e1",\n saddlebrown: "#8b4513",\n salmon: "#fa8072",\n sandybrown: "#f4a460",\n seagreen: "#2e8b57",\n seashell: "#fff5ee",\n sienna: "#a0522d",\n silver: "#c0c0c0",\n skyblue: "#87ceeb",\n slateblue: "#6a5acd",\n slategray: "#708090",\n slategrey: "#708090",\n snow: "#fffafa",\n springgreen: "#00ff7f",\n steelblue: "#4682b4",\n tan: "#d2b48c",\n teal: "#008080",\n thistle: "#d8bfd8",\n tomato: "#ff6347",\n turquoise: "#40e0d0",\n violet: "#ee82ee",\n wheat: "#f5deb3",\n white: "#ffffff",\n whitesmoke: "#f5f5f5",\n yellow: "#ffff00",\n yellowgreen: "#9acd32",\n};\n\nfunction parse_colour ( String x ) {\n let text := lc( trim(x) );\n\n if ( text ~ /^#[0-9a-f]{6}$/ ) {\n return text;\n }\n\n let short := text ~ /^#([0-9a-f])([0-9a-f])([0-9a-f])$/;\n if ( short ) {\n return "#"\n _ short[1] _ short[1]\n _ short[2] _ short[2]\n _ short[3] _ short[3];\n }\n\n if ( _COLOUR_KEYWORDS.exists(text) ) {\n return _COLOUR_KEYWORDS.get(text);\n }\n\n die `Invalid colour: ${x}`;\n}\n';
|
|
39661
41580
|
virtualFiles["/modules/std/result.zzm"] = "=encoding utf8\n\n=head1 NAME\n\nstd/result - A simple Result object for explicit success and failure values.\n\n=head1 SYNOPSIS\n\n from std/result import Result;\n\n let r := Result.ok(42);\n\n if ( r.is_ok() ) {\n say r.unwrap();\n }\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nC<Result> is a small, subclassable object modelled on a simplified version\nof Rust's C<Result> concept. It is useful when a function, task, or worker\nwants to return an explicit success or failure value without throwing an\nexception.\n\nIt is a normal ZuzuScript class. Workers do not require C<Result>; any value\nsupported by C<std/marshal> may be returned.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<Result>\n\nContainer for either an ok value or an error value.\n\n=over\n\n=item C<< Result.ok(value) >>\n\nParameters: C<value> is any success value. Returns: C<Result>. Creates an\nok result wrapping C<value>.\n\n=item C<< Result.err(error) >>\n\nParameters: C<error> is any error value. Returns: C<Result>. Creates an\nerror result wrapping C<error>.\n\n=item C<< result.is_ok() >>\n\nParameters: none. Returns: C<Boolean>. Returns true when the result is an\nok value.\n\n=item C<< result.is_err() >>\n\nParameters: none. Returns: C<Boolean>. Returns true when the result is an\nerror value.\n\n=item C<< result.value() >>\n\nParameters: none. Returns: value. Returns the stored ok value, or\nC<null> for an error result.\n\n=item C<< result.error() >>\n\nParameters: none. Returns: value. Returns the stored error value, or\nC<null> for an ok result.\n\n=item C<< result.unwrap() >>\n\nParameters: none. Returns: value. Returns the ok value, or throws if the\nresult is an error.\n\n=item C<< result.unwrap_err() >>\n\nParameters: none. Returns: value. Returns the error value, or throws if\nthe result is ok.\n\n=back\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/result >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nclass Result {\n let Boolean _is_ok := true;\n let _value := null;\n let _error := null;\n\n static method ok ( value ) {\n return new self(\n _is_ok: true,\n _value: value,\n _error: null,\n );\n }\n\n static method err ( error ) {\n return new self(\n _is_ok: false,\n _value: null,\n _error: error,\n );\n }\n\n method is_ok () {\n return _is_ok;\n }\n\n method is_err () {\n return not _is_ok;\n }\n\n method value () {\n return _value;\n }\n\n method error () {\n return _error;\n }\n\n method unwrap () {\n if ( _is_ok ) {\n return _value;\n }\n\n die `called Result.unwrap() on an err value: ${_error}`;\n }\n\n method unwrap_err () {\n if ( not _is_ok ) {\n return _error;\n }\n\n die `called Result.unwrap_err() on an ok value: ${_value}`;\n }\n}\n";
|
|
39662
41581
|
virtualFiles["/modules/std/string/quoted_printable.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/string/quoted_printable - Quoted-printable encoders and decoders.\n\n=head1 SYNOPSIS\n\n from std/string/quoted_printable import encode, decode;\n\n let raw := to_binary( "Hello, world!\\r\\n" );\n\n let text := encode(raw);\n let bytes := decode(text);\n\n let binary_text := encode(raw, binary: true);\n let short_lines := encode(raw, line_length: 40, newline: "\\n");\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module provides quoted-printable encoding and decoding helpers for\nRFC 2045-style byte transport. Encoding returns ASCII C<String> text.\nDecoding returns a C<BinaryString>, because quoted-printable is a byte\ntransfer encoding rather than a Unicode text format.\n\nThe C<binary> option controls how input line break bytes are encoded.\nIn the default non-binary mode, CRLF, CR, and LF bytes are normalized to\nthe configured C<newline> string. In binary mode, CR and LF bytes are\nencoded as C<=0D> and C<=0A>.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item * C<encode(BinaryString bytes, ... PairList options)>\n\nParameters: C<bytes> is binary input data and C<options> controls\nencoding. Returns: C<String>. Encodes C<bytes> as quoted-printable ASCII\ntext.\n\n=item * C<decode(String text, ... PairList options)>\n\nParameters: C<text> is quoted-printable text and C<options> controls\nstrictness. Returns: C<BinaryString>. Decodes quoted-printable text into\nbytes.\n\n=back\n\n=head1 OPTIONS\n\n=over\n\n=item * C<line_length>\n\nMaximum encoded line length. Defaults to C<76> and must be at least\nC<4>.\n\n=item * C<newline>\n\nOutput newline for hard line breaks and encoded soft breaks. Defaults\nto CRLF.\n\n=item * C<binary>\n\nWhen true, encode CR and LF bytes as C<=0D> and C<=0A>. Defaults to\nfalse.\n\n=item * C<strict>\n\nWhen true, malformed quoted-printable escape sequences throw during\ndecoding. Non-strict decoding preserves malformed escape text\nliterally.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/string/quoted_printable >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\n\nlet encode := null;\nlet decode := null;\n\n{\n from std/string import chr, index, ord, substr;\n from std/string/base64 import\n encode as _base64_encode,\n decode as _base64_decode;\n\n let _B64_ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\n _ "abcdefghijklmnopqrstuvwxyz0123456789+/";\n let _HEX := "0123456789ABCDEF";\n\n function _div_floor ( Number n, Number d ) {\n return floor( n / d );\n }\n\n function _mod ( Number n, Number d ) {\n return n - _div_floor( n, d ) * d;\n }\n\n function _bytes_to_binary ( Array bytes ) {\n let out := "";\n let i := 0;\n let n := bytes.length();\n\n while ( i < n ) {\n let b0 := bytes[i];\n let b1 := null;\n let b2 := null;\n if ( i + 1 < n ) {\n b1 := bytes[i + 1];\n }\n if ( i + 2 < n ) {\n b2 := bytes[i + 2];\n }\n\n let c0 := _div_floor( b0, 4 );\n let c1 := _mod( b0, 4 ) * 16;\n let c2 := 64;\n let c3 := 64;\n\n if ( not( b1 == null ) ) {\n c1 += _div_floor( b1, 16 );\n c2 := _mod( b1, 16 ) * 4;\n if ( not( b2 == null ) ) {\n c2 += _div_floor( b2, 64 );\n c3 := _mod( b2, 64 );\n }\n }\n\n out _= substr( _B64_ALPHABET, c0, 1 );\n out _= substr( _B64_ALPHABET, c1, 1 );\n out _= c2 == 64 ? "=" : substr( _B64_ALPHABET, c2, 1 );\n out _= c3 == 64 ? "=" : substr( _B64_ALPHABET, c3, 1 );\n i += 3;\n }\n\n return _base64_decode(out);\n }\n\n function _binary_to_bytes ( BinaryString raw ) {\n let b64 := _base64_encode(raw);\n let out := [];\n let i := 0;\n let n := length b64;\n\n while ( i < n ) {\n let c0 := index( _B64_ALPHABET, substr( b64, i, 1 ) );\n let c1 := index( _B64_ALPHABET, substr( b64, i + 1, 1 ) );\n let ch2 := substr( b64, i + 2, 1 );\n let ch3 := substr( b64, i + 3, 1 );\n let c2 := -1;\n let c3 := -1;\n if ( ch2 ne "=" ) {\n c2 := index( _B64_ALPHABET, ch2 );\n }\n if ( ch3 ne "=" ) {\n c3 := index( _B64_ALPHABET, ch3 );\n }\n\n out.push( c0 * 4 + _div_floor( c1, 16 ) );\n if ( c2 >= 0 ) {\n out.push( _mod( c1, 16 ) * 16 + _div_floor( c2, 4 ) );\n }\n if ( c3 >= 0 ) {\n out.push( _mod( c2, 4 ) * 64 + c3 );\n }\n\n i += 4;\n }\n\n return out;\n }\n\n function _parse_options ( PairList options ) {\n let line_length := 76;\n let newline := "\\r\\n";\n let binary := false;\n let strict := false;\n\n for ( let option in options.enumerate() ) {\n let key := option.key;\n let value := option.value;\n\n if ( key eq "line_length" ) {\n line_length := value;\n }\n else if ( key eq "newline" ) {\n newline := value;\n }\n else if ( key eq "binary" ) {\n binary := value;\n }\n else if ( key eq "strict" ) {\n strict := value;\n }\n else {\n die `quoted_printable option \'${key}\' is not supported`;\n }\n }\n\n if ( not( line_length instanceof Number ) ) {\n die "quoted_printable line_length option expects Number";\n }\n if ( line_length < 4 ) {\n die "quoted_printable line_length option must be at least 4";\n }\n if ( not( newline instanceof String ) ) {\n die "quoted_printable newline option expects String";\n }\n if ( not( binary instanceof Boolean ) ) {\n die "quoted_printable binary option expects Boolean";\n }\n if ( not( strict instanceof Boolean ) ) {\n die "quoted_printable strict option expects Boolean";\n }\n\n return {\n line_length: int(line_length),\n newline: newline,\n binary: binary,\n strict: strict,\n };\n }\n\n function _is_safe_literal ( Number b ) {\n return ( b >= 33 and b <= 60 ) or ( b >= 62 and b <= 126 );\n }\n\n function _byte_to_hex_token ( Number b ) {\n return "="\n _ substr( _HEX, _div_floor( b, 16 ), 1 )\n _ substr( _HEX, _mod( b, 16 ), 1 );\n }\n\n function _simple_token_length ( Number b, Boolean final_byte ) {\n if ( ( b == 9 or b == 32 ) and not final_byte ) {\n return 1;\n }\n if ( _is_safe_literal(b) ) {\n return 1;\n }\n return 3;\n }\n\n function _space_tab_needs_escape (\n Array bytes,\n Number i,\n Number column,\n Number line_length,\n ) {\n let n := bytes.length();\n if ( i + 1 >= n ) {\n return true;\n }\n\n let j := i + 1;\n while ( j < n and ( bytes[j] == 9 or bytes[j] == 32 ) ) {\n j++;\n }\n if ( j >= n ) {\n return true;\n }\n\n let next_is_final := i + 2 >= n;\n let next_len := _simple_token_length( bytes[i + 1], next_is_final );\n let max := next_is_final ? line_length : line_length - 1;\n return column + 1 + next_len > max;\n }\n\n function _token_for_byte (\n Array bytes,\n Number i,\n Number column,\n Number line_length,\n ) {\n let b := bytes[i];\n\n if ( b == 9 or b == 32 ) {\n if ( _space_tab_needs_escape( bytes, i, column, line_length ) ) {\n return _byte_to_hex_token(b);\n }\n return chr(b);\n }\n\n if ( _is_safe_literal(b) ) {\n return chr(b);\n }\n\n return _byte_to_hex_token(b);\n }\n\n function _emit_token (\n String out,\n Number column,\n String token,\n Boolean more_after,\n Number line_length,\n String newline,\n ) {\n let max := more_after ? line_length - 1 : line_length;\n let updated_out := out;\n let updated_column := column;\n\n if ( updated_column > 0 and updated_column + ( length token ) > max ) {\n updated_out _= "=" _ newline;\n updated_column := 0;\n }\n\n updated_out _= token;\n updated_column += length token;\n\n return [ updated_out, updated_column ];\n }\n\n function _encode_segment (\n Array bytes,\n Number line_length,\n String newline,\n ) {\n let out := "";\n let column := 0;\n let i := 0;\n let n := bytes.length();\n\n while ( i < n ) {\n let token := _token_for_byte( bytes, i, column, line_length );\n let emitted := _emit_token(\n out,\n column,\n token,\n i + 1 < n,\n line_length,\n newline,\n );\n out := emitted[0];\n column := emitted[1];\n i++;\n }\n\n return out;\n }\n\n function _encode_text_bytes (\n Array bytes,\n Number line_length,\n String newline,\n ) {\n let out := "";\n let line := [];\n let i := 0;\n let n := bytes.length();\n\n while ( i < n ) {\n let b := bytes[i];\n if ( b == 13 or b == 10 ) {\n out _= _encode_segment( line, line_length, newline );\n out _= newline;\n line := [];\n\n if ( b == 13 and i + 1 < n and bytes[i + 1] == 10 ) {\n i++;\n }\n }\n else {\n line.push(b);\n }\n\n i++;\n }\n\n out _= _encode_segment( line, line_length, newline );\n return out;\n }\n\n function _hex_value ( String ch ) {\n let cp := ord(ch);\n if ( cp >= 48 and cp <= 57 ) {\n return cp - 48;\n }\n if ( cp >= 65 and cp <= 70 ) {\n return cp - 55;\n }\n if ( cp >= 97 and cp <= 102 ) {\n return cp - 87;\n }\n return -1;\n }\n\n function _decode_text_bytes ( String text, Boolean strict ) {\n let out := [];\n let i := 0;\n let n := length text;\n\n while ( i < n ) {\n let ch := substr( text, i, 1 );\n let cp := ord( text, i );\n\n if ( cp > 127 ) {\n die "quoted_printable.decode rejects non-ASCII input";\n }\n\n if ( ch eq "=" ) {\n if ( i + 1 >= n ) {\n die "malformed quoted-printable escape" if strict;\n out.push(61);\n i++;\n next;\n }\n\n let ch1 := substr( text, i + 1, 1 );\n if ( ch1 eq "\\r" ) {\n if ( i + 2 < n and substr( text, i + 2, 1 ) eq "\\n" ) {\n i += 3;\n }\n else {\n i += 2;\n }\n next;\n }\n if ( ch1 eq "\\n" ) {\n i += 2;\n next;\n }\n\n if ( i + 2 < n ) {\n let hi := _hex_value(ch1);\n let lo := _hex_value( substr( text, i + 2, 1 ) );\n if ( hi >= 0 and lo >= 0 ) {\n out.push( hi * 16 + lo );\n i += 3;\n next;\n }\n }\n\n die "malformed quoted-printable escape" if strict;\n out.push(61);\n i++;\n next;\n }\n\n out.push(cp);\n i++;\n }\n\n return out;\n }\n\n encode := function ( BinaryString bytes, ... PairList options ) {\n let opts := _parse_options(options);\n let raw := _binary_to_bytes(bytes);\n\n if ( opts{binary} ) {\n return _encode_segment(\n raw,\n opts{line_length},\n opts{newline},\n );\n }\n\n return _encode_text_bytes(\n raw,\n opts{line_length},\n opts{newline},\n );\n };\n\n decode := function ( String text, ... PairList options ) {\n let opts := _parse_options(options);\n return _bytes_to_binary( _decode_text_bytes( text, opts{strict} ) );\n };\n}\n';
|
|
39663
41582
|
virtualFiles["/modules/std/gui.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/gui - User-facing GUI constructor helpers.\n\n=head1 SYNOPSIS\n\n from std/gui import *;\n\n let w := Window(\n title: "Demo",\n VBox(\n Label( text: "Name:" ),\n Input( id: "name" ),\n Button( text: "OK", id: "submit" ),\n ),\n );\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Electron.\nIt is not supported by zuzu-js on Node. It is partially supported by\nzuzu-js in the browser: core GUI and widget lifecycle coverage passes,\nbut filesystem-backed file and directory dialogue coverage is unsupported.\n\n=head1 DESCRIPTION\n\nThis module provides thin constructor helpers over C<std/gui/objects>.\nHost runtimes expose the shared widget, object tree, event, and window\nlifecycle APIs when GUI support is available. It also re-exports\nbackend-native file and directory dialogue hooks for C<std/gui/dialogue>.\n\nThe module exports C<EM>, the standard UI font height in logical\npixels, derived from C<std/gui/objects> metadata.\n\n=head1 EXPORTS\n\n=head2 Constants\n\n=over\n\n=item C<EM>\n\nType: C<Number>. Standard UI font height in logical pixels.\n\n=item C<GUI_XML_NS>\n\nType: C<String>. XML namespace URI used by GUI XML serialization and\nparsing.\n\n=back\n\n=head2 Functions\n\n=over\n\n=item C<< Window(... PairList p, Array c) >>, C<< VBox(... PairList p, Array c) >>, C<< HBox(... PairList p, Array c) >>, C<< Frame(... PairList p, Array c) >>\n\nParameters: C<p> are widget properties and C<c> contains child widgets.\nReturns: widget object. Constructs window and layout widgets.\n\n=item C<< Label(... PairList p, Array c) >>, C<< Text(... PairList p, Array c) >>, C<< RichText(... PairList p, Array c) >>, C<< Image(... PairList p, Array c) >>\n\nParameters: C<p> are widget properties and C<c> contains child widgets.\nReturns: widget object. Constructs content widgets.\n\n=item C<< Input(... PairList p, Array c) >>, C<< DatePicker(... PairList p, Array c) >>, C<< Checkbox(... PairList p, Array c) >>, C<< Radio(... PairList p, Array c) >>, C<< RadioGroup(... PairList p, Array c) >>, C<< Select(... PairList p, Array c) >>\n\nParameters: C<p> are widget properties and C<c> contains child widgets.\nReturns: widget object. Constructs input widgets.\n\n=item C<< Menu(... PairList p, Array c) >>, C<< MenuItem(... PairList p, Array c) >>, C<< Button(... PairList p, Array c) >>, C<< Separator(... PairList p, Array c) >>, C<< Slider(... PairList p, Array c) >>, C<< Progress(... PairList p, Array c) >>\n\nParameters: C<p> are widget properties and C<c> contains child widgets.\nReturns: widget object. Constructs command and control widgets.\n\n=item C<< Tabs(... PairList p, Array c) >>, C<< Tab(... PairList p, Array c) >>, C<< ListView(... PairList p, Array c) >>, C<< TreeView(... PairList p, Array c) >>\n\nParameters: C<p> are widget properties and C<c> contains child widgets.\nReturns: widget object. Constructs tabular and collection widgets.\n\n=item C<< unbind(BindingToken token) >>\n\nParameters: C<token> is a binding token. Returns: C<null>. Removes a GUI\nbinding.\n\n=item C<< gui_from_xml(String xml) >>, C<< gui_from_xml_file(path) >>\n\nParameters: C<xml> is GUI XML text and C<path> is a file path. Returns:\nwidget object. Builds a GUI object tree from XML.\n\n=item C<< gui_to_xml(Widget root) >>\n\nParameters: C<root> is a GUI widget. Returns: C<String>. Serializes a\nGUI object tree to XML.\n\n=back\n\n=head2 Classes\n\n=over\n\n=item C<BindingToken>\n\nRepresents a model/widget binding.\n\n=over\n\n=item C<< token.is_active() >>\n\nParameters: none. Returns: C<Boolean>. Returns true while the binding is\nactive.\n\n=item C<< token.set_listener(token) >>\n\nParameters: C<token> is a listener token. Returns: C<BindingToken>.\nStores the listener token associated with the binding.\n\n=item C<< token.sync_model_to_widget() >>, C<< token.sync_widget_to_model() >>\n\nParameters: none. Returns: C<null>. Synchronizes the bound values.\n\n=item C<< token.unbind() >>\n\nParameters: none. Returns: C<null>. Removes the binding.\n\n=back\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/gui >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/gui/objects import\n Window as _WindowClass,\n VBox as _VBoxClass,\n HBox as _HBoxClass,\n Frame as _FrameClass,\n Label as _LabelClass,\n Text as _TextClass,\n RichText as _RichTextClass,\n Image as _ImageClass,\n Input as _InputClass,\n DatePicker as _DatePickerClass,\n Checkbox as _CheckboxClass,\n Radio as _RadioClass,\n RadioGroup as _RadioGroupClass,\n Select as _SelectClass,\n Menu as _MenuClass,\n MenuItem as _MenuItemClass,\n Button as _ButtonClass,\n Separator as _SeparatorClass,\n Slider as _SliderClass,\n Progress as _ProgressClass,\n Tabs as _TabsClass,\n Tab as _TabClass,\n ListView as _ListViewClass,\n TreeView as _TreeViewClass,\n Widget,\n Event,\n ListenerToken,\n native_file_open,\n native_file_save,\n native_directory_open,\n native_directory_save,\n native_colour_picker,\n meta as _gui_meta;\n\nfrom std/gui/objects try import\n native_alert,\n native_confirm,\n native_prompt;\n\nfrom std/data/xml import XML;\nfrom std/data/xml/escape import escape_xml;\nfrom std/internals import getupperprop;\nfrom std/path/zz import ZZPath;\nfrom std/string import join, split, substr, trim;\n\n\nconst Number EM := _gui_meta{font_size_pixels};\n\nfunction _assert_known_props ( String ctor, PairList props, Array allowed ) {\n let geometry := [\n "width",\n "height",\n "minwidth",\n "minheight",\n "maxwidth",\n "maxheight",\n ];\n for ( let key in props.keys() ) {\n if ( key \u2209 allowed and key \u2209 geometry ) {\n die `GUI_PROP_UNKNOWN: ${ctor} does not accept property \'${key}\'`;\n }\n }\n}\n\nfunction _assert_prop_value ( String ctor, String prop, value, Array allowed ) {\n if ( value \u2209 allowed ) {\n die `GUI_PROP_TYPE: ${ctor} property \'${prop}\' has invalid value`;\n }\n}\n\nfunction _assert_prop_array ( String ctor, String prop, value ) {\n if ( not( value instanceof Array ) ) {\n die `GUI_PROP_TYPE: ${ctor} property \'${prop}\' expects Array`;\n }\n}\n\nfunction _with_geometry_props ( Array allowed ) {\n for ( let key in [\n "width",\n "height",\n "minwidth",\n "minheight",\n "maxwidth",\n "maxheight",\n ] ) {\n allowed.push(key) unless key \u2208 allowed;\n }\n return allowed;\n}\n\nfunction _apply_geometry ( Widget widget, PairList p ) {\n for ( let key in [\n "width",\n "height",\n "minwidth",\n "minheight",\n "maxwidth",\n "maxheight",\n ] ) {\n if ( p.has(key) ) {\n widget.(key)( p.get(key) );\n }\n }\n return widget;\n}\n\nfunction Window ( ... PairList p, Array c ) {\n _assert_known_props(\n "Window",\n p,\n _with_geometry_props( [\n "id",\n "title",\n "width",\n "height",\n "resizable",\n "modal",\n "visible",\n "enabled",\n "disabled",\n ] ),\n );\n\n return new _WindowClass(\n id: p.get( "id", null ),\n title: p.get( "title", "" ),\n width: p.get( "width", 800 ),\n height: p.get( "height", 600 ),\n minwidth: p.get( "minwidth", null ),\n minheight: p.get( "minheight", null ),\n maxwidth: p.get( "maxwidth", null ),\n maxheight: p.get( "maxheight", null ),\n resizable: p.get( "resizable", true ),\n modal: p.get( "modal", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n );\n}\n\nfunction VBox ( ... PairList p, Array c ) {\n _assert_known_props(\n "VBox",\n p,\n [\n "id",\n "align",\n "gap",\n "padding",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n _assert_prop_value(\n "VBox",\n "align",\n p.get( "align", "top" ),\n [ "top", "centre", "bottom", "stretch" ],\n );\n\n return _apply_geometry( new _VBoxClass(\n id: p.get( "id", null ),\n align: p.get( "align", "top" ),\n gap: p.get( "gap", 0 ),\n padding: p.get( "padding", 0 ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction HBox ( ... PairList p, Array c ) {\n _assert_known_props(\n "HBox",\n p,\n _with_geometry_props( [\n "id",\n "align",\n "gap",\n "padding",\n "visible",\n "enabled",\n "disabled",\n ] ),\n );\n\n _assert_prop_value(\n "HBox",\n "align",\n p.get( "align", "left" ),\n [ "left", "centre", "right", "stretch" ],\n );\n\n return new _HBoxClass(\n id: p.get( "id", null ),\n align: p.get( "align", "left" ),\n gap: p.get( "gap", 0 ),\n padding: p.get( "padding", 0 ),\n width: p.get( "width", null ),\n height: p.get( "height", null ),\n minwidth: p.get( "minwidth", null ),\n minheight: p.get( "minheight", null ),\n maxwidth: p.get( "maxwidth", null ),\n maxheight: p.get( "maxheight", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n );\n}\n\nfunction Frame ( ... PairList p, Array c ) {\n _assert_known_props(\n "Frame",\n p,\n [\n "id",\n "label",\n "collapsible",\n "collapsed",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _FrameClass(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n collapsible: p.get( "collapsible", false ),\n collapsed: p.get( "collapsed", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Label ( ... PairList p, Array c ) {\n _assert_known_props(\n "Label",\n p,\n [ "id", "text", "for", "visible", "enabled", "disabled" ],\n );\n\n let label := new _LabelClass(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n );\n if ( p.has("for") ) {\n label.set_for_id( p.get( "for", null ) );\n }\n\n return _apply_geometry( label, p );\n}\n\nfunction Text ( ... PairList p, Array c ) {\n _assert_known_props(\n "Text",\n p,\n [\n "id",\n "value",\n "multiline",\n "readonly",\n "wrap",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _TextClass(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n multiline: p.get( "multiline", false ),\n readonly: p.get( "readonly", false ),\n wrap: p.get( "wrap", true ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction RichText ( ... PairList p, Array c ) {\n _assert_known_props(\n "RichText",\n p,\n [\n "id",\n "value",\n "multiline",\n "readonly",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _RichTextClass(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n multiline: p.get( "multiline", true ),\n readonly: p.get( "readonly", true ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Image ( ... PairList p, Array c ) {\n _assert_known_props(\n "Image",\n p,\n [ "id", "src", "alt", "fit", "visible", "enabled", "disabled" ],\n );\n\n _assert_prop_value(\n "Image",\n "fit",\n p.get( "fit", "none" ),\n [ "none", "contain", "cover", "stretch" ],\n );\n\n return _apply_geometry( new _ImageClass(\n id: p.get( "id", null ),\n src: p.get( "src", "" ),\n alt: p.get( "alt", "" ),\n fit: p.get( "fit", "none" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Input ( ... PairList p, Array c ) {\n _assert_known_props(\n "Input",\n p,\n [\n "id",\n "value",\n "placeholder",\n "multiline",\n "readonly",\n "password",\n "required",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _InputClass(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n placeholder: p.get( "placeholder", "" ),\n multiline: p.get( "multiline", false ),\n readonly: p.get( "readonly", false ),\n password: p.get( "password", false ),\n required: p.get( "required", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction DatePicker ( ... PairList p, Array c ) {\n _assert_known_props(\n "DatePicker",\n p,\n [\n "id",\n "value",\n "min",\n "max",\n "first_day_of_week",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _DatePickerClass(\n id: p.get( "id", null ),\n value: p.get( "value", null ),\n min: p.get( "min", null ),\n max: p.get( "max", null ),\n first_day_of_week: p.get( "first_day_of_week", 0 ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Checkbox ( ... PairList p, Array c ) {\n _assert_known_props(\n "Checkbox",\n p,\n [\n "id",\n "label",\n "checked",\n "indeterminate",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _CheckboxClass(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n checked: p.get( "checked", false ),\n indeterminate: p.get( "indeterminate", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Radio ( ... PairList p, Array c ) {\n _assert_known_props(\n "Radio",\n p,\n [\n "id",\n "label",\n "value",\n "group",\n "checked",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _RadioClass(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n value: p.get( "value", "" ),\n group: p.get( "group", null ),\n checked: p.get( "checked", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction RadioGroup ( ... PairList p, Array c ) {\n _assert_known_props(\n "RadioGroup",\n p,\n [\n "id",\n "name",\n "value",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _RadioGroupClass(\n id: p.get( "id", null ),\n name: p.get( "name", "" ),\n value: p.get( "value", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Select ( ... PairList p, Array c ) {\n _assert_known_props(\n "Select",\n p,\n [\n "id",\n "value",\n "options",\n "multiple",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n if ( p.has("options") ) {\n _assert_prop_array( "Select", "options", p.get("options") );\n }\n\n return _apply_geometry( new _SelectClass(\n id: p.get( "id", null ),\n value: p.get( "value", null ),\n options: p.get( "options", [] ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Menu ( ... PairList p, Array c ) {\n _assert_known_props(\n "Menu",\n p,\n [ "id", "text", "visible", "enabled", "disabled" ],\n );\n\n return _apply_geometry( new _MenuClass(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction MenuItem ( ... PairList p, Array c ) {\n _assert_known_props(\n "MenuItem",\n p,\n [ "id", "text", "disabled", "visible", "enabled" ],\n );\n\n return _apply_geometry( new _MenuItemClass(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Button ( ... PairList p, Array c ) {\n _assert_known_props(\n "Button",\n p,\n _with_geometry_props( [\n "id",\n "text",\n "variant",\n "visible",\n "enabled",\n "disabled",\n ] ),\n );\n\n _assert_prop_value(\n "Button",\n "variant",\n p.get( "variant", "default" ),\n [ "default", "primary", "danger" ],\n );\n\n return new _ButtonClass(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n variant: p.get( "variant", "default" ),\n width: p.get( "width", null ),\n height: p.get( "height", null ),\n minwidth: p.get( "minwidth", null ),\n minheight: p.get( "minheight", null ),\n maxwidth: p.get( "maxwidth", null ),\n maxheight: p.get( "maxheight", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n );\n}\n\nfunction Separator ( ... PairList p, Array c ) {\n _assert_known_props(\n "Separator",\n p,\n [ "id", "orientation", "visible", "enabled", "disabled" ],\n );\n\n _assert_prop_value(\n "Separator",\n "orientation",\n p.get( "orientation", "horizontal" ),\n [ "horizontal", "vertical" ],\n );\n\n return _apply_geometry( new _SeparatorClass(\n id: p.get( "id", null ),\n orientation: p.get( "orientation", "horizontal" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Slider ( ... PairList p, Array c ) {\n _assert_known_props(\n "Slider",\n p,\n [\n "id",\n "value",\n "min",\n "max",\n "step",\n "orientation",\n "readonly",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n _assert_prop_value(\n "Slider",\n "orientation",\n p.get( "orientation", "horizontal" ),\n [ "horizontal", "vertical" ],\n );\n\n return _apply_geometry( new _SliderClass(\n id: p.get( "id", null ),\n value: p.get( "value", 0 ),\n min: p.get( "min", 0 ),\n max: p.get( "max", 100 ),\n step: p.get( "step", 1 ),\n orientation: p.get( "orientation", "horizontal" ),\n readonly: p.get( "readonly", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Progress ( ... PairList p, Array c ) {\n _assert_known_props(\n "Progress",\n p,\n [\n "id",\n "value",\n "min",\n "max",\n "indeterminate",\n "show_text",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _ProgressClass(\n id: p.get( "id", null ),\n value: p.get( "value", 0 ),\n min: p.get( "min", 0 ),\n max: p.get( "max", 100 ),\n indeterminate: p.get( "indeterminate", false ),\n show_text: p.get( "show_text", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Tabs ( ... PairList p, Array c ) {\n _assert_known_props(\n "Tabs",\n p,\n [\n "id",\n "selected",\n "placement",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n _assert_prop_value(\n "Tabs",\n "placement",\n p.get( "placement", "top" ),\n [ "top", "bottom", "left", "right" ],\n );\n\n return _apply_geometry( new _TabsClass(\n id: p.get( "id", null ),\n selected: p.get( "selected", null ),\n placement: p.get( "placement", "top" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction Tab ( ... PairList p, Array c ) {\n _assert_known_props(\n "Tab",\n p,\n [\n "id",\n "title",\n "value",\n "selected",\n "closable",\n "icon",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n return _apply_geometry( new _TabClass(\n id: p.get( "id", null ),\n title: p.get( "title", "" ),\n value: p.get( "value", "" ),\n selected: p.get( "selected", false ),\n closable: p.get( "closable", false ),\n icon: p.get( "icon", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction ListView ( ... PairList p, Array c ) {\n _assert_known_props(\n "ListView",\n p,\n [\n "id",\n "items",\n "selected_index",\n "multiple",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n if ( p.has("items") ) {\n _assert_prop_array( "ListView", "items", p.get("items") );\n }\n\n return _apply_geometry( new _ListViewClass(\n id: p.get( "id", null ),\n items: p.get( "items", [] ),\n selected_index: p.get( "selected_index", null ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction TreeView ( ... PairList p, Array c ) {\n _assert_known_props(\n "TreeView",\n p,\n [\n "id",\n "items",\n "selected_path",\n "multiple",\n "visible",\n "enabled",\n "disabled",\n ],\n );\n\n if ( p.has("items") ) {\n _assert_prop_array( "TreeView", "items", p.get("items") );\n }\n if ( p.has("selected_path") ) {\n _assert_prop_array( "TreeView", "selected_path", p.get("selected_path") );\n }\n\n return _apply_geometry( new _TreeViewClass(\n id: p.get( "id", null ),\n items: p.get( "items", [] ),\n selected_path: p.get( "selected_path", [] ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: c,\n ), p );\n}\n\nfunction _binding_path_class ( path_class ) {\n if ( path_class \u2261 null ) {\n return ZZPath;\n }\n if ( not( path_class instanceof Class ) ) {\n die "GUI_BIND_PATH: paths special property must be Class or null";\n }\n return path_class;\n}\n\nfunction _binding_compile_path ( String path_text, path_class ) {\n if ( path_class \u2261 null ) {\n try {\n return new ZZPath( path: path_text );\n }\n catch ( Exception e ) {\n die `GUI_BIND_PATH: ${e{message}}`;\n }\n }\n\n let path_type := _binding_path_class(path_class);\n try {\n return new path_type( path: path_text );\n }\n catch ( Exception e ) {\n die `GUI_BIND_PATH: ${e{message}}`;\n }\n}\n\nfunction _binding_path ( pathish, path_class ) {\n if ( pathish instanceof String ) {\n return _binding_compile_path( pathish, path_class );\n }\n if (\n pathish can first\n and ( pathish can assign_first or pathish can ref_first )\n ) {\n return pathish;\n }\n\n die "GUI_BIND_PATH: binding path must be String or path-like Object";\n}\n\nfunction _binding_get ( model, path ) {\n return path.first( model, null );\n}\n\nfunction _binding_set ( model, path, value ) {\n if ( path can assign_first ) {\n return path.assign_first( model, value );\n }\n\n let ref := path.ref_first(model);\n return ref(value);\n}\n\nclass BindingToken {\n let Widget widget but weak;\n let String widget_prop;\n let model;\n let model_path;\n let String event := "change";\n let listener := null;\n let Boolean _active := true;\n\n method is_active () {\n return _active;\n }\n\n method set_listener ( token ) {\n listener := token;\n return self;\n }\n\n method sync_model_to_widget () {\n widget.(widget_prop)( _binding_get( model, model_path ) );\n return self;\n }\n\n method sync_widget_to_model () {\n _binding_set( model, model_path, widget.(widget_prop)() );\n return self;\n }\n\n method unbind () {\n if ( _active and listener \u2262 null ) {\n widget.off(listener);\n }\n _active := false;\n return self;\n }\n}\n\nfunction bind (\n Widget widget,\n String widget_prop,\n model,\n model_path,\n ... PairList p\n) {\n let path := _binding_path( model_path, getupperprop( 1, "paths" ) );\n\n let token := new BindingToken(\n widget: widget,\n widget_prop: widget_prop,\n model: model,\n model_path: path,\n event: p.get( "event", "change" ),\n );\n let event_name := p.get( "event", "change" );\n\n switch ( p.get( "initial", "model" ): eq ) {\n case "model":\n token.sync_model_to_widget();\n case "widget":\n token.sync_widget_to_model();\n case "none":\n // No initial sync.\n default:\n die "GUI_BIND_INITIAL: initial must be model, widget, or none";\n }\n\n token.set_listener(\n widget.on( event_name, function () {\n if ( token.is_active() ) {\n token.sync_widget_to_model();\n }\n } ),\n );\n return token;\n}\n\nfunction unbind ( BindingToken token ) {\n return token.unbind();\n}\n\nlet GUI_XML_NS := "https://zuzulang.org/ns/std/gui";\n\nfunction _xml_error ( String code, String message ) {\n die `${code}: ${message}`;\n}\n\nfunction _xml_tag_name ( node ) {\n return node.localName() ?: node.nodeName();\n}\n\nfunction _xml_assert_namespace ( node ) {\n let ns := node.namespaceURI();\n if ( ns \u2262 null and ns \u2262 "" and ns \u2262 GUI_XML_NS ) {\n _xml_error(\n "GUI_XML_STRUCTURE",\n `unsupported GUI XML namespace \'${ns}\'`,\n );\n }\n}\n\nfunction _xml_common_allowed ( Array extra ) {\n let out := [\n "id",\n "visible",\n "enabled",\n "disabled",\n "width",\n "height",\n "minwidth",\n "minheight",\n "maxwidth",\n "maxheight",\n ];\n for ( let attr in extra ) {\n out.push(attr);\n }\n return out;\n}\n\nfunction _xml_allowed_attrs ( String tag ) {\n switch ( tag: eq ) {\n case "Window":\n return _xml_common_allowed(\n [ "title", "width", "height", "resizable", "modal" ],\n );\n case "VBox", "HBox":\n return _xml_common_allowed( [ "align", "gap", "padding" ] );\n case "Frame":\n return _xml_common_allowed( [ "label", "collapsible", "collapsed" ] );\n case "Label":\n return _xml_common_allowed( [ "text", "for" ] );\n case "Text":\n return _xml_common_allowed(\n [ "value", "multiline", "readonly", "wrap" ],\n );\n case "RichText":\n return _xml_common_allowed(\n [ "value", "multiline", "readonly" ],\n );\n case "Image":\n return _xml_common_allowed( [ "src", "alt", "fit" ] );\n case "Input":\n return _xml_common_allowed( [\n "value",\n "placeholder",\n "multiline",\n "readonly",\n "password",\n "required",\n ] );\n case "DatePicker":\n return _xml_common_allowed(\n [ "value", "min", "max", "first_day_of_week" ],\n );\n case "Checkbox":\n return _xml_common_allowed( [ "label", "checked", "indeterminate" ] );\n case "Radio":\n return _xml_common_allowed( [ "label", "value", "group", "checked" ] );\n case "RadioGroup":\n return _xml_common_allowed( [ "name", "value" ] );\n case "Select":\n return _xml_common_allowed( [ "value", "multiple" ] );\n case "Menu":\n return _xml_common_allowed( [ "text" ] );\n case "MenuItem":\n return _xml_common_allowed( [ "text" ] );\n case "Button":\n return _xml_common_allowed( [ "text", "variant" ] );\n case "Separator":\n return _xml_common_allowed( [ "orientation" ] );\n case "Slider":\n return _xml_common_allowed( [\n "value",\n "min",\n "max",\n "step",\n "orientation",\n "readonly",\n ] );\n case "Progress":\n return _xml_common_allowed( [\n "value",\n "min",\n "max",\n "indeterminate",\n "show_text",\n ] );\n case "Tabs":\n return _xml_common_allowed( [ "selected", "placement" ] );\n case "Tab":\n return _xml_common_allowed(\n [ "title", "value", "selected", "closable", "icon" ],\n );\n case "ListView":\n return _xml_common_allowed( [ "selected_index", "multiple" ] );\n case "TreeView":\n return _xml_common_allowed( [ "selected_path", "multiple" ] );\n }\n\n _xml_error( "GUI_XML_STRUCTURE", `unsupported GUI XML element \'${tag}\'` );\n}\n\nfunction _xml_bool_attrs ( String tag ) {\n return [\n "visible",\n "enabled",\n "disabled",\n "resizable",\n "modal",\n "collapsible",\n "collapsed",\n "multiline",\n "readonly",\n "wrap",\n "password",\n "required",\n "checked",\n "indeterminate",\n "multiple",\n "show_text",\n "selected",\n "closable",\n ];\n}\n\nfunction _xml_number_attrs ( String tag ) {\n return [\n "width",\n "height",\n "minwidth",\n "minheight",\n "maxwidth",\n "maxheight",\n "gap",\n "padding",\n "first_day_of_week",\n "selected_index",\n "value",\n "min",\n "max",\n "step",\n ];\n}\n\nfunction _xml_bool ( String tag, String attr, String raw ) {\n switch ( lc(raw): eq ) {\n case "true", "1", "yes", "on": return true;\n case "false", "0", "no", "off": return false;\n }\n _xml_error(\n "GUI_XML_ATTR_TYPE",\n `${tag}.${attr} expects a boolean XML attribute`,\n );\n}\n\nfunction _xml_number ( String tag, String attr, String raw ) {\n if ( not ( raw ~ /^-?[0-9]+(\\.[0-9]+)?$/ ) ) {\n _xml_error(\n "GUI_XML_ATTR_TYPE",\n `${tag}.${attr} expects a numeric XML attribute`,\n );\n }\n return 0 + raw;\n}\n\nfunction _xml_int_list ( String tag, String attr, String raw ) {\n let out := [];\n return out if raw eq "";\n for ( let part in split( raw, "," ) ) {\n let item := trim(part);\n if ( not ( item ~ /^-?[0-9]+$/ ) ) {\n _xml_error(\n "GUI_XML_ATTR_TYPE",\n `${tag}.${attr} expects comma-separated integers`,\n );\n }\n out.push( 0 + item );\n }\n return out;\n}\n\nfunction _xml_coerce_attr ( String tag, String attr, String raw ) {\n if ( attr eq "selected" and tag eq "Tabs" ) {\n return raw;\n }\n if ( attr eq "value" and tag \u2209 [ "Slider", "Progress" ] ) {\n return raw;\n }\n if ( attr eq "min" and tag eq "DatePicker" ) {\n return raw;\n }\n if ( attr eq "max" and tag eq "DatePicker" ) {\n return raw;\n }\n if ( attr eq "selected_path" ) {\n return _xml_int_list( tag, attr, raw );\n }\n if ( attr \u2208 _xml_bool_attrs(tag) ) {\n return _xml_bool( tag, attr, raw );\n }\n if ( attr \u2208 _xml_number_attrs(tag) ) {\n return _xml_number( tag, attr, raw );\n }\n return raw;\n}\n\nfunction _xml_attrs ( node ) {\n let tag := _xml_tag_name(node);\n let props := {};\n let meta := {};\n let meta_keys := [];\n let style := {};\n let style_keys := [];\n let allowed := _xml_allowed_attrs(tag);\n\n for ( let attr in node.attributeNames() ) {\n next if attr eq "xmlns";\n next if substr( attr, 0, 6 ) eq "xmlns:";\n let value := node.getAttribute(attr);\n if ( substr( attr, 0, 5 ) eq "meta." ) {\n let key := substr( attr, 5 );\n _xml_error( "GUI_XML_ATTR_UNKNOWN", "empty meta attribute name" )\n if key eq "";\n meta{(key)} := value;\n meta_keys.push(key);\n next;\n }\n if ( substr( attr, 0, 6 ) eq "style." ) {\n let key := substr( attr, 6 );\n _xml_error( "GUI_XML_ATTR_UNKNOWN", "empty style attribute name" )\n if key eq "";\n style{(key)} := value;\n style_keys.push(key);\n next;\n }\n if ( attr \u2209 allowed ) {\n _xml_error(\n "GUI_XML_ATTR_UNKNOWN",\n `${tag} does not accept XML attribute \'${attr}\'`,\n );\n }\n props{(attr)} := _xml_coerce_attr( tag, attr, value );\n }\n\n return {\n props: props,\n meta: meta,\n meta_keys: meta_keys,\n style: style,\n style_keys: style_keys,\n };\n}\n\nfunction _xml_apply_meta ( Widget widget, Dict meta, Array keys ) {\n for ( let key in keys ) {\n widget.meta( key, meta{(key)} );\n }\n if ( keys.length() > 0 ) {\n widget.meta( "__xml_meta_keys", keys );\n }\n return widget;\n}\n\nfunction _xml_apply_style ( Widget widget, Dict style, Array keys ) {\n for ( let key in keys ) {\n widget.style( key, style{(key)} );\n }\n if ( keys.length() > 0 ) {\n widget.meta( "__xml_style_keys", keys );\n }\n return widget;\n}\n\nfunction _xml_widget_from_node ( node ) {\n _xml_assert_namespace(node);\n\n let tag := _xml_tag_name(node);\n let child_widgets := [];\n for ( let child in node.children() ) {\n child_widgets.push( _xml_widget_from_node(child) );\n }\n let parsed := _xml_attrs(node);\n let p := parsed{props};\n let widget;\n\n switch ( tag: eq ) {\n case "Window":\n widget := new _WindowClass(\n id: p.get( "id", null ),\n title: p.get( "title", "" ),\n width: p.get( "width", 800 ),\n height: p.get( "height", 600 ),\n resizable: p.get( "resizable", true ),\n modal: p.get( "modal", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "VBox":\n widget := new _VBoxClass(\n id: p.get( "id", null ),\n align: p.get( "align", "top" ),\n gap: p.get( "gap", 0 ),\n padding: p.get( "padding", 0 ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "HBox":\n widget := new _HBoxClass(\n id: p.get( "id", null ),\n align: p.get( "align", "left" ),\n gap: p.get( "gap", 0 ),\n padding: p.get( "padding", 0 ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "Frame":\n widget := new _FrameClass(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n collapsible: p.get( "collapsible", false ),\n collapsed: p.get( "collapsed", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "Label":\n widget := Label(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n ("for"): p.get( "for", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Text":\n widget := Text(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n multiline: p.get( "multiline", false ),\n readonly: p.get( "readonly", false ),\n wrap: p.get( "wrap", true ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "RichText":\n widget := RichText(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n multiline: p.get( "multiline", true ),\n readonly: p.get( "readonly", true ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Image":\n widget := Image(\n id: p.get( "id", null ),\n src: p.get( "src", "" ),\n alt: p.get( "alt", "" ),\n fit: p.get( "fit", "none" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Input":\n widget := Input(\n id: p.get( "id", null ),\n value: p.get( "value", "" ),\n placeholder: p.get( "placeholder", "" ),\n multiline: p.get( "multiline", false ),\n readonly: p.get( "readonly", false ),\n password: p.get( "password", false ),\n required: p.get( "required", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "DatePicker":\n widget := DatePicker(\n id: p.get( "id", null ),\n value: p.get( "value", null ),\n min: p.get( "min", null ),\n max: p.get( "max", null ),\n first_day_of_week: p.get( "first_day_of_week", 0 ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Checkbox":\n widget := Checkbox(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n checked: p.get( "checked", false ),\n indeterminate: p.get( "indeterminate", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Radio":\n widget := Radio(\n id: p.get( "id", null ),\n label: p.get( "label", "" ),\n value: p.get( "value", "" ),\n group: p.get( "group", null ),\n checked: p.get( "checked", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "RadioGroup":\n widget := new _RadioGroupClass(\n id: p.get( "id", null ),\n name: p.get( "name", "" ),\n value: p.get( "value", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "Select":\n widget := Select(\n id: p.get( "id", null ),\n value: p.get( "value", null ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Menu":\n widget := new _MenuClass(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "MenuItem":\n widget := MenuItem(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Button":\n widget := Button(\n id: p.get( "id", null ),\n text: p.get( "text", "" ),\n variant: p.get( "variant", "default" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Separator":\n widget := Separator(\n id: p.get( "id", null ),\n orientation: p.get( "orientation", "horizontal" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Slider":\n widget := Slider(\n id: p.get( "id", null ),\n value: p.get( "value", 0 ),\n min: p.get( "min", 0 ),\n max: p.get( "max", 100 ),\n step: p.get( "step", 1 ),\n orientation: p.get( "orientation", "horizontal" ),\n readonly: p.get( "readonly", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Progress":\n widget := Progress(\n id: p.get( "id", null ),\n value: p.get( "value", 0 ),\n min: p.get( "min", 0 ),\n max: p.get( "max", 100 ),\n indeterminate: p.get( "indeterminate", false ),\n show_text: p.get( "show_text", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "Tabs":\n widget := new _TabsClass(\n id: p.get( "id", null ),\n selected: p.get( "selected", null ),\n placement: p.get( "placement", "top" ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "Tab":\n widget := new _TabClass(\n id: p.get( "id", null ),\n title: p.get( "title", "" ),\n value: p.get( "value", "" ),\n selected: p.get( "selected", false ),\n closable: p.get( "closable", false ),\n icon: p.get( "icon", null ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n children: child_widgets,\n );\n case "ListView":\n widget := ListView(\n id: p.get( "id", null ),\n selected_index: p.get( "selected_index", null ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n case "TreeView":\n widget := TreeView(\n id: p.get( "id", null ),\n selected_path: p.get( "selected_path", [] ),\n multiple: p.get( "multiple", false ),\n visible: p.get( "visible", true ),\n enabled: p.get( "enabled", true ),\n disabled: p.get( "disabled", false ),\n );\n default:\n _xml_error(\n "GUI_XML_STRUCTURE",\n `unsupported GUI XML element \'${tag}\'`,\n );\n }\n\n _xml_apply_meta( widget, parsed{meta}, parsed{meta_keys} );\n return _xml_apply_style( widget, parsed{style}, parsed{style_keys} );\n}\n\nfunction gui_from_xml ( String xml ) {\n return _xml_widget_from_node( XML.parse(xml).documentElement() );\n}\n\nfunction gui_from_xml_file ( path ) {\n die "XML.load is denied by runtime policy" if __system__{deny_fs};\n from std/io import Path;\n let file := path instanceof Path ? path : new Path(path);\n return _xml_widget_from_node( XML.load(file).documentElement() );\n}\n\nfunction _xml_tag_for_widget ( Widget widget ) {\n if ( widget instanceof _WindowClass ) { return "Window"; }\n if ( widget instanceof _VBoxClass ) { return "VBox"; }\n if ( widget instanceof _HBoxClass ) { return "HBox"; }\n if ( widget instanceof _FrameClass ) { return "Frame"; }\n if ( widget instanceof _LabelClass ) { return "Label"; }\n if ( widget instanceof _TextClass ) { return "Text"; }\n if ( widget instanceof _RichTextClass ) { return "RichText"; }\n if ( widget instanceof _ImageClass ) { return "Image"; }\n if ( widget instanceof _InputClass ) { return "Input"; }\n if ( widget instanceof _DatePickerClass ) { return "DatePicker"; }\n if ( widget instanceof _CheckboxClass ) { return "Checkbox"; }\n if ( widget instanceof _RadioClass ) { return "Radio"; }\n if ( widget instanceof _RadioGroupClass ) { return "RadioGroup"; }\n if ( widget instanceof _SelectClass ) { return "Select"; }\n if ( widget instanceof _MenuClass ) { return "Menu"; }\n if ( widget instanceof _MenuItemClass ) { return "MenuItem"; }\n if ( widget instanceof _ButtonClass ) { return "Button"; }\n if ( widget instanceof _SeparatorClass ) { return "Separator"; }\n if ( widget instanceof _SliderClass ) { return "Slider"; }\n if ( widget instanceof _ProgressClass ) { return "Progress"; }\n if ( widget instanceof _TabsClass ) { return "Tabs"; }\n if ( widget instanceof _TabClass ) { return "Tab"; }\n if ( widget instanceof _ListViewClass ) { return "ListView"; }\n if ( widget instanceof _TreeViewClass ) { return "TreeView"; }\n _xml_error( "GUI_XML_STRUCTURE", "unsupported widget for gui_to_xml" );\n}\n\nfunction _xml_attr ( String name, value ) {\n return "" if value \u2261 null;\n return ` ${name}="${escape_xml(value)}"`;\n}\n\nfunction _xml_attr_if ( String name, value, fallback ) {\n return "" if value \u2261 fallback;\n return _xml_attr( name, value );\n}\n\nfunction _xml_bool_attr_if ( String name, value, fallback ) {\n let normalized := value ? true : false;\n let normalized_fallback := fallback ? true : false;\n return "" if normalized \u2261 normalized_fallback;\n return _xml_attr( name, normalized ? "true" : "false" );\n}\n\nfunction _xml_attr_nonempty ( String name, value ) {\n return "" if value \u2261 null or value eq "";\n return _xml_attr( name, value );\n}\n\nfunction _xml_join_ints ( Array values ) {\n let out := [];\n for ( let value in values ) {\n out.push( "" _ value );\n }\n return join( ",", out );\n}\n\nfunction _xml_meta_attrs ( Widget widget ) {\n let keys := widget.meta( "__xml_meta_keys" ) ?: [];\n let out := "";\n for ( let key in keys ) {\n out _= _xml_attr( "meta." _ key, widget.meta(key) );\n }\n return out;\n}\n\nfunction _xml_style_attrs ( Widget widget ) {\n let keys := widget.meta( "__xml_style_keys" ) ?: [];\n let out := "";\n for ( let key in keys ) {\n out _= _xml_attr( "style." _ key, widget.style(key) );\n }\n return out;\n}\n\nfunction _xml_common_attrs ( Widget widget ) {\n let out := "";\n out _= _xml_attr( "id", widget.id() ) if widget.id() \u2262 null;\n out _= _xml_bool_attr_if( "visible", widget.visible(), true );\n out _= _xml_bool_attr_if( "disabled", not widget.enabled(), false );\n out _= _xml_meta_attrs(widget);\n out _= _xml_style_attrs(widget);\n return out;\n}\n\nfunction _xml_widget_attrs ( Widget widget ) {\n let out := _xml_common_attrs(widget);\n if ( widget instanceof _WindowClass ) {\n out _= _xml_attr_if( "title", widget.title(), "" );\n }\n else if ( widget instanceof _VBoxClass or widget instanceof _HBoxClass ) {\n let default_align := widget instanceof _VBoxClass ? "top" : "left";\n out _= _xml_attr_if( "align", widget.align(), default_align );\n out _= _xml_attr_if( "gap", widget.gap(), 0 );\n out _= _xml_attr_if( "padding", widget.padding(), 0 )\n unless widget.padding() instanceof Array;\n }\n else if ( widget instanceof _FrameClass ) {\n out _= _xml_attr_if( "label", widget.label(), "" );\n out _= _xml_bool_attr_if( "collapsible", widget.collapsible(), false );\n out _= _xml_bool_attr_if( "collapsed", widget.collapsed(), false );\n }\n else if ( widget instanceof _LabelClass ) {\n out _= _xml_attr_if( "text", widget.text(), "" );\n out _= _xml_attr_nonempty( "for", widget.for_id() );\n }\n else if ( widget instanceof _TextClass ) {\n out _= _xml_attr_if( "value", widget.value(), "" );\n out _= _xml_bool_attr_if( "multiline", widget.multiline(), false );\n out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );\n out _= _xml_bool_attr_if( "wrap", widget.wrap(), true );\n }\n else if ( widget instanceof _RichTextClass ) {\n out _= _xml_attr_if( "value", widget.value(), "" );\n out _= _xml_bool_attr_if( "multiline", widget.multiline(), true );\n out _= _xml_bool_attr_if( "readonly", widget.readonly(), true );\n }\n else if ( widget instanceof _ImageClass ) {\n out _= _xml_attr_if( "src", widget.src(), "" );\n out _= _xml_attr_if( "alt", widget.alt(), "" );\n out _= _xml_attr_if( "fit", widget.fit(), "none" );\n }\n else if ( widget instanceof _InputClass ) {\n out _= _xml_attr_if( "value", widget.value(), "" );\n out _= _xml_attr_if( "placeholder", widget.placeholder(), "" );\n out _= _xml_bool_attr_if( "multiline", widget.multiline(), false );\n out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );\n out _= _xml_bool_attr_if( "password", widget.password(), false );\n out _= _xml_bool_attr_if( "required", widget.required(), false );\n }\n else if ( widget instanceof _DatePickerClass ) {\n out _= _xml_attr( "value", widget.value() );\n out _= _xml_attr( "min", widget.min() ) if widget.min() \u2262 null;\n out _= _xml_attr( "max", widget.max() ) if widget.max() \u2262 null;\n out _= _xml_attr_if(\n "first_day_of_week",\n widget.first_day_of_week(),\n 0,\n );\n }\n else if ( widget instanceof _CheckboxClass ) {\n out _= _xml_attr_if( "label", widget.label(), "" );\n out _= _xml_bool_attr_if( "checked", widget.checked(), false );\n out _= _xml_bool_attr_if( "indeterminate", widget.indeterminate(), false );\n }\n else if ( widget instanceof _RadioClass ) {\n out _= _xml_attr_if( "label", widget.label(), "" );\n out _= _xml_attr_if( "value", widget.value(), "" );\n out _= _xml_attr_nonempty( "group", widget.group() );\n out _= _xml_bool_attr_if( "checked", widget.checked(), false );\n }\n else if ( widget instanceof _RadioGroupClass ) {\n out _= _xml_attr_if( "name", widget.name(), "" );\n out _= _xml_attr( "value", widget.value() ) if widget.value() \u2262 null;\n }\n else if ( widget instanceof _SelectClass ) {\n out _= _xml_attr( "value", widget.value() ) if widget.value() \u2262 null;\n out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );\n }\n else if ( widget instanceof _MenuClass ) {\n out _= _xml_attr_if( "text", widget.text(), "" );\n }\n else if ( widget instanceof _MenuItemClass ) {\n out _= _xml_attr_if( "text", widget.text(), "" );\n }\n else if ( widget instanceof _ButtonClass ) {\n out _= _xml_attr_if( "text", widget.text(), "" );\n out _= _xml_attr_if( "variant", widget.variant(), "default" );\n }\n else if ( widget instanceof _SeparatorClass ) {\n out _= _xml_attr_if( "orientation", widget.orientation(), "horizontal" );\n }\n else if ( widget instanceof _SliderClass ) {\n out _= _xml_attr_if( "value", widget.value(), 0 );\n out _= _xml_attr_if( "min", widget.min(), 0 );\n out _= _xml_attr_if( "max", widget.max(), 100 );\n out _= _xml_attr_if( "step", widget.step(), 1 );\n out _= _xml_attr_if( "orientation", widget.orientation(), "horizontal" );\n out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );\n }\n else if ( widget instanceof _ProgressClass ) {\n out _= _xml_attr_if( "value", widget.value(), 0 );\n out _= _xml_attr_if( "min", widget.min(), 0 );\n out _= _xml_attr_if( "max", widget.max(), 100 );\n out _= _xml_bool_attr_if( "indeterminate", widget.indeterminate(), false );\n out _= _xml_bool_attr_if( "show_text", widget.show_text(), false );\n }\n else if ( widget instanceof _TabsClass ) {\n out _= _xml_attr( "selected", widget.selected() )\n if widget.selected() \u2262 null;\n out _= _xml_attr_if( "placement", widget.placement(), "top" );\n }\n else if ( widget instanceof _TabClass ) {\n out _= _xml_attr_if( "title", widget.title(), "" );\n out _= _xml_attr_if( "value", widget.value(), "" );\n out _= _xml_attr( "icon", widget.icon() ) if widget.icon() \u2262 null;\n out _= _xml_bool_attr_if( "selected", widget.selected(), false );\n out _= _xml_bool_attr_if( "closable", widget.closable(), false );\n }\n else if ( widget instanceof _ListViewClass ) {\n out _= _xml_attr( "selected_index", widget.selected_index() )\n if widget.selected_index() \u2262 null;\n out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );\n }\n else if ( widget instanceof _TreeViewClass ) {\n let selected_path := widget.selected_path();\n out _= _xml_attr( "selected_path", _xml_join_ints(selected_path) )\n if selected_path.length() > 0;\n out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );\n }\n return out;\n}\n\nfunction _xml_serialize_widget ( Widget widget, Number depth ) {\n let indent := "";\n let i := 0;\n while ( i < depth ) {\n indent _= "\\t";\n i++;\n }\n\n let tag := _xml_tag_for_widget(widget);\n let attrs := _xml_widget_attrs(widget);\n attrs _= _xml_attr( "xmlns", GUI_XML_NS ) if depth = 0;\n let children := widget.children();\n if ( children.length() = 0 ) {\n return indent _ "<" _ tag _ attrs _ " />";\n }\n\n let parts := [];\n for ( let child in children ) {\n parts.push( _xml_serialize_widget( child, depth + 1 ) );\n }\n\n return indent _ "<" _ tag _ attrs _ ">\\n"\n _ join( "\\n", parts )\n _ "\\n" _ indent _ "</" _ tag _ ">";\n}\n\nfunction gui_to_xml ( Widget root ) {\n return _xml_serialize_widget( root, 0 ) _ "\\n";\n}\n';
|
|
39664
41583
|
virtualFiles["/modules/std/gui/dialogue.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/gui/dialogue - Dialogue helpers.\n\n=head1 SYNOPSIS\n\n from std/gui/dialogue import *;\n\n alert("Saved");\n let ok := confirm("Continue?");\n let name := prompt("Name:", value: "Ada");\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Electron\nand Browser. It is not supported by zuzu-js on Node.\n\n=head1 DESCRIPTION\n\nThis module provides convenience dialogue helpers layered on top of the\nregular C<std/gui> widgets.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item C<< alert(String message, ... PairList p) >>, C<< alert_window(String message, ... PairList p) >>\n\nParameters: C<message> is display text and C<p> contains options.\nReturns: C<null> for C<alert> or C<Window> for C<alert_window>. Shows or\nbuilds an alert dialogue.\n\n=item C<< confirm(String message, ... PairList p) >>, C<< confirm_window(String message, ... PairList p) >>\n\nParameters: C<message> is display text and C<p> contains options.\nReturns: C<Boolean> for C<confirm> or C<Window> for\nC<confirm_window>. Shows or builds a confirmation dialogue.\n\n=item C<< prompt(String message, ... PairList p) >>, C<< prompt_window(String message, ... PairList p) >>\n\nParameters: C<message> is prompt text and C<p> contains options such as\nC<value>. Returns: C<String> or C<null> for C<prompt>, or C<Window> for\nC<prompt_window>. Shows or builds a text prompt.\n\n=item C<< file_open(... PairList p) >>, C<< file_save(... PairList p) >>\n\nParameters: C<p> contains dialogue options. Returns: path value or\nC<null>. Opens a file selection dialogue.\n\n=item C<< directory_open(... PairList p) >>, C<< directory_save(... PairList p) >>\n\nParameters: C<p> contains dialogue options. Returns: path value or\nC<null>. Opens a directory selection dialogue.\n\n=item C<< colour_picker(... PairList p) >>\n\nParameters: C<p> contains dialogue options. Returns: C<String> or\nC<null>. Opens a colour picker and returns a normalized colour string.\n\n=item C<< file_open_window(... PairList p) >>, C<< file_save_window(... PairList p) >>, C<< directory_open_window(... PairList p) >>, C<< directory_save_window(... PairList p) >>, C<< colour_picker_window(... PairList p) >>\n\nParameters: C<p> contains dialogue options. Returns: C<Window>. Builds\nthe corresponding GUI dialogue window.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/gui/dialogue >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/gui try import\n EM,\n Window,\n VBox,\n HBox,\n Label,\n Text,\n Input,\n Button,\n Widget,\n native_file_open,\n native_file_save,\n native_directory_open,\n native_directory_save,\n native_colour_picker;\nfrom std/gui/objects try import\n meta as _objects_meta,\n native_alert,\n native_confirm,\n native_prompt;\nfrom std/colour import parse_colour;\nfrom std/string import split;\nfrom std/tui import\n colour_text,\n directory_completions,\n filename_completions,\n readline;\n\nfunction _tui_string ( value ) {\n return value \u2261 null ? "" : "" _ value;\n}\n\nfunction _gui_backend () {\n if ( _objects_meta \u2262 null ) {\n return _objects_meta{backend};\n }\n return "";\n}\n\nfunction _path_dialogue_unsupported () {\n if ( __system__{deny_fs} ) {\n die "GUI_DIALOGUE_FS_DENIED: file and directory dialogues require filesystem capability";\n }\n if ( _gui_backend() eq "browser-dom" ) {\n die "GUI_DIALOGUE_UNSUPPORTED: file and directory dialogues are unsupported in JS/Browser";\n }\n}\n\nfunction _tui_prompt ( String message, PairList p, String default_value ) {\n return readline(\n colour_text( message _ " ", "cyan" ),\n default_value,\n null,\n );\n}\n\nfunction _tui_path_dialog (\n String label,\n String default_value,\n completion,\n PairList p\n) {\n let answer := readline(\n colour_text( p.get( "label", label ) _ " ", "cyan" ),\n _tui_string( p.get( "value", default_value ) ),\n completion,\n );\n if ( p.get( "multiple", false ) ) {\n return split( answer, p.get( "separator", "\\n" ) );\n }\n return answer;\n}\n\nfunction _parse_colour_or_null ( value ) {\n return try {\n parse_colour( _tui_string(value) );\n }\n catch {\n null;\n };\n}\n\nfunction _colour_initial_value ( PairList p ) {\n let raw := _tui_string( p.get( "value", "#000000" ) );\n let parsed := _parse_colour_or_null(raw);\n return parsed \u2262 null ? parsed : raw;\n}\n\nfunction _colour_default_value ( PairList p ) {\n return _parse_colour_or_null( p.get( "value", "#000000" ) ) ?: "#000000";\n}\n\nfunction _tui_colour_dialog ( PairList p ) {\n let default_value := _colour_default_value(p);\n while ( true ) {\n let answer := readline(\n colour_text( p.get( "label", "Colour:" ) _ " ", "cyan" ),\n default_value,\n null,\n );\n let parsed := _parse_colour_or_null(answer);\n if ( parsed \u2262 null ) {\n return parsed;\n }\n say( colour_text( "Invalid colour; try #336699 or red.", "yellow" ) );\n }\n}\n\nfunction _dialogue_window (\n String kind,\n String title,\n Widget body,\n Array buttons,\n PairList p\n) {\n let button_row := HBox(\n id: "buttons",\n align: "right",\n gap: 6,\n height: p.get( "button_row_height", 2.125 \xD7 EM ),\n maxheight: p.get( "button_row_height", 2.125 \xD7 EM ),\n );\n for ( let button in buttons ) {\n button_row.add_child(button);\n }\n let w := Window(\n title: title,\n width: p.get( "width", 360 ),\n height: p.get( "height", 180 ),\n resizable: p.get( "resizable", false ),\n modal: true,\n VBox(\n id: p.get( "id", null ),\n gap: p.get( "gap", 8 ),\n padding: p.get( "padding", 12 ),\n body,\n button_row,\n ),\n );\n w.meta( "dialogue.kind", kind );\n return w;\n}\n\nfunction _message_body ( String message, PairList p ) {\n return Text(\n id: p.get( "message_id", "message" ),\n value: message,\n readonly: true,\n wrap: true,\n );\n}\n\nfunction _primary_button ( PairList p, String fallback ) {\n return Button(\n id: p.get( "ok_id", "ok" ),\n text: p.get( "ok_text", fallback ),\n variant: "primary",\n width: p.get( "button_width", 5.5 \xD7 EM ),\n height: p.get( "button_height", 1.75 \xD7 EM ),\n maxheight: p.get( "button_height", 1.75 \xD7 EM ),\n );\n}\n\nfunction _cancel_button ( PairList p ) {\n return Button(\n id: p.get( "cancel_id", "cancel" ),\n text: p.get( "cancel_text", "Cancel" ),\n width: p.get( "button_width", 5.5 \xD7 EM ),\n height: p.get( "button_height", 1.75 \xD7 EM ),\n maxheight: p.get( "button_height", 1.75 \xD7 EM ),\n );\n}\n\nfunction _alert_window ( String message, PairList p ) {\n let ok := _primary_button( p, "OK" );\n let w := _dialogue_window(\n "alert",\n p.get( "title", "Alert" ),\n _message_body( message, p ),\n [ ok ],\n p,\n );\n ok.click( function () {\n w.close(null);\n } );\n return w;\n}\n\nfunction alert_window ( String message, ... PairList p ) {\n return _alert_window( message, p );\n}\n\nfunction alert ( String message, ... PairList p ) {\n if ( p.has("auto_result") ) {\n return null;\n }\n if ( __system__{deny_gui} ) {\n say( colour_text( message, "yellow" ) );\n return null;\n }\n if ( native_alert \u2262 null ) {\n let native_result := native_alert( message, p );\n if ( native_result ) {\n return null;\n }\n }\n return _alert_window( message, p ).call();\n}\n\nfunction _confirm_window ( String message, PairList p ) {\n let ok := _primary_button( p, p.get( "ok_text", "OK" ) );\n let cancel := _cancel_button(p);\n let w := _dialogue_window(\n "confirm",\n p.get( "title", "Confirm" ),\n _message_body( message, p ),\n [ cancel, ok ],\n p,\n );\n ok.click( function () {\n w.close(true);\n } );\n cancel.click( function () {\n w.close(false);\n } );\n return w;\n}\n\nfunction confirm_window ( String message, ... PairList p ) {\n return _confirm_window( message, p );\n}\n\nfunction confirm ( String message, ... PairList p ) {\n if ( p.has("auto_result") ) {\n return p.get("auto_result") ? true : false;\n }\n if ( __system__{deny_gui} ) {\n let yes_default := p.get( "value", p.get( "default", false ) );\n let suffix := yes_default ? " [Y/n] " : " [y/N] ";\n let answer := readline(\n colour_text( message _ suffix, "cyan" ),\n yes_default ? "y" : "n",\n null,\n );\n return ( answer ~ /^(?:y|yes|1|true)$/i ) ? true : false;\n }\n if ( native_confirm \u2262 null ) {\n let native_result := native_confirm( message, p );\n if ( native_result \u2262 null ) {\n return native_result ? true : false;\n }\n }\n return _confirm_window( message, p ).call() ? true : false;\n}\n\nfunction _prompt_window ( String message, PairList p ) {\n let input := Input(\n id: p.get( "input_id", "value" ),\n value: p.get( "value", "" ),\n placeholder: p.get( "placeholder", "" ),\n );\n let ok := _primary_button( p, p.get( "ok_text", "OK" ) );\n let cancel := _cancel_button(p);\n let w := _dialogue_window(\n "prompt",\n p.get( "title", "Prompt" ),\n VBox(\n gap: 6,\n _message_body( message, p ),\n input,\n ),\n [ cancel, ok ],\n p,\n );\n ok.click( function () {\n w.close( input.value() );\n } );\n cancel.click( function () {\n w.close(null);\n } );\n return w;\n}\n\nfunction prompt_window ( String message, ... PairList p ) {\n return _prompt_window( message, p );\n}\n\nfunction prompt ( String message, ... PairList p ) {\n if ( p.has("auto_result") ) {\n return p.get("auto_result");\n }\n if ( __system__{deny_gui} ) {\n return _tui_prompt(\n message,\n p,\n _tui_string( p.get( "value", "" ) ),\n );\n }\n if ( native_prompt \u2262 null ) {\n let native_result := native_prompt( message, p );\n if ( _gui_backend() eq "browser-dom" ) {\n return native_result;\n }\n if ( native_result \u2262 null ) {\n return native_result;\n }\n }\n return _prompt_window( message, p ).call();\n}\n\nfunction _path_dialog_window (\n String kind,\n String title,\n String label,\n String default_value,\n PairList p\n) {\n let input := Input(\n id: p.get( "input_id", "path" ),\n value: p.get( "value", default_value ),\n placeholder: p.get( "placeholder", "" ),\n multiline: p.get( "multiple", false ),\n );\n let ok := _primary_button( p, p.get( "ok_text", "OK" ) );\n let cancel := _cancel_button(p);\n let w := _dialogue_window(\n kind,\n p.get( "title", title ),\n VBox(\n gap: 6,\n Label( text: p.get( "label", label ), ("for"): input.id() ),\n input,\n ),\n [ cancel, ok ],\n p,\n );\n ok.click( function () {\n if ( p.get( "multiple", false ) ) {\n w.close( split( input.value(), p.get( "separator", "\\n" ) ) );\n }\n else {\n w.close( input.value() );\n }\n } );\n cancel.click( function () {\n w.close(null);\n } );\n return w;\n}\n\nfunction file_open_window ( ... PairList p ) {\n return _path_dialog_window( "file_open", "Open File", "File:", "", p );\n}\n\nfunction file_save_window ( ... PairList p ) {\n return _path_dialog_window( "file_save", "Save File", "File:", "", p );\n}\n\nfunction directory_open_window ( ... PairList p ) {\n return _path_dialog_window(\n "directory_open",\n "Open Directory",\n "Directory:",\n "",\n p,\n );\n}\n\nfunction directory_save_window ( ... PairList p ) {\n return _path_dialog_window(\n "directory_save",\n "Save Directory",\n "Directory:",\n "",\n p,\n );\n}\n\nfunction _colour_picker_window ( PairList p ) {\n let input := Input(\n id: p.get( "input_id", "path" ),\n value: _colour_initial_value(p),\n placeholder: p.get( "placeholder", "#336699" ),\n );\n let ok := _primary_button( p, p.get( "ok_text", "OK" ) );\n let cancel := _cancel_button(p);\n let default_value := _colour_default_value(p);\n let sync_ok := function () {\n ok.set_enabled( _parse_colour_or_null( input.value() ) \u2262 null );\n };\n let w := _dialogue_window(\n "colour_picker",\n p.get( "title", "Choose Colour" ),\n VBox(\n gap: 6,\n Label(\n text: p.get( "label", "Colour:" ),\n ("for"): input.id(),\n ),\n input,\n ),\n [ cancel, ok ],\n p,\n );\n sync_ok();\n input.on( "change", sync_ok );\n ok.click( function () {\n let parsed := _parse_colour_or_null( input.value() );\n if ( parsed \u2262 null ) {\n w.close(parsed);\n }\n } );\n cancel.click( function () {\n w.close(default_value);\n } );\n return w;\n}\n\nfunction colour_picker_window ( ... PairList p ) {\n return _colour_picker_window(p);\n}\n\nfunction file_open ( ... PairList p ) {\n _path_dialogue_unsupported();\n if ( p.has("auto_result") ) {\n return p.get("auto_result");\n }\n if ( __system__{deny_gui} ) {\n return _tui_path_dialog( "File:", "", filename_completions, p );\n }\n return native_file_open(p);\n}\n\nfunction file_save ( ... PairList p ) {\n _path_dialogue_unsupported();\n if ( p.has("auto_result") ) {\n return p.get("auto_result");\n }\n if ( __system__{deny_gui} ) {\n return _tui_path_dialog( "File:", "", filename_completions, p );\n }\n return native_file_save(p);\n}\n\nfunction directory_open ( ... PairList p ) {\n _path_dialogue_unsupported();\n if ( p.has("auto_result") ) {\n return p.get("auto_result");\n }\n if ( __system__{deny_gui} ) {\n return _tui_path_dialog(\n "Directory:",\n "",\n directory_completions,\n p,\n );\n }\n return native_directory_open(p);\n}\n\nfunction directory_save ( ... PairList p ) {\n _path_dialogue_unsupported();\n if ( p.has("auto_result") ) {\n return p.get("auto_result");\n }\n if ( __system__{deny_gui} ) {\n return _tui_path_dialog(\n "Directory:",\n "",\n directory_completions,\n p,\n );\n }\n if ( native_directory_save \u2262 null ) {\n let native_result := native_directory_save(p);\n if ( native_result \u2262 null ) {\n return native_result;\n }\n if ( _gui_backend() eq "electron-dom" ) {\n return null;\n }\n }\n return _path_dialog_window(\n "directory_save",\n "Save Directory",\n "Directory:",\n "",\n p,\n ).call();\n}\n\nfunction colour_picker ( ... PairList p ) {\n if ( p.has("auto_result") ) {\n return parse_colour( _tui_string( p.get("auto_result") ) );\n }\n if ( __system__{deny_gui} ) {\n return _tui_colour_dialog(p);\n }\n if ( native_colour_picker \u2262 null ) {\n let native_result := native_colour_picker(p);\n if ( native_result \u2262 null ) {\n return parse_colour(native_result);\n }\n if ( _gui_backend() eq "browser-dom" ) {\n return null;\n }\n }\n if ( _gui_backend() eq "electron-dom" ) {\n return _colour_picker_window(p).call();\n }\n return parse_colour( _colour_picker_window(p).call() );\n}\n';
|
|
39665
|
-
virtualFiles["/modules/std/uuid.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/uuid - Pure ZuzuScript UUID v1 generator.\n\n=head1 SYNOPSIS\n\n from std/uuid import create_uuid, create_uuid_binary;\n\n let text := create_uuid();\n let raw := create_uuid_binary();\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module implements UUID version 1 generation using only\nZuzuScript code.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item * C<create_uuid_binary()>\n\nParameters: none. Returns: C<BinaryString>. Returns a single UUID as 16\nraw bytes.\n\n=item * C<create_uuid()>\n\nParameters: none. Returns: C<String>. Returns a single UUID as\nlowercase hexadecimal text with hyphens in the usual C<8-4-4-4-12>\nlayout.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/uuid >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/math import Math;\nfrom std/string import substr;\nfrom std/string/base64 import decode;\nfrom std/time import Time;\n\nlet _B64_ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\nlet _HEX_ALPHABET := "0123456789abcdef";\n\nfunction _div_floor ( Number n, Number d ) {\n return floor( n / d );\n}\n\nfunction _mod ( Number n, Number d ) {\n return n - _div_floor( n, d ) * d;\n}\n\nfunction _rand_int ( Number max ) {\n return floor( Math.rand(max) );\n}\n\nfunction _bytes_to_binary ( Array bytes ) {\n let out := "";\n let i := 0;\n let n := bytes.length();\n\n while ( i < n ) {\n let b0 := bytes[i];\n let b1 := null;\n let b2 := null;\n if ( i + 1 < n ) {\n b1 := bytes[i + 1];\n }\n if ( i + 2 < n ) {\n b2 := bytes[i + 2];\n }\n\n let c0 := _div_floor( b0, 4 );\n let c1 := _mod( b0, 4 ) * 16;\n let c2 := 64;\n let c3 := 64;\n\n if ( b1 \u2262 null ) {\n c1 += _div_floor( b1, 16 );\n c2 := _mod( b1, 16 ) * 4;\n if ( b2 \u2262 null ) {\n c2 += _div_floor( b2, 64 );\n c3 := _mod( b2, 64 );\n }\n }\n\n out _= substr( _B64_ALPHABET, c0, 1 );\n out _= substr( _B64_ALPHABET, c1, 1 );\n if ( c2 \u2261 64 ) {\n out _= "=";\n }\n else {\n out _= substr( _B64_ALPHABET, c2, 1 );\n }\n if ( c3 \u2261 64 ) {\n out _= "=";\n }\n else {\n out _= substr( _B64_ALPHABET, c3, 1 );\n }\n\n i += 3;\n }\n\n return decode(out);\n}\n\nfunction _timestamp_words () {\n // Seconds between 1582-10-15 and 1970-01-01.\n let epoch_offset := 12219292800;\n let seconds := new Time().epoch() + epoch_offset;\n let ticks := _rand_int(10000000);\n\n let words := [\n _mod( seconds, 65536 ),\n _mod( _div_floor( seconds, 65536 ), 65536 ),\n _mod( _div_floor( seconds, 4294967296 ), 65536 ),\n 0,\n 0,\n ];\n\n let scale := 10000000;\n let i := 0;\n let carry := 0;\n while ( i < words.length() ) {\n let product := words[i] * scale + carry;\n words[i] := _mod( product, 65536 );\n carry := _div_floor( product, 65536 );\n i++;\n }\n\n let add_i := 0;\n let add_carry := ticks;\n while ( add_carry > 0 and add_i < words.length() ) {\n let sum := words[add_i] + _mod( add_carry, 65536 );\n words[add_i] := _mod( sum, 65536 );\n add_carry := _div_floor( add_carry, 65536 ) + _div_floor( sum, 65536 );\n add_i++;\n }\n\n return words;\n}\n\nfunction _create_uuid_bytes () {\n let words := _timestamp_words();\n let time_low := words[0] + words[1] * 65536;\n let time_mid := words[2];\n let time_hi_and_version := _mod( words[3], 4096 ) + 4096;\n\n let clock_seq := _rand_int(16384);\n let clock_seq_hi_and_reserved := _mod( _div_floor( clock_seq, 256 ), 64 ) + 128;\n let clock_seq_low := _mod( clock_seq, 256 );\n\n let node := [];\n let j := 0;\n while ( j < 6 ) {\n node.push( _rand_int(256) );\n j++;\n }\n // Multicast bit set means this is not an IEEE MAC address.\n node[0] := node[0] | 1;\n\n return [\n _mod( _div_floor( time_low, 16777216 ), 256 ),\n _mod( _div_floor( time_low, 65536 ), 256 ),\n _mod( _div_floor( time_low, 256 ), 256 ),\n _mod( time_low, 256 ),\n _mod( _div_floor( time_mid, 256 ), 256 ),\n _mod( time_mid, 256 ),\n _mod( _div_floor( time_hi_and_version, 256 ), 256 ),\n _mod( time_hi_and_version, 256 ),\n clock_seq_hi_and_reserved,\n clock_seq_low,\n node[0],\n node[1],\n node[2],\n node[3],\n node[4],\n node[5],\n ];\n}\n\nfunction _byte_to_hex ( Number b ) {\n let hi := _div_floor( b, 16 );\n let lo := _mod( b, 16 );\n return substr( _HEX_ALPHABET, hi, 1 ) _ substr( _HEX_ALPHABET, lo, 1 );\n}\n\nfunction _bytes_to_uuid_text ( Array bytes ) {\n let out := "";\n let i := 0;\n while ( i < 16 ) {\n out _= _byte_to_hex( bytes[i] );\n if ( i \u2261 3 or i \u2261 5 or i \u2261 7 or i \u2261 9 ) {\n out _= "-";\n }\n i++;\n }\n return out;\n}\n\nfunction create_uuid_binary () {\n return _bytes_to_binary( _create_uuid_bytes() );\n}\n\nfunction create_uuid () {\n return _bytes_to_uuid_text( _create_uuid_bytes() );\n}\n';
|
|
41584
|
+
virtualFiles["/modules/std/uuid.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/uuid - Pure ZuzuScript UUID v1 generator.\n\n=head1 SYNOPSIS\n\n from std/uuid import create_uuid, create_uuid_binary;\n\n let text := create_uuid();\n let raw := create_uuid_binary();\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module implements UUID version 1 generation using only\nZuzuScript code.\n\n=head1 EXPORTS\n\n=head2 Functions\n\n=over\n\n=item * C<create_uuid_binary()>\n\nParameters: none. Returns: C<BinaryString>. Returns a single UUID as 16\nraw bytes.\n\n=item * C<create_uuid()>\n\nParameters: none. Returns: C<String>. Returns a single UUID as\nlowercase hexadecimal text with hyphens in the usual C<8-4-4-4-12>\nlayout.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/uuid >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/math import Math;\nfrom std/string import substr;\nfrom std/string/base64 import decode;\nfrom std/time import Time;\n\nlet _B64_ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\nlet _HEX_ALPHABET := "0123456789abcdef";\n\nfunction _div_floor ( Number n, Number d ) {\n return floor( n / d );\n}\n\nfunction _mod ( Number n, Number d ) {\n return n - _div_floor( n, d ) * d;\n}\n\nfunction _rand_int ( Number max ) {\n return floor( Math.rand(max) );\n}\n\nfunction _bytes_to_binary ( Array bytes ) {\n let out := "";\n let i := 0;\n let n := bytes.length();\n\n while ( i < n ) {\n let b0 := bytes[i];\n let b1 := null;\n let b2 := null;\n if ( i + 1 < n ) {\n b1 := bytes[i + 1];\n }\n if ( i + 2 < n ) {\n b2 := bytes[i + 2];\n }\n\n let c0 := _div_floor( b0, 4 );\n let c1 := _mod( b0, 4 ) * 16;\n let c2 := 64;\n let c3 := 64;\n\n if ( b1 \u2262 null ) {\n c1 += _div_floor( b1, 16 );\n c2 := _mod( b1, 16 ) * 4;\n if ( b2 \u2262 null ) {\n c2 += _div_floor( b2, 64 );\n c3 := _mod( b2, 64 );\n }\n }\n\n out _= substr( _B64_ALPHABET, c0, 1 );\n out _= substr( _B64_ALPHABET, c1, 1 );\n if ( c2 \u2261 64 ) {\n out _= "=";\n }\n else {\n out _= substr( _B64_ALPHABET, c2, 1 );\n }\n if ( c3 \u2261 64 ) {\n out _= "=";\n }\n else {\n out _= substr( _B64_ALPHABET, c3, 1 );\n }\n\n i += 3;\n }\n\n return decode(out);\n}\n\nfunction _timestamp_words () {\n // Seconds between 1582-10-15 and 1970-01-01.\n let epoch_offset := 12219292800;\n let seconds := floor( new Time().epoch() ) + epoch_offset;\n let ticks := _rand_int(10000000);\n\n let words := [\n _mod( seconds, 65536 ),\n _mod( _div_floor( seconds, 65536 ), 65536 ),\n _mod( _div_floor( seconds, 4294967296 ), 65536 ),\n 0,\n 0,\n ];\n\n let scale := 10000000;\n let i := 0;\n let carry := 0;\n while ( i < words.length() ) {\n let product := words[i] * scale + carry;\n words[i] := _mod( product, 65536 );\n carry := _div_floor( product, 65536 );\n i++;\n }\n\n let add_i := 0;\n let add_carry := ticks;\n while ( add_carry > 0 and add_i < words.length() ) {\n let sum := words[add_i] + _mod( add_carry, 65536 );\n words[add_i] := _mod( sum, 65536 );\n add_carry := _div_floor( add_carry, 65536 ) + _div_floor( sum, 65536 );\n add_i++;\n }\n\n return words;\n}\n\nfunction _create_uuid_bytes () {\n let words := _timestamp_words();\n let time_low := words[0] + words[1] * 65536;\n let time_mid := words[2];\n let time_hi_and_version := _mod( words[3], 4096 ) + 4096;\n\n let clock_seq := _rand_int(16384);\n let clock_seq_hi_and_reserved := _mod( _div_floor( clock_seq, 256 ), 64 ) + 128;\n let clock_seq_low := _mod( clock_seq, 256 );\n\n let node := [];\n let j := 0;\n while ( j < 6 ) {\n node.push( _rand_int(256) );\n j++;\n }\n // Multicast bit set means this is not an IEEE MAC address.\n node[0] := node[0] | 1;\n\n return [\n _mod( _div_floor( time_low, 16777216 ), 256 ),\n _mod( _div_floor( time_low, 65536 ), 256 ),\n _mod( _div_floor( time_low, 256 ), 256 ),\n _mod( time_low, 256 ),\n _mod( _div_floor( time_mid, 256 ), 256 ),\n _mod( time_mid, 256 ),\n _mod( _div_floor( time_hi_and_version, 256 ), 256 ),\n _mod( time_hi_and_version, 256 ),\n clock_seq_hi_and_reserved,\n clock_seq_low,\n node[0],\n node[1],\n node[2],\n node[3],\n node[4],\n node[5],\n ];\n}\n\nfunction _byte_to_hex ( Number b ) {\n let hi := _div_floor( b, 16 );\n let lo := _mod( b, 16 );\n return substr( _HEX_ALPHABET, hi, 1 ) _ substr( _HEX_ALPHABET, lo, 1 );\n}\n\nfunction _bytes_to_uuid_text ( Array bytes ) {\n let out := "";\n let i := 0;\n while ( i < 16 ) {\n out _= _byte_to_hex( bytes[i] );\n if ( i \u2261 3 or i \u2261 5 or i \u2261 7 or i \u2261 9 ) {\n out _= "-";\n }\n i++;\n }\n return out;\n}\n\nfunction create_uuid_binary () {\n return _bytes_to_binary( _create_uuid_bytes() );\n}\n\nfunction create_uuid () {\n return _bytes_to_uuid_text( _create_uuid_bytes() );\n}\n';
|
|
39666
41585
|
virtualFiles["/modules/std/dump.zzm"] = `=encoding utf8
|
|
39667
41586
|
|
|
39668
41587
|
=head1 NAME
|
|
@@ -45423,7 +47342,7 @@ const STANDARD_FUNCTIONS := [
|
|
|
45423
47342
|
virtualFiles["/modules/std/path/z/parser.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/path/z/parser - Pure Zuzu parser for ZPath expressions.\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module provides the pure-Zuzu parser used by ZPath.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<< Parser({ lexer_class?, allowed_operators }) >>\n\nConstructs a ZPath parser. Returns: C<Parser>.\n\n=over\n\n=item C<< parser.parse_top_level_terms(src) >>\n\nParameters: C<src> is a ZPath expression string. Returns: C<Array>.\nParses comma-separated top-level expression terms.\n\n=item C<< parser.parse_expression(lx) >>\n\nParameters: C<lx> is a C<Lexer>. Returns: C<Dict>. Parses an expression.\n\n=item C<< parser.parse_ternary(lx) >>\n\nParameters: C<lx> is a C<Lexer>. Returns: C<Dict>. Parses ternary and\nElvis expressions.\n\n=item C<< parser.parse_subexpression(lx, min_prec) >>\n\nParameters: C<lx> is a C<Lexer> and C<min_prec> is a precedence floor.\nReturns: C<Dict>. Parses a precedence-climbing subexpression.\n\n=item C<< parser.parse_primary(lx) >>\n\nParameters: C<lx> is a C<Lexer>. Returns: C<Dict>. Parses a primary\nexpression.\n\n=back\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/path/z/parser >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/string import trim;\nfrom std/path/z/lexer import Lexer;\n\nclass Parser {\n let lexer_class;\n let allowed_operators;\n let _binop_prec := {};\n let _unop_prec := {};\n let _need_ws := {};\n let _right_assoc := {};\n let _path_terminators := {};\n let _allow_elvis := false;\n\n method __build__ () {\n lexer_class ?:= Lexer;\n self._init_path_terminators();\n for ( let op in allowed_operators ) {\n let spell := op.get_spelling();\n if ( op.is_unary() ) {\n _unop_prec.set( spell, op.get_precedence() );\n }\n else {\n if ( op.get_kind() \u2261 "ELVIS" ) {\n _allow_elvis := true;\n _path_terminators.set( op.get_kind(), true );\n next;\n }\n _binop_prec.set( spell, op.get_precedence() );\n _path_terminators.set( op.get_kind(), true );\n if ( op.has_alias() ) {\n _path_terminators.set( op.get_alias(), true );\n }\n if ( op.requires_whitespace() ) {\n _need_ws.set( spell, true );\n }\n if ( op.is_right_associative() ) {\n _right_assoc.set( spell, true );\n }\n }\n }\n }\n\n method _init_path_terminators () {\n for ( let k in [\n "EOF",\n "COMMA",\n "RPAREN",\n "RBRACK",\n "QMARK",\n "COLON",\n ] ) {\n _path_terminators.set( k, true );\n }\n }\n\n method parse_top_level_terms ( src ) {\n let terms := [];\n let lexer := new lexer_class(\n src: src,\n allowed_operators: allowed_operators,\n );\n\n while ( true ) {\n let expr := self.parse_expression(lexer);\n terms.push(expr);\n if ( lexer.peek_kind() \u2261 "COMMA" ) {\n lexer.next_tok();\n next;\n }\n lexer.expect("EOF");\n last;\n }\n\n return terms;\n }\n\n method _trim ( s ) {\n return trim(s);\n }\n\n method parse_expression ( lx ) {\n return self.parse_ternary(lx);\n }\n\n method parse_ternary ( lx ) {\n let cond := self.parse_subexpression( lx, 1 );\n\n if ( lx.peek_kind() \u2261 "QMARK" ) {\n lx.next_tok();\n let then := self.parse_expression(lx); // ZZPath should use: self.parse_subexpression( lx, 1 )\n lx.expect("COLON");\n let els := self.parse_expression(lx);\n return { t: "ternary", c: cond, a: then, b: els };\n }\n if ( _allow_elvis and lx.peek_kind() \u2261 "ELVIS" ) {\n lx.next_tok();\n let fallback := self.parse_expression(lx);\n return { t: "elvis", c: cond, b: fallback };\n }\n\n return cond;\n }\n\n method parse_subexpression ( lx, min_prec ) {\n let left := self._parse_maybe_unary( lx, min_prec );\n\n while ( true ) {\n let spell := lx.peek{v};\n let op_prec := _binop_prec.get( spell, null );\n last if op_prec \u2261 null or op_prec < min_prec;\n\n let op := lx.next_tok;\n if ( _need_ws.exists( spell ) ) {\n if ( not ( op{ws_before} and op{ws_after} ) ) {\n die `Binary operator \'${spell}\' requires whitespace around it`;\n }\n }\n\n let next_min := _right_assoc.exists(spell) ? op_prec : op_prec + 1;\n let right := self.parse_subexpression( lx, next_min );\n left := { t: "bin", op: spell, l: left, r: right };\n }\n\n return left;\n }\n\n method _parse_maybe_unary ( lx, min_prec ) {\n let spell := lx.peek{v};\n let op_prec := _unop_prec.get( spell, null );\n if ( op_prec \u2262 null and op_prec >= min_prec ) {\n let op := lx.next_tok{v};\n let e := self._parse_maybe_unary( lx, op_prec );\n return { t: "un", op: op, e: e };\n }\n return self.parse_primary( lx );\n }\n\n method parse_primary ( lx ) {\n let k := lx.peek_kind;\n\n if ( k \u2261 "NUMBER" ) {\n return { t: "num", v: lx.next_tok(){v} };\n }\n if ( k \u2261 "STRING" ) {\n return { t: "str", v: lx.next_tok(){v} };\n }\n if ( k \u2261 "LPAREN" ) {\n lx.next_tok();\n let e := self.parse_expression(lx);\n lx.expect("RPAREN");\n return e;\n }\n\n if ( k \u2261 "NAME" and lx.peek_kind_n(1) \u2261 "LPAREN" ) {\n let name := lx.next_tok(){v};\n lx.expect("LPAREN");\n let args := [];\n if ( lx.peek_kind() \u2262 "RPAREN" ) {\n args.push( self.parse_expression(lx) );\n while ( lx.peek_kind() \u2261 "COMMA" ) {\n lx.next_tok();\n args.push( self.parse_expression(lx) );\n }\n }\n lx.expect("RPAREN");\n return { t: "fn", n: name, a: args };\n }\n\n return self._parse_path_expr(lx);\n }\n\n method _is_path_terminator ( k ) {\n return _path_terminators.exists(k);\n }\n\n method _parse_path_expr ( lx ) {\n let segs := [];\n\n if ( lx.peek_kind() \u2261 "SLASH_PATH" ) {\n lx.next_tok();\n let root := { k: "root", q: [] };\n segs.push(root);\n\n if ( lx.peek_kind() \u2261 "LBRACK" ) {\n root{q} := self._parse_qualifiers(lx);\n }\n\n if ( self._is_path_terminator( lx.peek_kind() ) ) {\n return { t: "path", s: segs };\n }\n }\n else if ( lx.peek_kind() \u2261 "LBRACK" ) {\n let seg := { k: "dot", q: self._parse_qualifiers(lx) };\n segs.push(seg);\n if ( self._is_path_terminator( lx.peek_kind() ) ) {\n return { t: "path", s: segs };\n }\n }\n\n if (\n lx.peek_kind() \u2262 "SLASH_PATH"\n and not self._is_path_terminator( lx.peek_kind() )\n ) {\n segs.push( self._parse_path_segment(lx) );\n }\n\n while ( lx.peek_kind() \u2261 "SLASH_PATH" ) {\n lx.next_tok();\n if ( lx.peek_kind() \u2261 "LBRACK" ) {\n let seg := { k: "star", q: [] };\n seg{q} := self._parse_qualifiers(lx);\n segs.push(seg);\n next;\n }\n segs.push( self._parse_path_segment(lx) );\n }\n\n return { t: "path", s: segs };\n }\n\n method _parse_path_segment ( lx ) {\n let k := lx.peek_kind();\n let seg := null;\n\n if ( k \u2261 "DOT" ) {\n lx.next_tok();\n seg := { k: "dot" };\n }\n else if ( k \u2261 "DOTDOT" ) {\n lx.next_tok();\n seg := { k: "parent" };\n }\n else if ( k \u2261 "DOTDOTSTAR" ) {\n lx.next_tok();\n seg := { k: "ancestors" };\n }\n else if ( k \u2261 "STAR_PATH" ) {\n lx.next_tok();\n seg := { k: "star" };\n }\n else if ( k \u2261 "STARSTAR" ) {\n lx.next_tok();\n seg := { k: "desc" };\n }\n else if ( k \u2261 "INDEX" ) {\n let i := lx.next_tok(){v};\n seg := { k: "index", i: i };\n }\n else if ( k \u2261 "NUMBER" ) {\n let i := lx.next_tok(){v};\n seg := { k: "index", i: i };\n }\n else if ( k \u2261 "NAME" and lx.peek_kind_n(1) \u2261 "LPAREN" ) {\n let name := lx.next_tok(){v};\n lx.expect("LPAREN");\n let args := [];\n if ( lx.peek_kind() \u2262 "RPAREN" ) {\n args.push( self.parse_expression(lx) );\n while ( lx.peek_kind() \u2261 "COMMA" ) {\n lx.next_tok();\n args.push( self.parse_expression(lx) );\n }\n }\n lx.expect("RPAREN");\n seg := { k: "fnseg", n: name, a: args };\n }\n else if ( k \u2261 "NAME" ) {\n let n := lx.next_tok(){v};\n seg := { k: "name", n: n };\n }\n else {\n die `Unexpected token in path segment: ${k}`;\n }\n\n if ( seg{k} \u2261 "name" and lx.peek_kind() \u2261 "INDEX" ) {\n seg{i} := lx.next_tok(){v};\n }\n\n seg{q} := self._parse_qualifiers(lx);\n return seg;\n }\n\n method _parse_qualifiers ( lx ) {\n let q := [];\n\n while ( lx.peek_kind() \u2261 "LBRACK" ) {\n lx.next_tok();\n let e := self.parse_expression(lx);\n lx.expect("RBRACK");\n q.push(e);\n }\n\n return q;\n }\n}\n';
|
|
45424
47343
|
virtualFiles["/modules/std/path/zz.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/path/zz - ZuzuScript-flavoured path selectors.\n\n=head1 SYNOPSIS\n\n from std/path/zz import ZZPath;\n\n let data := { users: [ { name: "Ada" } ] };\n say( ( new ZZPath( path: "/users/#0/name" ) ).first(data) );\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module provides the public C<ZZPath> class. It currently reuses the\nZPath traversal, parser, lexer, assignment, and reference\nmachinery while routing expression operators through\nC<std/path/zz/operators> and expression functions through\nC<std/path/zz/functions>.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<ZZEvaluator>\n\nEvaluator class that supplies ZZPath operators and functions.\n\n=over\n\n=item C<< evaluator.operator_definitions() >>\n\nParameters: none. Returns: C<Array>. Returns ZZPath operator\ndefinitions.\n\n=item C<< evaluator.function_definitions() >>\n\nParameters: none. Returns: C<Array>. Returns ZZPath function\ndefinitions.\n\n=back\n\n=item C<< ZZPath({ path: String }) >>\n\nConstructs a ZZPath query object. Returns: C<ZZPath>. Inherits the\npublic query, assignment, and reference methods from C<ZPath>.\n\n=over\n\n=item C<< path.get_evaluator() >>\n\nParameters: none. Returns: C<ZZEvaluator>. Returns the evaluator used\nfor this path.\n\n=item C<< node.find(path) >>\n\nC<ZZPath> inherits from C<ZPath>, so a C<ZZPath> object can be passed to\nC<std/path/z/node> C<Node.find()>.\n\n=back\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/path/zz >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/path/z import ZPath;\nfrom std/path/z/evaluate import Evaluator as ZEvaluator;\n\nclass ZZEvaluator extends ZEvaluator {\n method operator_definitions () {\n from std/path/zz/operators import STANDARD_OPERATORS;\n return STANDARD_OPERATORS;\n }\n\n method function_definitions () {\n from std/path/zz/functions import STANDARD_FUNCTIONS;\n return STANDARD_FUNCTIONS;\n }\n}\n\nclass ZZPath extends ZPath {\n method get_evaluator () {\n return new ZZEvaluator();\n }\n}\n';
|
|
45425
47344
|
virtualFiles["/modules/std/path/zz/functions.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/path/zz/functions - Function definitions for ZZPath expressions.\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module extends the base ZPath function table with\nZuzuScript-flavoured path expression helpers.\n\n=head1 EXPORTS\n\n=head2 Constants\n\n=over\n\n=item C<STANDARD_FUNCTION_NAMES>\n\nType: C<Array>. Names of inherited ZPath functions available to ZZPath.\n\n=item C<STANDARD_FUNCTIONS>\n\nType: C<Array>. Complete ZZPath function definition table.\n\n=back\n\n=head2 Functions\n\n=over\n\n=item C<< first_arg_node(name, ev, ctx, args) >>\n\nParameters: function name, evaluator, context, and argument AST nodes.\nReturns: C<Node> or C<null>. Resolves the first argument or current\ncontext node.\n\n=item C<< first_number_arg(name, ev, ctx, args) >>, C<< nth_number_arg(name, ev, ctx, args, i) >>\n\nParameters: function name, evaluator, context, arguments, and optional\nindex. Returns: C<Number>. Resolves an argument as a number.\n\n=item C<< first_string_arg(name, ev, ctx, args) >>, C<< nth_string_arg(name, ev, ctx, args, i) >>\n\nParameters: function name, evaluator, context, arguments, and optional\nindex. Returns: C<String>. Resolves an argument as a string.\n\n=item C<< nth_value_arg(name, ev, ctx, args, i) >>\n\nParameters: function name, evaluator, context, arguments, and index.\nReturns: value. Resolves an argument as a primitive value.\n\n=item C<< nth_array_arg(name, ev, ctx, args, i) >>\n\nParameters: function name, evaluator, context, arguments, and index.\nReturns: C<Array>. Resolves an argument as an array value.\n\n=item C<< number_args(ev, ctx, args) >>\n\nParameters: evaluator, context, and argument AST nodes. Returns:\nC<Array>. Resolves all arguments as numbers.\n\n=item C<< first_arg_value(name, ev, ctx, args) >>\n\nParameters: function name, evaluator, context, and arguments. Returns:\nvalue. Resolves the first argument as a primitive value.\n\n=item C<< z_function(spelling) >>\n\nParameters: C<spelling> is a base ZPath function name. Returns:\nC<Function>. Returns the inherited function implementation.\n\n=item C<< string_index_of(funk, ev, ast, ctx, args) >>\n\nParameters: standard ZPath function callback arguments. Returns:\nC<Array>. Implements string C<index-of>.\n\n=item C<< string_rindex(funk, ev, ast, ctx, args) >>\n\nParameters: standard ZPath function callback arguments. Returns:\nC<Array>. Implements string reverse-index lookup.\n\n=item C<< defined_function(funk, ev, ast, ctx, args) >>\n\nParameters: standard ZPath function callback arguments. Returns:\nC<Array>. Implements defined-value testing.\n\n=item C<< empty_function(funk, ev, ast, ctx, args) >>\n\nParameters: standard ZPath function callback arguments. Returns:\nC<Array>. Implements empty-value testing.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/path/zz/functions >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/path/z/functions import Func, STANDARD_FUNCTIONS as Z_STANDARD_FUNCTIONS;\n\n\nconst STANDARD_FUNCTION_NAMES := [\n "true",\n "false",\n "null",\n "tag",\n "url",\n "local-name",\n "key",\n "value",\n "index",\n "count",\n "is-first",\n "is-last",\n "next",\n "prev",\n];\n\nfunction first_arg_node ( name, ev, ctx, args ) {\n if ( args.length() = 0 ) {\n return ctx.nodeset.get( 0, null );\n }\n if ( args.length() = 1 ) {\n const got := ev.eval_expr( args[0], ev.nested_ctx( ctx ) );\n return got.get( 0, null );\n }\n die `Too many arguments for ${name}()`;\n}\n\nfunction first_number_arg ( name, ev, ctx, args ) {\n const node := first_arg_node( name, ev, ctx, args );\n return ev.to_number(node) ?: 0;\n}\n\nfunction nth_number_arg ( name, ev, ctx, args, i ) {\n die `Not enough arguments for ${name}()` if args.length() <= i;\n const got := ev.eval_expr( args[i], ev.nested_ctx( ctx ) );\n return ev.to_number( got.get( 0, null ) ) ?: 0;\n}\n\nfunction nth_string_arg ( name, ev, ctx, args, i ) {\n die `Not enough arguments for ${name}()` if args.length() <= i;\n const got := ev.eval_expr( args[i], ev.nested_ctx( ctx ) );\n const value := ev.to_string( got.get( 0, null ) );\n return value \u2261 null ? "" : "" _ value;\n}\n\nfunction nth_value_arg ( name, ev, ctx, args, i ) {\n die `Not enough arguments for ${name}()` if args.length() <= i;\n const got := ev.eval_expr( args[i], ev.nested_ctx( ctx ) );\n const node := got.get( 0, null );\n return node \u2261 null ? null : node.primitive_value();\n}\n\nfunction nth_array_arg ( name, ev, ctx, args, i ) {\n die `Not enough arguments for ${name}()` if args.length() <= i;\n const got := ev.eval_expr( args[i], ev.nested_ctx( ctx ) );\n if ( got.length() = 1 ) {\n const one := got[0].primitive_value();\n return one if one instanceof Array;\n }\n return got.map( fn node \u2192 node.primitive_value() );\n}\n\nfunction number_args ( ev, ctx, args ) {\n let nums := [];\n if ( args.length() = 0 ) {\n for ( let node in ctx.nodeset ) {\n const value := ev.to_number(node);\n nums.push(value) if value instanceof Number;\n }\n return nums;\n }\n for ( let arg in args ) {\n const got := ev.eval_expr( arg, ev.nested_ctx( ctx ) );\n for ( let node in got ) {\n const value := ev.to_number(node);\n nums.push(value) if value instanceof Number;\n }\n }\n return nums;\n}\n\nfunction first_string_arg ( name, ev, ctx, args ) {\n const node := first_arg_node( name, ev, ctx, args );\n const value := ev.to_string(node);\n return value \u2261 null ? "" : "" _ value;\n}\n\nfunction first_arg_value ( name, ev, ctx, args ) {\n const node := first_arg_node( name, ev, ctx, args );\n return node \u2261 null ? null : node.primitive_value();\n}\n\nfunction z_function ( spelling ) {\n const func := Z_STANDARD_FUNCTIONS.first( fn f \u2192 f.has_name(spelling) );\n die `std/path/z/functions is missing ${spelling}()` if func \u2261 null;\n return func;\n}\n\nfunction string_index_of ( funk, ev, ast, ctx, args ) {\n from std/string import index;\n die "Too many arguments for index-of()" if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( index(\n nth_string_arg( "index-of", ev, ctx, args, 0 ),\n nth_string_arg( "index-of", ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( index(\n nth_string_arg( "index-of", ev, ctx, args, 0 ),\n nth_string_arg( "index-of", ev, ctx, args, 1 ),\n nth_number_arg( "index-of", ev, ctx, args, 2 ),\n ) );\n}\n\nfunction string_rindex ( funk, ev, ast, ctx, args ) {\n from std/string import rindex;\n const name := funk.get_spelling;\n die `Too many arguments for ${name}()` if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( rindex(\n nth_string_arg( name, ev, ctx, args, 0 ),\n nth_string_arg( name, ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( rindex(\n nth_string_arg( name, ev, ctx, args, 0 ),\n nth_string_arg( name, ev, ctx, args, 1 ),\n nth_number_arg( name, ev, ctx, args, 2 ),\n ) );\n}\n\nfunction defined_function ( funk, ev, ast, ctx, args ) {\n const node := first_arg_node( "defined", ev, ctx, args );\n return funk.wrap( node \u2262 null and node.primitive_value() \u2262 null );\n}\n\nfunction empty_function ( funk, ev, ast, ctx, args ) {\n const value := first_arg_value( "empty", ev, ctx, args );\n return funk.wrap( true ) if value \u2261 null;\n\n if (\n value instanceof Array or\n value instanceof Bag or\n value instanceof Set or\n value instanceof Dict or\n value instanceof PairList\n ) {\n return funk.wrap( value.length() = 0 );\n }\n\n die `empty() expects a Collection or null, got ${typeof value}`;\n}\n\n// Start with a base of functions inherited from ZPath:\nconst STANDARD_FUNCTIONS := STANDARD_FUNCTION_NAMES.map( fn n \u2192 z_function(n) );\n\n// Add equivalents for ZuzuScript word-like unary operators:\nSTANDARD_FUNCTIONS.push(\n new Func(\n spelling: "abs",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( abs first_number_arg( "abs", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "floor",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( floor first_number_arg( "floor", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "ceil",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( ceil first_number_arg( "ceil", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "round",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( round first_number_arg( "round", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "int",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( int first_number_arg( "int", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "sqrt",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( sqrt first_number_arg( "sqrt", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "uc",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( uc first_string_arg( "uc", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "lc",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( lc first_string_arg( "lc", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "length",\n f: function ( funk, ev, ast, ctx, args ) {\n return funk.wrap( length first_string_arg( "length", ev, ctx, args ) );\n },\n ),\n new Func(\n spelling: "not",\n f: function ( funk, ev, ast, ctx, args ) {\n const node := first_arg_node( "not", ev, ctx, args );\n return funk.wrap( not ev.truthy(node) );\n },\n ),\n new Func(\n spelling: "typeof",\n f: function ( funk, ev, ast, ctx, args ) {\n const node := first_arg_node( "typeof", ev, ctx, args );\n const value := node \u2261 null ? null : node.primitive_value();\n return funk.wrap( typeof value );\n },\n ),\n new Func(\n spelling: "defined",\n f: defined_function,\n ),\n new Func(\n spelling: "empty",\n f: empty_function,\n ),\n);\n\n// Functions from std/internals:\nSTANDARD_FUNCTIONS.push(\n new Func(\n spelling: "string",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/internals import to_String;\n return funk.wrap( to_String( first_arg_value(\n "string",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "number",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/internals import to_Number;\n return funk.wrap( to_Number( first_arg_value(\n "number",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "boolean",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/internals import to_Boolean;\n return funk.wrap( to_Boolean( first_arg_value(\n "boolean",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "regexp",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/internals import to_Regexp;\n return funk.wrap( to_Regexp( first_arg_value(\n "regexp",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n);\n\n// Functions from std/math:\nSTANDARD_FUNCTIONS.push(\n new Func(\n spelling: "sum",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/math import Math;\n return funk.wrap( Math.sum( number_args( ev, ctx, args ) ) );\n },\n ),\n new Func(\n spelling: "min",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/math import Math;\n return funk.wrap( Math.min( number_args( ev, ctx, args ) ) );\n },\n ),\n new Func(\n spelling: "max",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/math import Math;\n return funk.wrap( Math.max( number_args( ev, ctx, args ) ) );\n },\n ),\n new Func(\n spelling: "clamp",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/math import Math;\n die "Too many arguments for clamp()" if args.length() > 3;\n return funk.wrap( Math.clamp(\n nth_number_arg( "clamp", ev, ctx, args, 0 ),\n nth_number_arg( "clamp", ev, ctx, args, 1 ),\n nth_number_arg( "clamp", ev, ctx, args, 2 ),\n ) );\n },\n ),\n);\n\n// Functions from std/string:\nSTANDARD_FUNCTIONS.push(\n new Func(\n spelling: "substr",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import substr;\n die "Too many arguments for substr()" if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( substr(\n nth_string_arg( "substr", ev, ctx, args, 0 ),\n nth_number_arg( "substr", ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( substr(\n nth_string_arg( "substr", ev, ctx, args, 0 ),\n nth_number_arg( "substr", ev, ctx, args, 1 ),\n nth_number_arg( "substr", ev, ctx, args, 2 ),\n ) );\n },\n ),\n new Func(\n spelling: "index-of",\n f: string_index_of,\n ),\n new Func(\n spelling: "rindex",\n f: string_rindex,\n ),\n new Func(\n spelling: "last-index-of",\n f: string_rindex,\n ),\n new Func(\n spelling: "contains",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import contains;\n die "Too many arguments for contains()" if args.length() > 2;\n return funk.wrap( contains(\n nth_string_arg( "contains", ev, ctx, args, 0 ),\n nth_string_arg( "contains", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "chr",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import chr;\n die "Too many arguments for chr()" if args.length() > 1;\n return funk.wrap( chr( nth_number_arg(\n "chr",\n ev,\n ctx,\n args,\n 0,\n ) ) );\n },\n ),\n new Func(\n spelling: "ord",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import ord;\n die "Too many arguments for ord()" if args.length() > 2;\n if ( args.length() = 1 ) {\n return funk.wrap( ord( nth_string_arg(\n "ord",\n ev,\n ctx,\n args,\n 0,\n ) ) );\n }\n return funk.wrap( ord(\n nth_string_arg( "ord", ev, ctx, args, 0 ),\n nth_number_arg( "ord", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "replace",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import replace;\n die "Too many arguments for replace()" if args.length() > 4;\n if ( args.length() = 3 ) {\n return funk.wrap( replace(\n nth_string_arg( "replace", ev, ctx, args, 0 ),\n nth_value_arg( "replace", ev, ctx, args, 1 ),\n nth_string_arg( "replace", ev, ctx, args, 2 ),\n ) );\n }\n return funk.wrap( replace(\n nth_string_arg( "replace", ev, ctx, args, 0 ),\n nth_value_arg( "replace", ev, ctx, args, 1 ),\n nth_string_arg( "replace", ev, ctx, args, 2 ),\n nth_string_arg( "replace", ev, ctx, args, 3 ),\n ) );\n },\n ),\n new Func(\n spelling: "search",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import search;\n die "Too many arguments for search()" if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( search(\n nth_string_arg( "search", ev, ctx, args, 0 ),\n nth_value_arg( "search", ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( search(\n nth_string_arg( "search", ev, ctx, args, 0 ),\n nth_value_arg( "search", ev, ctx, args, 1 ),\n nth_string_arg( "search", ev, ctx, args, 2 ),\n ) );\n },\n ),\n new Func(\n spelling: "starts_with",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import starts_with;\n die "Too many arguments for starts_with()" if args.length() > 2;\n return funk.wrap( starts_with(\n nth_string_arg( "starts_with", ev, ctx, args, 0 ),\n nth_string_arg( "starts_with", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "ends_with",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import ends_with;\n die "Too many arguments for ends_with()" if args.length() > 2;\n return funk.wrap( ends_with(\n nth_string_arg( "ends_with", ev, ctx, args, 0 ),\n nth_string_arg( "ends_with", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "matches",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import matches;\n die "Too many arguments for matches()" if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( matches(\n nth_string_arg( "matches", ev, ctx, args, 0 ),\n nth_value_arg( "matches", ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( matches(\n nth_string_arg( "matches", ev, ctx, args, 0 ),\n nth_value_arg( "matches", ev, ctx, args, 1 ),\n nth_string_arg( "matches", ev, ctx, args, 2 ),\n ) );\n },\n ),\n new Func(\n spelling: "pattern_to_regexp",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import pattern_to_regexp;\n die "Too many arguments for pattern_to_regexp()"\n if args.length() > 2;\n if ( args.length() = 1 ) {\n return funk.wrap( pattern_to_regexp(\n nth_string_arg( "pattern_to_regexp", ev, ctx, args, 0 ),\n ) );\n }\n return funk.wrap( pattern_to_regexp(\n nth_string_arg( "pattern_to_regexp", ev, ctx, args, 0 ),\n nth_value_arg( "pattern_to_regexp", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "quotemeta",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import quotemeta;\n die "Too many arguments for quotemeta()" if args.length() > 1;\n return funk.wrap( quotemeta(\n nth_string_arg( "quotemeta", ev, ctx, args, 0 ),\n ) );\n },\n ),\n new Func(\n spelling: "sprint",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import sprint;\n die "Not enough arguments for sprint()" if args.length() = 0;\n die "Too many arguments for sprint()" if args.length() > 8;\n\n const fmt := nth_string_arg( "sprint", ev, ctx, args, 0 );\n if ( args.length() = 1 ) {\n return funk.wrap( sprint(fmt) );\n }\n if ( args.length() = 2 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n ) );\n }\n if ( args.length() = 3 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n ) );\n }\n if ( args.length() = 4 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n nth_value_arg( "sprint", ev, ctx, args, 3 ),\n ) );\n }\n if ( args.length() = 5 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n nth_value_arg( "sprint", ev, ctx, args, 3 ),\n nth_value_arg( "sprint", ev, ctx, args, 4 ),\n ) );\n }\n if ( args.length() = 6 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n nth_value_arg( "sprint", ev, ctx, args, 3 ),\n nth_value_arg( "sprint", ev, ctx, args, 4 ),\n nth_value_arg( "sprint", ev, ctx, args, 5 ),\n ) );\n }\n if ( args.length() = 7 ) {\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n nth_value_arg( "sprint", ev, ctx, args, 3 ),\n nth_value_arg( "sprint", ev, ctx, args, 4 ),\n nth_value_arg( "sprint", ev, ctx, args, 5 ),\n nth_value_arg( "sprint", ev, ctx, args, 6 ),\n ) );\n }\n return funk.wrap( sprint(\n fmt,\n nth_value_arg( "sprint", ev, ctx, args, 1 ),\n nth_value_arg( "sprint", ev, ctx, args, 2 ),\n nth_value_arg( "sprint", ev, ctx, args, 3 ),\n nth_value_arg( "sprint", ev, ctx, args, 4 ),\n nth_value_arg( "sprint", ev, ctx, args, 5 ),\n nth_value_arg( "sprint", ev, ctx, args, 6 ),\n nth_value_arg( "sprint", ev, ctx, args, 7 ),\n ) );\n },\n ),\n new Func(\n spelling: "split",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import split;\n die "Too many arguments for split()" if args.length() > 3;\n if ( args.length() = 2 ) {\n return funk.wrap( split(\n nth_string_arg( "split", ev, ctx, args, 0 ),\n nth_value_arg( "split", ev, ctx, args, 1 ),\n ) );\n }\n return funk.wrap( split(\n nth_string_arg( "split", ev, ctx, args, 0 ),\n nth_value_arg( "split", ev, ctx, args, 1 ),\n nth_number_arg( "split", ev, ctx, args, 2 ),\n ) );\n },\n ),\n new Func(\n spelling: "join",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import join;\n die "Too many arguments for join()" if args.length() > 2;\n return funk.wrap( join(\n nth_string_arg( "join", ev, ctx, args, 0 ),\n nth_array_arg( "join", ev, ctx, args, 1 ),\n ) );\n },\n ),\n new Func(\n spelling: "trim",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import trim;\n die "Too many arguments for trim()" if args.length() > 1;\n return funk.wrap( trim( first_string_arg(\n "trim",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "pad",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import pad;\n die "Too many arguments for pad()" if args.length() > 4;\n if ( args.length() = 2 ) {\n return funk.wrap( pad(\n nth_string_arg( "pad", ev, ctx, args, 0 ),\n nth_number_arg( "pad", ev, ctx, args, 1 ),\n ) );\n }\n if ( args.length() = 3 ) {\n return funk.wrap( pad(\n nth_string_arg( "pad", ev, ctx, args, 0 ),\n nth_number_arg( "pad", ev, ctx, args, 1 ),\n nth_string_arg( "pad", ev, ctx, args, 2 ),\n ) );\n }\n return funk.wrap( pad(\n nth_string_arg( "pad", ev, ctx, args, 0 ),\n nth_number_arg( "pad", ev, ctx, args, 1 ),\n nth_string_arg( "pad", ev, ctx, args, 2 ),\n nth_string_arg( "pad", ev, ctx, args, 3 ),\n ) );\n },\n ),\n new Func(\n spelling: "chomp",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import chomp;\n die "Too many arguments for chomp()" if args.length() > 1;\n return funk.wrap( chomp( first_string_arg(\n "chomp",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "title",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import title;\n die "Too many arguments for title()" if args.length() > 1;\n return funk.wrap( title( first_string_arg(\n "title",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "snake",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import snake;\n die "Too many arguments for snake()" if args.length() > 1;\n return funk.wrap( snake( first_string_arg(\n "snake",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "kebab",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import kebab;\n die "Too many arguments for kebab()" if args.length() > 1;\n return funk.wrap( kebab( first_string_arg(\n "kebab",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n new Func(\n spelling: "camel",\n f: function ( funk, ev, ast, ctx, args ) {\n from std/string import camel;\n die "Too many arguments for camel()" if args.length() > 1;\n return funk.wrap( camel( first_string_arg(\n "camel",\n ev,\n ctx,\n args,\n ) ) );\n },\n ),\n);\n';
|
|
45426
|
-
virtualFiles["/modules/std/path/zz/operators.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/path/zz/operators - Operator definitions for ZZPath expressions.\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module extends the base ZPath operator model with\nZuzuScript-flavoured expression operators.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<Operator>\n\nZZPath operator class extending C<std/path/z/operators> C<Operator>.\n\n=back\n\n=head2 Functions\n\n=over\n\n=item C<< string_operand(ev, ctx, expr) >>, C<< string_operands(ev, ctx, left, right) >>\n\nParameters: evaluator, context, and expression AST nodes. Returns:\nC<String> or C<Array>. Evaluates one or two operands as strings.\n\n=item C<< first_eval_value(values) >>, C<< primitive_eval_value(values) >>\n\nParameters: C<values> is an evaluated node array. Returns: value.\nExtracts the first or primitive value used by ZZPath operators.\n\n=item C<< collection_operand(ev, ctx, expr) >>\n\nParameters: evaluator, context, and expression AST node. Returns:\ncollection value. Evaluates an operand for collection operators.\n\n=item C<< builtin_can(value, method_name) >>\n\nParameters: C<value> is any value and C<method_name> is a method name.\nReturns: C<Boolean>. Tests whether built-in values support a method.\n\n=back\n\n=head2 Constants\n\n=over\n\n=item C<STANDARD_OPERATORS>\n\nType: C<Array>. Complete ZZPath operator definition table.\n\n=item C<logical_negation>, C<logical_and>, C<logical_nand>, C<logical_xor>, C<logical_or>\n\nType: C<Function>. Logical operator implementations.\n\n=item C<numeric_power>, C<numeric_multiplication>, C<numeric_division>, C<numeric_modulus>, C<numeric_addition>, C<numeric_subtraction>, C<numeric_equality>, C<numeric_inequality>, C<numeric_less_than>, C<numeric_greater_than>, C<numeric_less_than_or_equal>, C<numeric_greater_than_or_equal>, C<numeric_compare>\n\nType: C<Function>. Numeric operator implementations.\n\n=item C<string_concatenation>, C<string_equality>, C<string_inequality>, C<string_greater_than>, C<string_greater_than_or_equal>, C<string_less_than>, C<string_less_than_or_equal>, C<string_compare>, C<string_equality_insensitive>, C<string_inequality_insensitive>, C<string_greater_than_insensitive>, C<string_greater_than_or_equal_insensitive>, C<string_less_than_insensitive>, C<string_less_than_or_equal_insensitive>, C<string_compare_insensitive>\n\nType: C<Function>. String operator implementations.\n\n=item C<regexp_match>, C<bitwise_and>, C<bitwise_xor>, C<bitwise_or>, C<set_union>, C<set_intersection>, C<set_difference>, C<collection_membership>, C<collection_non_membership>, C<set_subsetof>, C<set_supersetof>, C<set_equivalentof>, C<type_aware_equality>, C<type_aware_inequality>, C<object_can>\n\nType: C<Function>. Regular expression, bitwise, collection, type-aware,\nand object capability operator implementations.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/path/zz/operators >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/path/z/operators import Operator as ZOperator;\n\n\nclass Operator extends ZOperator;\n\nconst logical_negation := function ( op, ev, ast, ctx, expr ) {\n const got := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n const value := got.length() > 0 ? got[0] : null;\n return op.wrap( not ev.truthy(value) );\n};\n\nconst numeric_power := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val ** right_val );\n};\n\nconst numeric_multiplication := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xD7 right_val );\n};\n\nconst numeric_division := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xF7 right_val );\n};\n\nconst numeric_modulus := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val mod right_val );\n};\n\nconst numeric_addition := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val + right_val );\n};\n\nconst numeric_subtraction := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val - right_val );\n};\n\nconst numeric_equality := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val = right_val );\n};\n\nconst numeric_inequality := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2260 right_val );\n};\n\nconst numeric_less_than := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val < right_val );\n};\n\nconst numeric_greater_than := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val > right_val );\n};\n\nconst numeric_less_than_or_equal := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2264 right_val );\n};\n\nconst numeric_greater_than_or_equal := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2265 right_val );\n};\n\nconst numeric_compare := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val <=> right_val );\n};\n\nfunction string_operand ( ev, ctx, expr ) {\n const result := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n return "" unless result.length;\n const value := ev.to_string( result[0] );\n return value \u2261 null ? "" : "" _ value;\n}\n\nfunction string_operands ( ev, ctx, left, right ) {\n return [\n string_operand( ev, ctx, left ),\n string_operand( ev, ctx, right ),\n ];\n}\n\nconst string_concatenation := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] _ values[1] );\n};\n\nconst string_equality := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] eq values[1] );\n};\n\nconst string_inequality := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ne values[1] );\n};\n\nconst string_greater_than := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] gt values[1] );\n};\n\nconst string_greater_than_or_equal := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ge values[1] );\n};\n\nconst string_less_than := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] lt values[1] );\n};\n\nconst string_less_than_or_equal := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] le values[1] );\n};\n\nconst string_compare := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] cmp values[1] );\n};\n\nconst string_equality_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val eq right_val );\n};\n\nconst string_inequality_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val ne right_val );\n};\n\nconst string_greater_than_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val gt right_val );\n};\n\nconst string_greater_than_or_equal_insensitive := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val ge right_val );\n};\n\nconst string_less_than_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val lt right_val );\n};\n\nconst string_less_than_or_equal_insensitive := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val le right_val );\n};\n\nconst string_compare_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val cmp right_val );\n};\n\nconst regexp_match := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ~ values[1] );\n};\n\nconst bitwise_and := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val & right_val );\n};\n\nconst bitwise_xor := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val ^ right_val );\n};\n\nconst bitwise_or := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val | right_val );\n};\n\nfunction first_eval_value ( values ) {\n return values.length() > 0 ? values[0] : null;\n}\n\nfunction primitive_eval_value ( values ) {\n const first := first_eval_value(values);\n return first \u2261 null ? null : first.primitive_value();\n}\n\nfunction collection_operand ( ev, ctx, expr ) {\n const values := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n if ( values.length() = 1 ) {\n return values[0].primitive_value();\n }\n return values.map( fn value \u2192 value.primitive_value() );\n}\n\nconst logical_and := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return ev.eval_expr( right, ev.nested_ctx( ctx ) );\n }\n return op.wrap(false);\n};\n\nconst logical_nand := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( not ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? false : true );\n};\n\nconst logical_xor := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n return op.wrap( ( left_truth xor right_truth ) ? true : false );\n};\n\nconst logical_or := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? true : false );\n};\n\nconst set_union := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val union right_val );\n};\n\nconst set_intersection := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val intersection right_val );\n};\n\nconst set_difference := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val \u2216 right_val );\n};\n\nconst collection_membership := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val in right_val );\n};\n\nconst collection_non_membership := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val \u2209 right_val );\n};\n\nconst set_subsetof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val subsetof right_val );\n};\n\nconst set_supersetof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val supersetof right_val );\n};\n\nconst set_equivalentof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val equivalentof right_val );\n};\n\nconst type_aware_equality := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.equals(\n first_eval_value(left_vals),\n first_eval_value(right_vals),\n ) );\n};\n\nconst type_aware_inequality := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( not ev.equals(\n first_eval_value(left_vals),\n first_eval_value(right_vals),\n ) );\n};\n\nfunction builtin_can ( value, method_name ) {\n return false if value \u2261 null\n or method_name \u2261 null\n or method_name eq "";\n\n if ( value instanceof Array or value instanceof Bag or value instanceof Set ) {\n return method_name in [\n "length",\n "empty",\n "contains",\n "push",\n "to_Array",\n "to_Bag",\n "to_Set",\n ];\n }\n if ( value instanceof Dict or value instanceof PairList ) {\n return method_name in [\n "length",\n "empty",\n "exists",\n "keys",\n "values",\n "to_Array",\n ];\n }\n if ( value instanceof String or value instanceof BinaryString ) {\n return method_name in [ "length" ];\n }\n return false;\n}\n\nconst object_can := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := primitive_eval_value(right_vals);\n return op.wrap(\n ( left_val can (right_val) ) or builtin_can( left_val, right_val )\n );\n};\n\nconst STANDARD_OPERATORS := [\n new Operator(\n spelling: "?:",\n kind: "ELVIS",\n precedence: 1,\n lex_ignore: true,\n ),\n\n new Operator(\n spelling: "+",\n kind: "UPLUS",\n unary: true,\n precedence: 20,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( +value );\n },\n ),\n\n new Operator(\n spelling: "-",\n kind: "UMINUS",\n unary: true,\n precedence: 20,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( -value );\n },\n ),\n\n new Operator(\n spelling: "\u221A",\n kind: "SQRT",\n unary: true,\n precedence: 20,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( sqrt value );\n },\n ),\n\n new Operator(\n spelling: "!",\n kind: "NOT",\n unary: true,\n precedence: 20,\n f: logical_negation,\n ),\n\n new Operator(\n spelling: "\xAC",\n kind: "NOTSYM",\n unary: true,\n precedence: 20,\n f: logical_negation,\n ),\n\n new Operator(\n spelling: "**",\n kind: "POW",\n require_ws: true,\n right_assoc: true,\n precedence: 13,\n f: numeric_power,\n ),\n\n new Operator(\n spelling: "\xD7",\n kind: "TIMES_SIGN",\n precedence: 12,\n f: numeric_multiplication,\n ),\n\n new Operator(\n spelling: "*",\n kind: "TIMES",\n require_ws: true,\n precedence: 12,\n lex_ignore: true,\n alias: "STAR",\n f: numeric_multiplication,\n ),\n\n new Operator(\n spelling: "\xF7",\n kind: "DIVIDE_SIGN",\n precedence: 12,\n f: numeric_division,\n ),\n\n new Operator(\n spelling: "/",\n kind: "DIVIDE",\n require_ws: true,\n precedence: 12,\n lex_ignore: true,\n alias: "SLASH",\n f: numeric_division,\n ),\n\n new Operator(\n spelling: "mod",\n kind: "MOD",\n precedence: 12,\n f: numeric_modulus,\n ),\n\n new Operator(\n spelling: "+",\n kind: "PLUS",\n require_ws: true,\n precedence: 11,\n f: numeric_addition,\n ),\n\n new Operator(\n spelling: "-",\n kind: "MINUS",\n require_ws: true,\n precedence: 11,\n f: numeric_subtraction,\n ),\n\n new Operator(\n spelling: "=",\n kind: "EQ",\n precedence: 5,\n f: numeric_equality,\n ),\n\n new Operator(\n spelling: "\u2260",\n kind: "NE",\n precedence: 5,\n f: numeric_inequality,\n ),\n\n new Operator(\n spelling: "<",\n kind: "LT",\n precedence: 5,\n f: numeric_less_than,\n ),\n\n new Operator(\n spelling: ">",\n kind: "GT",\n precedence: 5,\n f: numeric_greater_than,\n ),\n\n new Operator(\n spelling: "\u2264",\n kind: "LE_SIGN",\n precedence: 5,\n f: numeric_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "<=",\n kind: "LE",\n precedence: 5,\n f: numeric_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "\u2265",\n kind: "GE_SIGN",\n precedence: 5,\n f: numeric_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: ">=",\n kind: "GE",\n precedence: 5,\n f: numeric_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: "\u2276",\n kind: "CMP_SIGN",\n precedence: 5,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "<=>",\n kind: "CMP",\n precedence: 5,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "\u2277",\n kind: "CMP_REV_SIGN",\n precedence: 5,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "_",\n kind: "CONCAT",\n require_ws: true,\n precedence: 10,\n f: string_concatenation,\n ),\n\n new Operator(\n spelling: "eq",\n kind: "STR_EQ",\n precedence: 5,\n f: string_equality,\n ),\n\n new Operator(\n spelling: "ne",\n kind: "STR_NE",\n precedence: 5,\n f: string_inequality,\n ),\n\n new Operator(\n spelling: "gt",\n kind: "STR_GT",\n precedence: 5,\n f: string_greater_than,\n ),\n\n new Operator(\n spelling: "ge",\n kind: "STR_GE",\n precedence: 5,\n f: string_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: "lt",\n kind: "STR_LT",\n precedence: 5,\n f: string_less_than,\n ),\n\n new Operator(\n spelling: "le",\n kind: "STR_LE",\n precedence: 5,\n f: string_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "cmp",\n kind: "STR_CMP",\n precedence: 5,\n f: string_compare,\n ),\n\n new Operator(\n spelling: "eqi",\n kind: "STR_EQI",\n precedence: 5,\n f: string_equality_insensitive,\n ),\n\n new Operator(\n spelling: "nei",\n kind: "STR_NEI",\n precedence: 5,\n f: string_inequality_insensitive,\n ),\n\n new Operator(\n spelling: "gti",\n kind: "STR_GTI",\n precedence: 5,\n f: string_greater_than_insensitive,\n ),\n\n new Operator(\n spelling: "gei",\n kind: "STR_GEI",\n precedence: 5,\n f: string_greater_than_or_equal_insensitive,\n ),\n\n new Operator(\n spelling: "lti",\n kind: "STR_LTI",\n precedence: 5,\n f: string_less_than_insensitive,\n ),\n\n new Operator(\n spelling: "lei",\n kind: "STR_LEI",\n precedence: 5,\n f: string_less_than_or_equal_insensitive,\n ),\n\n new Operator(\n spelling: "cmpi",\n kind: "STR_CMPI",\n precedence: 5,\n f: string_compare_insensitive,\n ),\n\n new Operator(\n spelling: "~",\n kind: "REGEXP_MATCH",\n precedence: 5,\n f: regexp_match,\n ),\n\n new Operator(\n spelling: "&",\n kind: "BAND",\n precedence: 8,\n f: bitwise_and,\n ),\n\n new Operator(\n spelling: "^",\n kind: "BXOR",\n precedence: 7,\n f: bitwise_xor,\n ),\n\n new Operator(\n spelling: "|",\n kind: "BOR",\n precedence: 6,\n f: bitwise_or,\n ),\n\n new Operator(\n spelling: "\u22C0",\n kind: "LAND_SIGN",\n precedence: 3,\n f: logical_and,\n ),\n\n new Operator(\n spelling: "and",\n kind: "LAND",\n precedence: 3,\n f: logical_and,\n ),\n\n new Operator(\n spelling: "\u22BC",\n kind: "LNAND_SIGN",\n precedence: 3,\n f: logical_nand,\n ),\n\n new Operator(\n spelling: "nand",\n kind: "LNAND",\n precedence: 3,\n f: logical_nand,\n ),\n\n new Operator(\n spelling: "\u22BB",\n kind: "LXOR_SIGN",\n precedence: 2,\n f: logical_xor,\n ),\n\n new Operator(\n spelling: "xor",\n kind: "LXOR",\n precedence: 2,\n f: logical_xor,\n ),\n\n new Operator(\n spelling: "\u22C1",\n kind: "LOR_SIGN",\n precedence: 1,\n f: logical_or,\n ),\n\n new Operator(\n spelling: "or",\n kind: "LOR",\n precedence: 1,\n f: logical_or,\n ),\n\n new Operator(\n spelling: "\u22C3",\n kind: "SET_UNION_SIGN",\n precedence: 9,\n f: set_union,\n ),\n\n new Operator(\n spelling: "union",\n kind: "SET_UNION",\n precedence: 9,\n f: set_union,\n ),\n\n new Operator(\n spelling: "\u22C2",\n kind: "SET_INTERSECTION_SIGN",\n precedence: 9,\n f: set_intersection,\n ),\n\n new Operator(\n spelling: "intersection",\n kind: "SET_INTERSECTION",\n precedence: 9,\n f: set_intersection,\n ),\n\n new Operator(\n spelling: "\u2216",\n kind: "SET_DIFFERENCE_SIGN",\n precedence: 9,\n f: set_difference,\n ),\n\n new Operator(\n spelling: "\\\\",\n kind: "SET_DIFFERENCE",\n precedence: 9,\n require_ws: true,\n f: set_difference,\n ),\n\n new Operator(\n spelling: "\u2208",\n kind: "MEMBER_SIGN",\n precedence: 5,\n f: collection_membership,\n ),\n\n new Operator(\n spelling: "in",\n kind: "MEMBER",\n precedence: 5,\n f: collection_membership,\n ),\n\n new Operator(\n spelling: "\u2209",\n kind: "NOT_MEMBER_SIGN",\n precedence: 5,\n f: collection_non_membership,\n ),\n\n new Operator(\n spelling: "\u2282",\n kind: "SUBSETOF_SIGN",\n precedence: 5,\n f: set_subsetof,\n ),\n\n new Operator(\n spelling: "subsetof",\n kind: "SUBSETOF",\n precedence: 5,\n f: set_subsetof,\n ),\n\n new Operator(\n spelling: "\u2283",\n kind: "SUPERSETOF_SIGN",\n precedence: 5,\n f: set_supersetof,\n ),\n\n new Operator(\n spelling: "supersetof",\n kind: "SUPERSETOF",\n precedence: 5,\n f: set_supersetof,\n ),\n\n new Operator(\n spelling: "\u2282\u2283",\n kind: "EQUIVALENTOF_SIGN",\n precedence: 5,\n f: set_equivalentof,\n ),\n\n new Operator(\n spelling: "equivalentof",\n kind: "EQUIVALENTOF",\n precedence: 5,\n f: set_equivalentof,\n ),\n\n new Operator(\n spelling: "\u2261",\n kind: "TYPE_EQ_SIGN",\n precedence: 4,\n f: type_aware_equality,\n ),\n\n new Operator(\n spelling: "==",\n kind: "TYPE_EQ",\n precedence: 4,\n f: type_aware_equality,\n ),\n\n new Operator(\n spelling: "\u2262",\n kind: "TYPE_NE_SIGN",\n precedence: 4,\n f: type_aware_inequality,\n ),\n\n new Operator(\n spelling: "!=",\n kind: "TYPE_NE",\n precedence: 4,\n f: type_aware_inequality,\n ),\n\n new Operator(\n spelling: "can",\n kind: "CAN",\n precedence: 5,\n f: object_can,\n ),\n\n new Operator(\n spelling: "~",\n kind: "BNOT",\n unary: true,\n precedence: 20,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( ~value );\n },\n ),\n];\n';
|
|
47345
|
+
virtualFiles["/modules/std/path/zz/operators.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/path/zz/operators - Operator definitions for ZZPath expressions.\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by all implementations of ZuzuScript.\n\n=head1 DESCRIPTION\n\nThis module extends the base ZPath operator model with\nZuzuScript-flavoured expression operators.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<Operator>\n\nZZPath operator class extending C<std/path/z/operators> C<Operator>.\n\n=back\n\n=head2 Functions\n\n=over\n\n=item C<< string_operand(ev, ctx, expr) >>, C<< string_operands(ev, ctx, left, right) >>\n\nParameters: evaluator, context, and expression AST nodes. Returns:\nC<String> or C<Array>. Evaluates one or two operands as strings.\n\n=item C<< first_eval_value(values) >>, C<< primitive_eval_value(values) >>\n\nParameters: C<values> is an evaluated node array. Returns: value.\nExtracts the first or primitive value used by ZZPath operators.\n\n=item C<< collection_operand(ev, ctx, expr) >>\n\nParameters: evaluator, context, and expression AST node. Returns:\ncollection value. Evaluates an operand for collection operators.\n\n=item C<< builtin_can(value, method_name) >>\n\nParameters: C<value> is any value and C<method_name> is a method name.\nReturns: C<Boolean>. Tests whether built-in values support a method.\n\n=back\n\n=head2 Constants\n\n=over\n\n=item C<STANDARD_OPERATORS>\n\nType: C<Array>. Complete ZZPath operator definition table.\n\n=item C<logical_negation>, C<logical_and>, C<logical_nand>, C<logical_butnot>, C<logical_xor>, C<logical_nor>, C<logical_xnor>, C<logical_onlyif>, C<logical_or>, C<logical_and_value>, C<logical_nand_value>, C<logical_butnot_value>, C<logical_xor_value>, C<logical_nor_value>, C<logical_xnor_value>, C<logical_onlyif_value>, C<logical_or_value>\n\nType: C<Function>. Logical operator implementations.\n\n=item C<numeric_power>, C<numeric_multiplication>, C<numeric_division>, C<numeric_modulus>, C<numeric_addition>, C<numeric_subtraction>, C<numeric_left_shift>, C<numeric_right_shift>, C<numeric_equality>, C<numeric_inequality>, C<numeric_less_than>, C<numeric_greater_than>, C<numeric_less_than_or_equal>, C<numeric_greater_than_or_equal>, C<numeric_compare>, C<numeric_divides>, C<numeric_not_divides>\n\nType: C<Function>. Numeric operator implementations.\n\n=item C<string_concatenation>, C<string_equality>, C<string_inequality>, C<string_greater_than>, C<string_greater_than_or_equal>, C<string_less_than>, C<string_less_than_or_equal>, C<string_compare>, C<string_equality_insensitive>, C<string_inequality_insensitive>, C<string_greater_than_insensitive>, C<string_greater_than_or_equal_insensitive>, C<string_less_than_insensitive>, C<string_less_than_or_equal_insensitive>, C<string_compare_insensitive>\n\nType: C<Function>. String operator implementations.\n\n=item C<regexp_match>, C<bitwise_and>, C<bitwise_xor>, C<bitwise_or>, C<set_union>, C<set_intersection>, C<set_difference>, C<collection_membership>, C<collection_non_membership>, C<set_subsetof>, C<set_supersetof>, C<set_equivalentof>, C<type_aware_equality>, C<type_aware_inequality>, C<object_can>\n\nType: C<Function>. Regular expression, bitwise, collection, type-aware,\nand object capability operator implementations.\n\n=back\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/path/zz/operators >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/path/z/operators import Operator as ZOperator;\n\n\nclass Operator extends ZOperator;\n\nconst logical_negation := function ( op, ev, ast, ctx, expr ) {\n const got := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n const value := got.length() > 0 ? got[0] : null;\n return op.wrap( not ev.truthy(value) );\n};\n\nconst numeric_power := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val ** right_val );\n};\n\nconst numeric_multiplication := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xD7 right_val );\n};\n\nconst numeric_division := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xF7 right_val );\n};\n\nconst numeric_modulus := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val mod right_val );\n};\n\nconst numeric_left_shift := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const first := left_vals.length() > 0 ? left_vals[0] : null;\n const left_val := first \u2261 null ? null : first.primitive_value();\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xAB right_val );\n};\n\nconst numeric_right_shift := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const first := left_vals.length() > 0 ? left_vals[0] : null;\n const left_val := first \u2261 null ? null : first.primitive_value();\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \xBB right_val );\n};\n\nconst numeric_addition := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val + right_val );\n};\n\nconst numeric_subtraction := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val - right_val );\n};\n\nconst numeric_equality := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val = right_val );\n};\n\nconst numeric_inequality := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2260 right_val );\n};\n\nconst numeric_less_than := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val < right_val );\n};\n\nconst numeric_greater_than := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val > right_val );\n};\n\nconst numeric_less_than_or_equal := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2264 right_val );\n};\n\nconst numeric_greater_than_or_equal := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val \u2265 right_val );\n};\n\nconst numeric_compare := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val <=> right_val );\n};\n\nconst numeric_divides := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( right_val mod left_val = 0 );\n};\n\nconst numeric_not_divides := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( right_val mod left_val );\n};\n\nfunction string_operand ( ev, ctx, expr ) {\n const result := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n return "" unless result.length;\n const value := ev.to_string( result[0] );\n return value \u2261 null ? "" : "" _ value;\n}\n\nfunction string_operands ( ev, ctx, left, right ) {\n return [\n string_operand( ev, ctx, left ),\n string_operand( ev, ctx, right ),\n ];\n}\n\nconst string_concatenation := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] _ values[1] );\n};\n\nconst string_equality := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] eq values[1] );\n};\n\nconst string_inequality := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ne values[1] );\n};\n\nconst string_greater_than := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] gt values[1] );\n};\n\nconst string_greater_than_or_equal := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ge values[1] );\n};\n\nconst string_less_than := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] lt values[1] );\n};\n\nconst string_less_than_or_equal := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] le values[1] );\n};\n\nconst string_compare := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] cmp values[1] );\n};\n\nconst string_equality_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val eq right_val );\n};\n\nconst string_inequality_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val ne right_val );\n};\n\nconst string_greater_than_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val gt right_val );\n};\n\nconst string_greater_than_or_equal_insensitive := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val ge right_val );\n};\n\nconst string_less_than_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val lt right_val );\n};\n\nconst string_less_than_or_equal_insensitive := function (\n op,\n ev,\n ast,\n ctx,\n left,\n right,\n) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val le right_val );\n};\n\nconst string_compare_insensitive := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n const left_val := lc values[0];\n const right_val := lc values[1];\n return op.wrap( left_val cmp right_val );\n};\n\nconst regexp_match := function ( op, ev, ast, ctx, left, right ) {\n const values := string_operands( ev, ctx, left, right );\n return op.wrap( values[0] ~ values[1] );\n};\n\nconst bitwise_and := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val & right_val );\n};\n\nconst bitwise_xor := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val ^ right_val );\n};\n\nconst bitwise_or := function ( op, ev, ast, ctx, left, right ) {\n const left_val := op._handle_numeric_operand( ev, ctx, left );\n const right_val := op._handle_numeric_operand( ev, ctx, right );\n return op.wrap( left_val | right_val );\n};\n\nfunction first_eval_value ( values ) {\n return values.length() > 0 ? values[0] : null;\n}\n\nfunction primitive_eval_value ( values ) {\n const first := first_eval_value(values);\n return first \u2261 null ? null : first.primitive_value();\n}\n\nfunction collection_operand ( ev, ctx, expr ) {\n const values := ev.eval_expr( expr, ev.nested_ctx( ctx ) );\n if ( values.length() = 1 ) {\n return values[0].primitive_value();\n }\n return values.map( fn value \u2192 value.primitive_value() );\n}\n\nconst logical_and := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return ev.eval_expr( right, ev.nested_ctx( ctx ) );\n }\n return op.wrap(false);\n};\n\nconst logical_nand := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( not ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? false : true );\n};\n\nconst logical_butnot := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( not ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(false);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? false : true );\n};\n\nconst logical_xor := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n return op.wrap( ( left_truth xor right_truth ) ? true : false );\n};\n\nconst logical_nor := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(false);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? false : true );\n};\n\nconst logical_xnor := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n return op.wrap( left_truth \u2261 right_truth );\n};\n\nconst logical_onlyif := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( not ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? true : false );\n};\n\nconst logical_or := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.truthy( first_eval_value(right_vals) ) ? true : false );\n};\n\nconst logical_and_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return ev.eval_expr( right, ev.nested_ctx( ctx ) );\n }\n return left_vals;\n};\n\nconst logical_nand_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n if ( left_truth and right_truth ) {\n return op.wrap(false);\n }\n return right_vals if not left_truth and right_truth;\n return op.wrap(true);\n};\n\nconst logical_butnot_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n return left_vals unless left_truth;\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return ev.truthy( first_eval_value(right_vals) )\n ? op.wrap(false)\n : left_vals;\n};\n\nconst logical_xor_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n if ( left_truth xor right_truth ) {\n return left_truth ? left_vals : right_vals;\n }\n return op.wrap(false);\n};\n\nconst logical_nor_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n return op.wrap(false) if left_truth and right_truth;\n return right_vals if left_truth and not right_truth;\n return left_vals if not left_truth and right_truth;\n return op.wrap(true);\n};\n\nconst logical_xnor_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_truth := ev.truthy( first_eval_value(left_vals) );\n const right_truth := ev.truthy( first_eval_value(right_vals) );\n if ( left_truth \u2261 right_truth ) {\n return left_truth ? right_vals : op.wrap(true);\n }\n return left_truth ? right_vals : left_vals;\n};\n\nconst logical_onlyif_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( not ev.truthy( first_eval_value(left_vals) ) ) {\n return op.wrap(true);\n }\n return ev.eval_expr( right, ev.nested_ctx( ctx ) );\n};\n\nconst logical_or_value := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n if ( ev.truthy( first_eval_value(left_vals) ) ) {\n return left_vals;\n }\n return ev.eval_expr( right, ev.nested_ctx( ctx ) );\n};\n\nconst set_union := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val union right_val );\n};\n\nconst set_intersection := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val intersection right_val );\n};\n\nconst set_difference := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val \u2216 right_val );\n};\n\nconst collection_membership := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val in right_val );\n};\n\nconst collection_non_membership := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val \u2209 right_val );\n};\n\nconst set_subsetof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val subsetof right_val );\n};\n\nconst set_supersetof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val supersetof right_val );\n};\n\nconst set_equivalentof := function ( op, ev, ast, ctx, left, right ) {\n const left_val := collection_operand( ev, ctx, left );\n const right_val := collection_operand( ev, ctx, right );\n return op.wrap( left_val equivalentof right_val );\n};\n\nconst type_aware_equality := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( ev.equals(\n first_eval_value(left_vals),\n first_eval_value(right_vals),\n ) );\n};\n\nconst type_aware_inequality := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n return op.wrap( not ev.equals(\n first_eval_value(left_vals),\n first_eval_value(right_vals),\n ) );\n};\n\nfunction builtin_can ( value, method_name ) {\n return false if value \u2261 null\n or method_name \u2261 null\n or method_name eq "";\n\n if ( value instanceof Array or value instanceof Bag or value instanceof Set ) {\n return method_name in [\n "length",\n "empty",\n "contains",\n "push",\n "to_Array",\n "to_Bag",\n "to_Set",\n ];\n }\n if ( value instanceof Dict or value instanceof PairList ) {\n return method_name in [\n "length",\n "empty",\n "exists",\n "keys",\n "values",\n "to_Array",\n ];\n }\n if ( value instanceof String or value instanceof BinaryString ) {\n return method_name in [ "length" ];\n }\n return false;\n}\n\nconst object_can := function ( op, ev, ast, ctx, left, right ) {\n const left_vals := ev.eval_expr( left, ev.nested_ctx( ctx ) );\n const right_vals := ev.eval_expr( right, ev.nested_ctx( ctx ) );\n const left_val := primitive_eval_value(left_vals);\n const right_val := primitive_eval_value(right_vals);\n return op.wrap(\n ( left_val can (right_val) ) or builtin_can( left_val, right_val )\n );\n};\n\nconst STANDARD_OPERATORS := [\n new Operator(\n spelling: "?:",\n kind: "ELVIS",\n precedence: 2,\n lex_ignore: true,\n ),\n\n new Operator(\n spelling: "+",\n kind: "UPLUS",\n unary: true,\n precedence: 40,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( +value );\n },\n ),\n\n new Operator(\n spelling: "-",\n kind: "UMINUS",\n unary: true,\n precedence: 40,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( -value );\n },\n ),\n\n new Operator(\n spelling: "\u221A",\n kind: "SQRT",\n unary: true,\n precedence: 40,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( sqrt value );\n },\n ),\n\n new Operator(\n spelling: "!",\n kind: "NOT",\n unary: true,\n precedence: 40,\n f: logical_negation,\n ),\n\n new Operator(\n spelling: "\xAC",\n kind: "NOTSYM",\n unary: true,\n precedence: 40,\n f: logical_negation,\n ),\n\n new Operator(\n spelling: "**",\n kind: "POW",\n require_ws: true,\n right_assoc: true,\n precedence: 26,\n f: numeric_power,\n ),\n\n new Operator(\n spelling: "\xD7",\n kind: "TIMES_SIGN",\n precedence: 24,\n f: numeric_multiplication,\n ),\n\n new Operator(\n spelling: "*",\n kind: "TIMES",\n require_ws: true,\n precedence: 24,\n lex_ignore: true,\n alias: "STAR",\n f: numeric_multiplication,\n ),\n\n new Operator(\n spelling: "\xF7",\n kind: "DIVIDE_SIGN",\n precedence: 24,\n f: numeric_division,\n ),\n\n new Operator(\n spelling: "/",\n kind: "DIVIDE",\n require_ws: true,\n precedence: 24,\n lex_ignore: true,\n alias: "SLASH",\n f: numeric_division,\n ),\n\n new Operator(\n spelling: "mod",\n kind: "MOD",\n precedence: 24,\n f: numeric_modulus,\n ),\n\n new Operator(\n spelling: "+",\n kind: "PLUS",\n require_ws: true,\n precedence: 22,\n f: numeric_addition,\n ),\n\n new Operator(\n spelling: "-",\n kind: "MINUS",\n require_ws: true,\n precedence: 22,\n f: numeric_subtraction,\n ),\n\n new Operator(\n spelling: "=",\n kind: "EQ",\n precedence: 10,\n f: numeric_equality,\n ),\n\n new Operator(\n spelling: "\u2260",\n kind: "NE",\n precedence: 10,\n f: numeric_inequality,\n ),\n\n new Operator(\n spelling: "<",\n kind: "LT",\n precedence: 10,\n f: numeric_less_than,\n ),\n\n new Operator(\n spelling: ">",\n kind: "GT",\n precedence: 10,\n f: numeric_greater_than,\n ),\n\n new Operator(\n spelling: "\u2264",\n kind: "LE_SIGN",\n precedence: 10,\n f: numeric_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "<=",\n kind: "LE",\n precedence: 10,\n f: numeric_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "\u2265",\n kind: "GE_SIGN",\n precedence: 10,\n f: numeric_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: ">=",\n kind: "GE",\n precedence: 10,\n f: numeric_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: "\u2276",\n kind: "CMP_SIGN",\n precedence: 10,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "<=>",\n kind: "CMP",\n precedence: 10,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "\u2277",\n kind: "CMP_REV_SIGN",\n precedence: 10,\n f: numeric_compare,\n ),\n\n new Operator(\n spelling: "\u2223",\n kind: "DIVIDES_SIGN",\n precedence: 10,\n f: numeric_divides,\n ),\n\n new Operator(\n spelling: "divides",\n kind: "DIVIDES",\n precedence: 10,\n f: numeric_divides,\n ),\n\n new Operator(\n spelling: "\u2224",\n kind: "NOT_DIVIDES_SIGN",\n precedence: 10,\n f: numeric_not_divides,\n ),\n\n new Operator(\n spelling: "_",\n kind: "CONCAT",\n require_ws: true,\n precedence: 21,\n f: string_concatenation,\n ),\n\n new Operator(\n spelling: "eq",\n kind: "STR_EQ",\n precedence: 10,\n f: string_equality,\n ),\n\n new Operator(\n spelling: "ne",\n kind: "STR_NE",\n precedence: 10,\n f: string_inequality,\n ),\n\n new Operator(\n spelling: "gt",\n kind: "STR_GT",\n precedence: 10,\n f: string_greater_than,\n ),\n\n new Operator(\n spelling: "ge",\n kind: "STR_GE",\n precedence: 10,\n f: string_greater_than_or_equal,\n ),\n\n new Operator(\n spelling: "lt",\n kind: "STR_LT",\n precedence: 10,\n f: string_less_than,\n ),\n\n new Operator(\n spelling: "le",\n kind: "STR_LE",\n precedence: 10,\n f: string_less_than_or_equal,\n ),\n\n new Operator(\n spelling: "cmp",\n kind: "STR_CMP",\n precedence: 10,\n f: string_compare,\n ),\n\n new Operator(\n spelling: "eqi",\n kind: "STR_EQI",\n precedence: 10,\n f: string_equality_insensitive,\n ),\n\n new Operator(\n spelling: "nei",\n kind: "STR_NEI",\n precedence: 10,\n f: string_inequality_insensitive,\n ),\n\n new Operator(\n spelling: "gti",\n kind: "STR_GTI",\n precedence: 10,\n f: string_greater_than_insensitive,\n ),\n\n new Operator(\n spelling: "gei",\n kind: "STR_GEI",\n precedence: 10,\n f: string_greater_than_or_equal_insensitive,\n ),\n\n new Operator(\n spelling: "lti",\n kind: "STR_LTI",\n precedence: 10,\n f: string_less_than_insensitive,\n ),\n\n new Operator(\n spelling: "lei",\n kind: "STR_LEI",\n precedence: 10,\n f: string_less_than_or_equal_insensitive,\n ),\n\n new Operator(\n spelling: "cmpi",\n kind: "STR_CMPI",\n precedence: 10,\n f: string_compare_insensitive,\n ),\n\n new Operator(\n spelling: "~",\n kind: "REGEXP_MATCH",\n precedence: 10,\n f: regexp_match,\n ),\n\n new Operator(\n spelling: "\xAB",\n kind: "LSHIFT_SIGN",\n precedence: 18,\n f: numeric_left_shift,\n ),\n\n new Operator(\n spelling: "<<",\n kind: "LSHIFT",\n precedence: 18,\n f: numeric_left_shift,\n ),\n\n new Operator(\n spelling: "\xBB",\n kind: "RSHIFT_SIGN",\n precedence: 18,\n f: numeric_right_shift,\n ),\n\n new Operator(\n spelling: ">>",\n kind: "RSHIFT",\n precedence: 18,\n f: numeric_right_shift,\n ),\n\n new Operator(\n spelling: "&",\n kind: "BAND",\n precedence: 16,\n f: bitwise_and,\n ),\n\n new Operator(\n spelling: "^",\n kind: "BXOR",\n precedence: 14,\n f: bitwise_xor,\n ),\n\n new Operator(\n spelling: "|",\n kind: "BOR",\n precedence: 12,\n f: bitwise_or,\n ),\n\n new Operator(\n spelling: "\u22C0",\n kind: "LAND_SIGN",\n precedence: 7,\n f: logical_and,\n ),\n\n new Operator(\n spelling: "and",\n kind: "LAND",\n precedence: 7,\n f: logical_and,\n ),\n\n new Operator(\n spelling: "\u22C0?",\n kind: "LAND_VALUE_SIGN",\n precedence: 7,\n f: logical_and_value,\n ),\n\n new Operator(\n spelling: "and?",\n kind: "LAND_VALUE",\n precedence: 7,\n f: logical_and_value,\n ),\n\n new Operator(\n spelling: "\u22BC",\n kind: "LNAND_SIGN",\n precedence: 7,\n f: logical_nand,\n ),\n\n new Operator(\n spelling: "nand",\n kind: "LNAND",\n precedence: 7,\n f: logical_nand,\n ),\n\n new Operator(\n spelling: "\u22BC?",\n kind: "LNAND_VALUE_SIGN",\n precedence: 7,\n f: logical_nand_value,\n ),\n\n new Operator(\n spelling: "nand?",\n kind: "LNAND_VALUE",\n precedence: 7,\n f: logical_nand_value,\n ),\n\n new Operator(\n spelling: "\u22AD",\n kind: "LBUTNOT_SIGN",\n precedence: 7,\n f: logical_butnot,\n ),\n\n new Operator(\n spelling: "butnot",\n kind: "LBUTNOT",\n precedence: 7,\n f: logical_butnot,\n ),\n\n new Operator(\n spelling: "\u22AD?",\n kind: "LBUTNOT_VALUE_SIGN",\n precedence: 7,\n f: logical_butnot_value,\n ),\n\n new Operator(\n spelling: "butnot?",\n kind: "LBUTNOT_VALUE",\n precedence: 7,\n f: logical_butnot_value,\n ),\n\n new Operator(\n spelling: "\u22BB",\n kind: "LXOR_SIGN",\n precedence: 5,\n f: logical_xor,\n ),\n\n new Operator(\n spelling: "xor",\n kind: "LXOR",\n precedence: 5,\n f: logical_xor,\n ),\n\n new Operator(\n spelling: "\u22BB?",\n kind: "LXOR_VALUE_SIGN",\n precedence: 5,\n f: logical_xor_value,\n ),\n\n new Operator(\n spelling: "xor?",\n kind: "LXOR_VALUE",\n precedence: 5,\n f: logical_xor_value,\n ),\n\n new Operator(\n spelling: "\u22BD",\n kind: "LNOR_SIGN",\n precedence: 5,\n f: logical_nor,\n ),\n\n new Operator(\n spelling: "nor",\n kind: "LNOR",\n precedence: 5,\n f: logical_nor,\n ),\n\n new Operator(\n spelling: "\u22BD?",\n kind: "LNOR_VALUE_SIGN",\n precedence: 5,\n f: logical_nor_value,\n ),\n\n new Operator(\n spelling: "nor?",\n kind: "LNOR_VALUE",\n precedence: 5,\n f: logical_nor_value,\n ),\n\n new Operator(\n spelling: "\u2194",\n kind: "LXNOR_SIGN",\n precedence: 5,\n f: logical_xnor,\n ),\n\n new Operator(\n spelling: "xnor",\n kind: "LXNOR",\n precedence: 5,\n f: logical_xnor,\n ),\n\n new Operator(\n spelling: "\u2194?",\n kind: "LXNOR_VALUE_SIGN",\n precedence: 5,\n f: logical_xnor_value,\n ),\n\n new Operator(\n spelling: "xnor?",\n kind: "LXNOR_VALUE",\n precedence: 5,\n f: logical_xnor_value,\n ),\n\n new Operator(\n spelling: "\u22A8",\n kind: "LONLYIF_SIGN",\n precedence: 4,\n right_assoc: true,\n f: logical_onlyif,\n ),\n\n new Operator(\n spelling: "onlyif",\n kind: "LONLYIF",\n precedence: 4,\n right_assoc: true,\n f: logical_onlyif,\n ),\n\n new Operator(\n spelling: "\u22A8?",\n kind: "LONLYIF_VALUE_SIGN",\n precedence: 4,\n right_assoc: true,\n f: logical_onlyif_value,\n ),\n\n new Operator(\n spelling: "onlyif?",\n kind: "LONLYIF_VALUE",\n precedence: 4,\n right_assoc: true,\n f: logical_onlyif_value,\n ),\n\n new Operator(\n spelling: "\u22C1",\n kind: "LOR_SIGN",\n precedence: 2,\n f: logical_or,\n ),\n\n new Operator(\n spelling: "or",\n kind: "LOR",\n precedence: 2,\n f: logical_or,\n ),\n\n new Operator(\n spelling: "\u22C1?",\n kind: "LOR_VALUE_SIGN",\n precedence: 2,\n f: logical_or_value,\n ),\n\n new Operator(\n spelling: "or?",\n kind: "LOR_VALUE",\n precedence: 2,\n f: logical_or_value,\n ),\n\n new Operator(\n spelling: "\u22C3",\n kind: "SET_UNION_SIGN",\n precedence: 20,\n f: set_union,\n ),\n\n new Operator(\n spelling: "union",\n kind: "SET_UNION",\n precedence: 20,\n f: set_union,\n ),\n\n new Operator(\n spelling: "\u22C2",\n kind: "SET_INTERSECTION_SIGN",\n precedence: 20,\n f: set_intersection,\n ),\n\n new Operator(\n spelling: "intersection",\n kind: "SET_INTERSECTION",\n precedence: 20,\n f: set_intersection,\n ),\n\n new Operator(\n spelling: "\u2216",\n kind: "SET_DIFFERENCE_SIGN",\n precedence: 20,\n f: set_difference,\n ),\n\n new Operator(\n spelling: "\\\\",\n kind: "SET_DIFFERENCE",\n precedence: 20,\n require_ws: true,\n f: set_difference,\n ),\n\n new Operator(\n spelling: "\u2208",\n kind: "MEMBER_SIGN",\n precedence: 10,\n f: collection_membership,\n ),\n\n new Operator(\n spelling: "in",\n kind: "MEMBER",\n precedence: 10,\n f: collection_membership,\n ),\n\n new Operator(\n spelling: "\u2209",\n kind: "NOT_MEMBER_SIGN",\n precedence: 10,\n f: collection_non_membership,\n ),\n\n new Operator(\n spelling: "\u2282",\n kind: "SUBSETOF_SIGN",\n precedence: 10,\n f: set_subsetof,\n ),\n\n new Operator(\n spelling: "subsetof",\n kind: "SUBSETOF",\n precedence: 10,\n f: set_subsetof,\n ),\n\n new Operator(\n spelling: "\u2283",\n kind: "SUPERSETOF_SIGN",\n precedence: 10,\n f: set_supersetof,\n ),\n\n new Operator(\n spelling: "supersetof",\n kind: "SUPERSETOF",\n precedence: 10,\n f: set_supersetof,\n ),\n\n new Operator(\n spelling: "\u2282\u2283",\n kind: "EQUIVALENTOF_SIGN",\n precedence: 10,\n f: set_equivalentof,\n ),\n\n new Operator(\n spelling: "equivalentof",\n kind: "EQUIVALENTOF",\n precedence: 10,\n f: set_equivalentof,\n ),\n\n new Operator(\n spelling: "\u2261",\n kind: "TYPE_EQ_SIGN",\n precedence: 8,\n f: type_aware_equality,\n ),\n\n new Operator(\n spelling: "==",\n kind: "TYPE_EQ",\n precedence: 8,\n f: type_aware_equality,\n ),\n\n new Operator(\n spelling: "\u2262",\n kind: "TYPE_NE_SIGN",\n precedence: 8,\n f: type_aware_inequality,\n ),\n\n new Operator(\n spelling: "!=",\n kind: "TYPE_NE",\n precedence: 8,\n f: type_aware_inequality,\n ),\n\n new Operator(\n spelling: "can",\n kind: "CAN",\n precedence: 10,\n f: object_can,\n ),\n\n new Operator(\n spelling: "~",\n kind: "BNOT",\n unary: true,\n precedence: 40,\n f: function ( op, ev, ast, ctx, expr ) {\n const value := op._handle_numeric_operand( ev, ctx, expr );\n return op.wrap( ~value );\n },\n ),\n];\n';
|
|
45427
47346
|
virtualFiles["/modules/std/template/z.zzm"] = '=encoding utf8\n\n=head1 NAME\n\nstd/template/z - Pure ZuzuScript template engine.\n\n=head1 SYNOPSIS\n\n from std/template/z import ZTemplate;\n\n let inline := new ZTemplate(\n string: "Hello {{ user/name }}!",\n );\n say( inline.process( { user: { name: "Ada" } } ) );\n\n let file_tmpl := new ZTemplate(\n file: "templates/page.zt",\n escape: "html",\n );\n say( file_tmpl.process( data ) );\n\n=head1 IMPLEMENTATION SUPPORT\n\nThis module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Node and\nElectron. It is partially supported by zuzu-js in the browser: complex,\nHTTP/JSON/ZPath pipeline, self-contained, and trait-object rendering\ncoverage passes, but filesystem-backed template loading and database row\nrendering coverage are unsupported.\n\n=head1 DESCRIPTION\n\nC<std/template/z> is a pure ZuzuScript template renderer.\n\nThe module compiles template text into a cached parse tree and renders\nit against data using C<std/path/z> expressions.\n\n=head1 EXPORTS\n\n=head2 Classes\n\n=over\n\n=item C<< ZTemplate({ string?: String, file?, escape?: String, includes?: Boolean }) >>\n\nConstructs a template from inline text or a file path. Returns:\nC<ZTemplate>.\n\n=over\n\n=item C<< template.process(data) >>\n\nParameters: C<data> is the model used for path lookups. Returns:\nC<String>. Renders the template.\n\n=back\n\n=back\n\n=head1 TAG FORMS\n\n=over 4\n\n=item * C<{{ expr }}>\n\nRender expression output using template default escaping.\n\n=item * C<{{ expr :: raw }}>, C<{{ expr :: html }}>\n\nRender expression output using per-tag escape override.\n\n=item * C<{{# expr }}> ... C<{{/expr}}>\n\nBlock form. Each truthy match renders child nodes.\n\n=item * C<{{> include.zt }}>\n\nInclude another template file. Relative include paths resolve from the\ncurrent template\'s file directory.\n\n=back\n\n=head1 ESCAPING\n\nDefault escape mode is C<html>. Supported escape modes are C<html> and\nC<raw>.\n\nC<html> escapes C<&>, C<< < >>, C<E<gt>>, double quotes, and single\nquotes.\n\n=head1 INCLUDE RULES\n\n=over 4\n\n=item * Include processing is enabled by default.\n\n=item * Pass C<includes: false> to disable include tags.\n\n=item * Relative includes require a file-backed template source.\n\n=item * Circular include chains throw a deterministic error.\n\n=back\n\n=head1 KNOWN DIFFERENCES\n\nThis module is implemented on top of C<std/path/z>. Parser/rendering\ndeltas across runtimes are covered in ztests and should be treated as\nimplementation bugs unless explicitly documented.\n\n=head1 COPYRIGHT AND LICENCE\n\nB<< std/template/z >> is copyright Toby Inkster.\n\nIt is free software; you may redistribute it and/or modify it under\nthe terms of either the Artistic License 1.0 or the GNU General Public\nLicense version 2.\n\n=cut\n\nfrom std/string import index, substr, trim;\nfrom std/path/z import ZPath;\n\nclass ZTemplate {\n let string;\n let file;\n let String escape := "html";\n let includes := true;\n let source_file := null;\n let Array tree := [];\n let compiled_paths := {};\n\n method __build__ () {\n let has_string := string \u2262 null;\n let has_file := file \u2262 null;\n\n if ( has_string and has_file ) {\n die "Specify only one of \\"string\\" or \\"file\\"";\n }\n if ( not has_string and not has_file ) {\n die "Missing template source: provide \\"string\\" or \\"file\\"";\n }\n\n escape := lc( "" _ escape );\n if ( escape \u2262 "html" and escape \u2262 "raw" ) {\n die `Invalid escape mode "${escape}"`;\n }\n\n if ( has_file ) {\n let loaded := self._read_template_file(file);\n string := loaded{text};\n source_file := loaded{file};\n }\n\n tree := self._parse_template(\n template: string \u2261 null ? "": string,\n current_file: source_file,\n seen_files: {},\n includes: includes,\n );\n }\n\n method process ( data ) {\n die "process() requires a data model" if data \u2261 null;\n\n return self._render_nodes(\n nodes: tree,\n context: data,\n eval_meta: {},\n default_escape: escape,\n );\n }\n\n method _parse_template ( ... PairList args ) {\n let template := args.get( "template", "" );\n let current_file := args.get( "current_file", null );\n let seen_files := args.get( "seen_files", {} );\n let includes_enabled := args.get( "includes", true );\n let root := [];\n\n let stack := [\n {\n expr: null,\n nodes: root,\n },\n ];\n\n let pos := 0;\n while ( true ) {\n let tag_open := index( template, "{{", pos );\n last if tag_open < 0;\n\n let text := substr( template, pos, tag_open - pos );\n self._push_text( stack[ stack.length() - 1 ]{nodes}, text );\n\n let tag_close := index( template, "}}", tag_open + 2 );\n if ( tag_close < 0 ) {\n die `Unterminated tag at character ${tag_open}`;\n }\n\n let raw := substr( template, tag_open + 2, tag_close - tag_open - 2 );\n let tagged := trim(raw);\n\n if ( substr( tagged, 0, 1 ) \u2261 "#" ) {\n let inner := trim( substr( tagged, 1 ) );\n let parsed := self._parse_expression_spec(inner);\n let block := {\n type: "block",\n expr_src: parsed{expr},\n nodes: [],\n };\n stack[ stack.length() - 1 ]{nodes}.push(block);\n stack.push( {\n expr: parsed{expr},\n nodes: block{nodes},\n } );\n }\n else if ( substr( tagged, 0, 1 ) \u2261 "/" ) {\n let inner := trim( substr( tagged, 1 ) );\n let current := stack.pop();\n if ( current \u2261 null or current{expr} \u2261 null ) {\n die `Mismatched close tag {{/${inner}}}`;\n }\n if ( inner \u2262 "" ) {\n let parsed := self._parse_expression_spec(inner);\n if ( current{expr} \u2262 parsed{expr} ) {\n die `Mismatched close tag {{/${inner}}} for {{${current{expr}}}}`;\n }\n }\n }\n else if ( tagged \u2262 "" ) {\n if ( substr( tagged, 0, 1 ) \u2261 ">" ) {\n die "Template includes are disabled"\n if not includes_enabled;\n\n let include_path := trim( substr( tagged, 1 ) );\n die "Empty include path in template tag"\n if include_path \u2261 "";\n\n let resolved := self._resolve_include_path(\n include_path: include_path,\n current_file: current_file,\n );\n\n let key := self._canonical_path(resolved);\n if ( seen_files.exists(key) and seen_files.get(key) ) {\n die `Circular include detected for "${resolved}"`;\n }\n\n seen_files.set( key, true );\n let loaded := self._read_template_file(resolved);\n let include_nodes := self._parse_template(\n template: loaded{text},\n current_file: loaded{file},\n seen_files: seen_files,\n includes: includes_enabled,\n );\n seen_files.remove(key);\n\n for ( let node in include_nodes ) {\n stack[ stack.length() - 1 ]{nodes}.push(node);\n }\n }\n else {\n let parsed := self._parse_expression_spec(tagged);\n stack[ stack.length() - 1 ]{nodes}.push( {\n type: "expr",\n expr_src: parsed{expr},\n escape: parsed{escape},\n } );\n }\n }\n\n pos := tag_close + 2;\n }\n\n let tail := substr( template, pos );\n self._push_text( stack[ stack.length() - 1 ]{nodes}, tail );\n\n if ( stack.length() > 1 ) {\n let missing := stack[ stack.length() - 1 ]{expr};\n die `Missing close tag for {{${missing}}}`;\n }\n\n return root;\n }\n\n method _push_text ( nodes, text ) {\n if ( text \u2262 "" ) {\n nodes.push( {\n type: "text",\n text: text,\n } );\n }\n }\n\n method _read_template_file ( raw_file ) {\n let path_obj := self._to_path(raw_file);\n let text := path_obj.slurp_utf8();\n let canonical := self._canonical_path(path_obj);\n\n return {\n text: text,\n file: canonical,\n };\n }\n\n method _to_path ( raw_file ) {\n from std/io import Path;\n if ( raw_file instanceof Path ) {\n return raw_file;\n }\n return new Path( "" _ raw_file );\n }\n\n method _canonical_path ( path_obj ) {\n let obj := self._to_path(path_obj);\n let canonical := obj.realpath();\n if ( canonical \u2261 null ) {\n canonical := obj.absolute();\n }\n if ( canonical \u2261 null ) {\n return obj.to_String;\n }\n from std/io import Path;\n if ( canonical instanceof Path ) {\n return canonical.to_String;\n }\n return "" _ canonical;\n }\n\n method _resolve_include_path ( ... PairList args ) {\n let include_path := args.get( "include_path" );\n let current_file := args.get( "current_file" );\n\n let include_obj := self._to_path(include_path);\n if ( include_obj.is_absolute() ) {\n return include_obj.to_String;\n }\n\n if ( current_file \u2261 null ) {\n die `Relative include path "${include_path}" requires file-based template source`;\n }\n\n let base := self._to_path(current_file).parent();\n return base.child( include_obj.to_String ).to_String;\n }\n\n method _parse_expression_spec ( raw ) {\n let expr := raw;\n let escape_mode := null;\n\n let split := self._find_escape_separator(raw);\n if ( split \u2262 null ) {\n let lhs := split[0];\n let rhs := split[1];\n if ( rhs \u2261 "html" or rhs \u2261 "raw" ) {\n expr := lhs;\n escape_mode := rhs;\n }\n }\n\n expr := trim(expr);\n if ( expr \u2261 "" ) {\n die "Empty expression in template tag";\n }\n\n return {\n expr: expr,\n escape: escape_mode,\n };\n }\n\n method _find_escape_separator ( text ) {\n let quote := "";\n let i := 0;\n while ( i < length text ) {\n let ch := substr( text, i, 1 );\n if ( quote \u2262 "" ) {\n if ( ch \u2261 "\\\\" ) {\n i += 2;\n next;\n }\n if ( ch \u2261 quote ) {\n quote := "";\n }\n i++;\n next;\n }\n\n if ( ch \u2261 "\\"" or ch \u2261 "\'" ) {\n quote := ch;\n i++;\n next;\n }\n\n if ( ch \u2261 ":" and substr( text, i, 2 ) \u2261 "::" ) {\n let lhs := trim( substr( text, 0, i ) );\n let rhs := lc( trim( substr( text, i + 2 ) ) );\n return [ lhs, rhs ];\n }\n\n i++;\n }\n\n return null;\n }\n\n method _render_nodes ( ... PairList args ) {\n let nodes := args.get( "nodes", [] );\n let context := args.get( "context", null );\n let eval_meta := args.get( "eval_meta", {} );\n let default_escape := args.get( "default_escape", "html" );\n let out := "";\n\n for ( let node in nodes ) {\n if ( node{type} \u2261 "text" ) {\n out _= node{text};\n }\n else if ( node{type} \u2261 "expr" ) {\n let results := self._evaluate_expression(\n expr_src: node{expr_src},\n context: context,\n eval_meta: eval_meta,\n );\n let value := "";\n for ( let matched in results ) {\n let sv := matched.string_value();\n value _= sv \u2261 null ? "" : sv;\n }\n\n let escape_mode := node{escape};\n if ( escape_mode \u2261 null ) {\n escape_mode := default_escape;\n }\n\n if ( escape_mode \u2261 "html" ) {\n out _= self._escape_html(value);\n }\n else {\n out _= value;\n }\n }\n else if ( node{type} \u2261 "block" ) {\n let results := self._evaluate_expression(\n expr_src: node{expr_src},\n context: context,\n eval_meta: eval_meta,\n );\n for ( let matched in results ) {\n let primitive := matched.primitive_value();\n next if not self._truthy(primitive);\n\n let inner_context := context;\n let inner_meta := eval_meta;\n if ( self._node_has_identity(matched) ) {\n inner_context := matched;\n inner_meta := { parentset: results };\n }\n\n out _= self._render_nodes(\n nodes: node{nodes},\n context: inner_context,\n eval_meta: inner_meta,\n default_escape: default_escape,\n );\n }\n }\n }\n\n return out;\n }\n\n method _evaluate_expression ( ... PairList args ) {\n let expr_src := args.get( "expr_src" );\n let context := args.get( "context" );\n let eval_meta := args.get( "eval_meta", {} );\n if ( not compiled_paths.exists(expr_src) ) {\n compiled_paths.set(\n expr_src,\n self._compile_path(expr_src),\n );\n }\n let zpath := compiled_paths.get(expr_src);\n return zpath.evaluate( context, eval_meta );\n }\n\n method _compile_path ( expr_src ) {\n return new ZPath( path: expr_src );\n }\n\n method _node_has_identity ( node ) {\n let parent := node.parent();\n if ( parent \u2261 null ) {\n return false;\n }\n\n return true;\n }\n\n method _truthy ( value ) {\n return value ? true : false;\n }\n\n method _escape_html ( text ) {\n let out := "";\n let i := 0;\n while ( i < length text ) {\n let ch := substr( text, i, 1 );\n if ( ch \u2261 "&" ) {\n out _= "&";\n }\n else if ( ch \u2261 "<" ) {\n out _= "<";\n }\n else if ( ch \u2261 ">" ) {\n out _= ">";\n }\n else if ( ch \u2261 "\\"" ) {\n out _= """;\n }\n else if ( ch \u2261 "\'" ) {\n out _= "'";\n }\n else {\n out _= ch;\n }\n i++;\n }\n return out;\n }\n}\n';
|
|
45428
47347
|
virtualFiles["/modules/std/template/zz.zzm"] = `=encoding utf8
|
|
45429
47348
|
|
|
@@ -45866,7 +47785,7 @@ class ZZTemplate extends ZTemplate {
|
|
|
45866
47785
|
}
|
|
45867
47786
|
});
|
|
45868
47787
|
|
|
45869
|
-
// ../../../../../tmp/zuzu-browser-build.
|
|
47788
|
+
// ../../../../../tmp/zuzu-browser-build.gMJDcc/browser-worker-entry.generated.js
|
|
45870
47789
|
var { createBrowserStdlib } = require_browser_stdlib_generated();
|
|
45871
47790
|
globalThis.__ZUZU_BROWSER_DEFAULT_RUNTIME_OPTIONS__ = createBrowserStdlib();
|
|
45872
47791
|
var { installBrowserWorker } = require_browser_worker_entry();
|