zuzu-js 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/zuzu-browser-worker.js +359 -94
  2. package/dist/zuzu-browser.js +363 -98
  3. package/lib/cli.js +1 -1
  4. package/lib/runtime-helpers.js +9 -7
  5. package/lib/runtime.js +133 -29
  6. package/lib/transpiler-new/codegen.js +57 -35
  7. package/lib/transpiler-new/lexer.js +2 -1
  8. package/lib/transpiler-new/parser.js +34 -11
  9. package/lib/transpiler-new/validate-bindings.js +16 -0
  10. package/modules/std/proc.js +29 -26
  11. package/modules/std/string.js +162 -14
  12. package/package.json +1 -1
  13. package/stdlib/modules/javascript.zzm +4 -4
  14. package/stdlib/modules/perl.zzm +4 -4
  15. package/stdlib/modules/std/archive.zzm +3 -3
  16. package/stdlib/modules/std/cache/lru.zzm +3 -3
  17. package/stdlib/modules/std/clib.zzm +2 -2
  18. package/stdlib/modules/std/colour.zzm +1 -1
  19. package/stdlib/modules/std/config.zzm +3 -3
  20. package/stdlib/modules/std/data/csv.zzm +4 -4
  21. package/stdlib/modules/std/data/ini.zzm +1 -1
  22. package/stdlib/modules/std/data/json/schema/core.zzm +2 -2
  23. package/stdlib/modules/std/data/json/schema/format.zzm +2 -2
  24. package/stdlib/modules/std/data/json/schema/model.zzm +2 -2
  25. package/stdlib/modules/std/data/json/schema/output.zzm +2 -2
  26. package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +2 -2
  27. package/stdlib/modules/std/data/json/schema/validation.zzm +3 -3
  28. package/stdlib/modules/std/data/json/schema.zzm +3 -3
  29. package/stdlib/modules/std/data/kdl/json.zzm +1 -1
  30. package/stdlib/modules/std/data/kdl/xml.zzm +1 -1
  31. package/stdlib/modules/std/data/kdl.zzm +6 -6
  32. package/stdlib/modules/std/data/toml.zzm +1 -1
  33. package/stdlib/modules/std/data/toon.zzm +1 -1
  34. package/stdlib/modules/std/data/xml/escape.zzm +1 -1
  35. package/stdlib/modules/std/data/xml.zzm +4 -4
  36. package/stdlib/modules/std/data/yaml.zzm +1 -1
  37. package/stdlib/modules/std/db.zzm +4 -4
  38. package/stdlib/modules/std/defer.zzm +1 -1
  39. package/stdlib/modules/std/digest/crc32.zzm +2 -2
  40. package/stdlib/modules/std/digest/md5.zzm +2 -2
  41. package/stdlib/modules/std/digest/sha.zzm +2 -2
  42. package/stdlib/modules/std/dump.zzm +1 -1
  43. package/stdlib/modules/std/eval.zzm +1 -1
  44. package/stdlib/modules/std/getopt.zzm +5 -5
  45. package/stdlib/modules/std/gui/dialogue.zzm +1 -1
  46. package/stdlib/modules/std/gui/objects.zzm +1 -1
  47. package/stdlib/modules/std/gui.zzm +1 -1
  48. package/stdlib/modules/std/internals.zzm +4 -4
  49. package/stdlib/modules/std/io/socks.zzm +2 -2
  50. package/stdlib/modules/std/io.zzm +2 -2
  51. package/stdlib/modules/std/lingua/en.zzm +3 -3
  52. package/stdlib/modules/std/log.zzm +2 -2
  53. package/stdlib/modules/std/marshal.zzm +3 -3
  54. package/stdlib/modules/std/math/bignum.zzm +2 -2
  55. package/stdlib/modules/std/math/range.zzm +1 -1
  56. package/stdlib/modules/std/math/roman.zzm +1 -1
  57. package/stdlib/modules/std/math.zzm +1 -1
  58. package/stdlib/modules/std/net/dns.zzm +1 -1
  59. package/stdlib/modules/std/net/http.zzm +3 -3
  60. package/stdlib/modules/std/net/smtp.zzm +3 -3
  61. package/stdlib/modules/std/net/url.zzm +3 -3
  62. package/stdlib/modules/std/path/jsonpointer.zzm +2 -2
  63. package/stdlib/modules/std/path/kdl.zzm +2 -2
  64. package/stdlib/modules/std/path/z.zzm +3 -3
  65. package/stdlib/modules/std/proc.zzm +4 -4
  66. package/stdlib/modules/std/result.zzm +2 -2
  67. package/stdlib/modules/std/secure.zzm +1 -1
  68. package/stdlib/modules/std/string/base64.zzm +3 -3
  69. package/stdlib/modules/std/string/encode.zzm +1 -1
  70. package/stdlib/modules/std/string/quoted_printable.zzm +3 -3
  71. package/stdlib/modules/std/string.zzm +168 -1
  72. package/stdlib/modules/std/task.zzm +1 -1
  73. package/stdlib/modules/std/template/z.zzm +2 -2
  74. package/stdlib/modules/std/template/zz.zzm +1 -1
  75. package/stdlib/modules/std/time.zzm +2 -2
  76. package/stdlib/modules/std/tui.zzm +1 -1
  77. package/stdlib/modules/std/uuid.zzm +1 -1
  78. package/stdlib/modules/std/web/static.zzm +1 -1
  79. package/stdlib/modules/std/worker.zzm +3 -3
  80. package/stdlib/modules/test/parser.zzm +26 -8
@@ -1271,15 +1271,17 @@
1271
1271
  function runSwitch(value, cmpName, cases, defaultBody) {
1272
1272
  const cmp = buildComparator(cmpName);
1273
1273
  let runNext = false;
1274
+ let matched = false;
1274
1275
  for (const section of cases) {
1275
- let matched = false;
1276
+ let sectionMatched = false;
1276
1277
  if (Array.isArray(section.tests)) {
1277
- matched = section.tests.some((test) => switchTruthy(test(value)));
1278
+ sectionMatched = section.tests.some((test) => switchTruthy(test(value)));
1278
1279
  } else {
1279
- matched = section.values.some((item) => cmp(value, item));
1280
+ sectionMatched = section.values.some((item) => cmp(value, item));
1280
1281
  }
1281
- if (matched || runNext) {
1282
- const result = section.body();
1282
+ if (sectionMatched || runNext) {
1283
+ matched = true;
1284
+ const result = section.body(value);
1283
1285
  runNext = result === true;
1284
1286
  if (!runNext && result && typeof result === "object" && result.__zuzu_return) {
1285
1287
  return result;
@@ -1289,8 +1291,8 @@
1289
1291
  }
1290
1292
  }
1291
1293
  }
1292
- if (defaultBody) {
1293
- const result = defaultBody();
1294
+ if (defaultBody && (!matched || runNext)) {
1295
+ const result = defaultBody(value);
1294
1296
  if (result && typeof result === "object" && result.__zuzu_return) {
1295
1297
  return result;
1296
1298
  }
@@ -1793,29 +1795,156 @@
1793
1795
  function replace(text, pattern, replacement, flags = "") {
1794
1796
  return toStringValue(text).replace(normalizePattern(pattern, flags), toStringValue(replacement));
1795
1797
  }
1798
+ function formatWidth(text, width, flags, zeroPad = false) {
1799
+ if (width == null) {
1800
+ return text;
1801
+ }
1802
+ const target = Number(width);
1803
+ const byteLength = new TextEncoder().encode(text).length;
1804
+ if (byteLength >= target) {
1805
+ return text;
1806
+ }
1807
+ const padChar = zeroPad && !flags.includes("-") ? "0" : " ";
1808
+ const fill = padChar.repeat(target - byteLength);
1809
+ if (flags.includes("-")) {
1810
+ return `${text}${fill}`;
1811
+ }
1812
+ if (padChar === "0" && /^[+-]/u.test(text)) {
1813
+ return `${text[0]}${fill}${text.slice(1)}`;
1814
+ }
1815
+ return `${fill}${text}`;
1816
+ }
1817
+ function formatInteger(value, radix, uppercase = false, signed = true) {
1818
+ const number = Number(value ?? 0);
1819
+ const integer = Math.trunc(number);
1820
+ const negative = integer < 0;
1821
+ const magnitude = signed ? Math.abs(integer) : integer >>> 0;
1822
+ let rendered = magnitude.toString(radix);
1823
+ if (uppercase) {
1824
+ rendered = rendered.toUpperCase();
1825
+ }
1826
+ return signed && negative ? `-${rendered}` : rendered;
1827
+ }
1828
+ function signPrefix(rendered, number, flags) {
1829
+ if (rendered.startsWith("-")) {
1830
+ return rendered;
1831
+ }
1832
+ if (number < 0) {
1833
+ return `-${rendered}`;
1834
+ }
1835
+ if (flags.includes("+")) {
1836
+ return `+${rendered}`;
1837
+ }
1838
+ if (flags.includes(" ")) {
1839
+ return ` ${rendered}`;
1840
+ }
1841
+ return rendered;
1842
+ }
1843
+ function normalizeExponent(rendered) {
1844
+ return rendered.replace(/([eE][+-])(\d)$/u, "$10$2");
1845
+ }
1846
+ function trimGeneralFloat(rendered) {
1847
+ return rendered.replace(/(\.\d*?)0+(e[+-]?\d+)$/iu, "$1$2").replace(/\.e/iu, "e").replace(/(\.\d*?)0+$/u, "$1").replace(/\.$/u, "");
1848
+ }
1849
+ function formatFloat(number, precision, kind) {
1850
+ const digits = precision == null ? 6 : Number(precision);
1851
+ if (kind === "f") {
1852
+ return number.toFixed(digits);
1853
+ }
1854
+ if (kind === "e") {
1855
+ return normalizeExponent(number.toExponential(digits));
1856
+ }
1857
+ if (kind === "E") {
1858
+ return normalizeExponent(number.toExponential(digits).toUpperCase());
1859
+ }
1860
+ const significant = precision == null ? 6 : Number(precision);
1861
+ const rendered = trimGeneralFloat(number.toPrecision(significant));
1862
+ return kind === "G" ? rendered.toUpperCase() : rendered;
1863
+ }
1796
1864
  function sprint(format, ...args) {
1797
1865
  let idx = 0;
1798
- return toStringValue(format).replace(/%([0-9]+)?(?:\.([0-9]+))?([sdfc])/gu, (_token, width, precision, kind) => {
1866
+ const source = toStringValue(format);
1867
+ return source.replace(/%([-+ 0#]*)([0-9]+)?(?:\.([0-9]+))?([sdiuoxXfeEgGc%])/gu, (token, rawFlags, width, precision, kind) => {
1868
+ if (kind === "%") {
1869
+ return "%";
1870
+ }
1799
1871
  const value = args[idx++];
1872
+ const flags = rawFlags || "";
1800
1873
  let out = "";
1801
- if (kind === "d") {
1802
- out = String(Math.trunc(Number(value ?? 0)));
1803
- } else if (kind === "f") {
1804
- const num = Number(value ?? 0);
1805
- out = precision != null ? num.toFixed(Number(precision)) : String(num);
1874
+ let zeroPad = false;
1875
+ if (kind === "s") {
1876
+ out = toStringValue(value);
1877
+ if (precision != null) {
1878
+ out = [...out].slice(0, Number(precision)).join("");
1879
+ }
1880
+ } else if (kind === "d" || kind === "i") {
1881
+ const number = Math.trunc(Number(value ?? 0));
1882
+ out = signPrefix(String(Math.abs(number)), number, flags);
1883
+ if (number < 0) {
1884
+ out = `-${Math.abs(number)}`;
1885
+ }
1886
+ zeroPad = flags.includes("0");
1887
+ } else if (kind === "u") {
1888
+ out = formatInteger(value, 10, false, false);
1889
+ zeroPad = flags.includes("0");
1890
+ } else if (kind === "x" || kind === "X") {
1891
+ out = formatInteger(value, 16, kind === "X", true);
1892
+ if (flags.includes("#") && !out.startsWith("-") && Number(value ?? 0) !== 0) {
1893
+ out = `${kind === "X" ? "0X" : "0x"}${out}`;
1894
+ }
1895
+ zeroPad = flags.includes("0");
1896
+ } else if (kind === "o") {
1897
+ out = formatInteger(value, 8, false, true);
1898
+ if (flags.includes("#") && !out.startsWith("-") && !out.startsWith("0")) {
1899
+ out = `0${out}`;
1900
+ }
1901
+ zeroPad = flags.includes("0");
1902
+ } else if (kind === "f" || kind === "e" || kind === "E" || kind === "g" || kind === "G") {
1903
+ const number = Number(value ?? 0);
1904
+ const negative = number < 0 || Object.is(number, -0);
1905
+ out = formatFloat(Math.abs(number), precision, kind);
1906
+ out = signPrefix(out, negative ? -1 : number, flags);
1907
+ zeroPad = flags.includes("0");
1806
1908
  } else if (kind === "c") {
1807
- out = String.fromCharCode(Number(value ?? 0));
1909
+ out = String.fromCodePoint(Number(value ?? 0));
1808
1910
  } else {
1809
- out = toStringValue(value);
1911
+ return token;
1810
1912
  }
1811
- if (width != null) {
1812
- const target = Number(width);
1813
- if (out.length < target) {
1814
- out = `${" ".repeat(target - out.length)}${out}`;
1913
+ return formatWidth(out, width, flags, zeroPad);
1914
+ });
1915
+ }
1916
+ function repeat(count, text, separator = null) {
1917
+ if (arguments.length < 2 || arguments.length > 3) {
1918
+ throw new Error("repeat() expects two or three arguments");
1919
+ }
1920
+ const repetitions = Math.floor(Number(count ?? 0));
1921
+ if (repetitions < 0) {
1922
+ throw new Error("repeat() count cannot be negative");
1923
+ }
1924
+ const textIsBinary = text instanceof BinaryString2;
1925
+ const separatorIsBinary = separator instanceof BinaryString2;
1926
+ if (separator != null && textIsBinary !== separatorIsBinary) {
1927
+ throw new Error("TypeException: repeat() cannot mix String and BinaryString values");
1928
+ }
1929
+ if (textIsBinary) {
1930
+ const source = text.bytes;
1931
+ const sep2 = separator == null ? new Uint8Array(0) : separator.bytes;
1932
+ const total = repetitions === 0 ? 0 : source.length * repetitions + sep2.length * (repetitions - 1);
1933
+ const out = new Uint8Array(total);
1934
+ let offset = 0;
1935
+ for (let i = 0; i < repetitions; i++) {
1936
+ if (i > 0) {
1937
+ out.set(sep2, offset);
1938
+ offset += sep2.length;
1815
1939
  }
1940
+ out.set(source, offset);
1941
+ offset += source.length;
1816
1942
  }
1817
- return out;
1818
- });
1943
+ return new BinaryString2(out);
1944
+ }
1945
+ const value = toStringValue(text);
1946
+ const sep = separator == null ? "" : toStringValue(separator);
1947
+ return Array.from({ length: repetitions }, () => value).join(sep);
1819
1948
  }
1820
1949
  function join(separator, values) {
1821
1950
  const sep = toStringValue(separator);
@@ -1908,6 +2037,7 @@
1908
2037
  pad,
1909
2038
  pattern_to_regexp,
1910
2039
  quotemeta,
2040
+ repeat,
1911
2041
  rindex,
1912
2042
  replace,
1913
2043
  search,
@@ -4987,6 +5117,7 @@
4987
5117
  "length",
4988
5118
  "uc",
4989
5119
  "lc",
5120
+ "print",
4990
5121
  "say",
4991
5122
  "class",
4992
5123
  "trait",
@@ -5754,7 +5885,7 @@
5754
5885
  addToken("punctuation", ch, start, cursor());
5755
5886
  continue;
5756
5887
  }
5757
- if (["+", "-", "*", "/", "%", "<", ">", "=", "_", "?", ":", "~", "!", "\\", "&", "|", "^", "@", "\xD7", "\xF7", "\xAC", "\u22C0", "\u22C1", "\u22BB", "\u22BC", "\u22BD", "\u2194", "\u22A8", "\u22AD"].includes(ch)) {
5888
+ if (["+", "-", "*", "/", "%", "<", ">", "=", "_", "?", ":", "~", "!", "#", "\\", "&", "|", "^", "@", "\xD7", "\xF7", "\xAC", "\u22C0", "\u22C1", "\u22BB", "\u22BC", "\u22BD", "\u2194", "\u22A8", "\u22AD"].includes(ch)) {
5758
5889
  advance();
5759
5890
  const value = maybeValuePreservingOperator(ch, peek, advance);
5760
5891
  addToken("operator", value, start, cursor());
@@ -5982,6 +6113,8 @@
5982
6113
  return parseDieStatement();
5983
6114
  case "warn":
5984
6115
  return parseWarnStatement();
6116
+ case "print":
6117
+ return parsePrintStatement();
5985
6118
  case "assert":
5986
6119
  return parseAssertStatement();
5987
6120
  case "debug":
@@ -6197,7 +6330,7 @@
6197
6330
  name: typed.name
6198
6331
  };
6199
6332
  }
6200
- if (current().type === "identifier" || current().type === "keyword") {
6333
+ if ((current().type === "identifier" || current().type === "keyword") && !(current().type === "keyword" && current().value === "but")) {
6201
6334
  const name2 = expectIdentifier("Expected unpacked binding name after type");
6202
6335
  return {
6203
6336
  key: bindingIdentifierKey(name2),
@@ -6946,6 +7079,28 @@
6946
7079
  }, start, previous());
6947
7080
  return finishStatement(stmt, "Expected ; after warn statement");
6948
7081
  }
7082
+ function parsePrintStatement() {
7083
+ const start = expect("keyword", "print");
7084
+ const args = [];
7085
+ if (!(current().type === "punctuation" && current().value === ";")) {
7086
+ args.push(parseExpression());
7087
+ while (match("punctuation", ",")) {
7088
+ args.push(parseExpression());
7089
+ }
7090
+ }
7091
+ const stmt = withLoc({
7092
+ type: "ExpressionStatement",
7093
+ expression: withLoc({
7094
+ type: "CallExpression",
7095
+ callee: withLoc({
7096
+ type: "Identifier",
7097
+ name: "print"
7098
+ }, start, start),
7099
+ arguments: args
7100
+ }, start, previous() || start)
7101
+ }, start, previous() || start);
7102
+ return finishStatement(stmt, "Expected ; after print statement");
7103
+ }
6949
7104
  function parseAssertStatement() {
6950
7105
  const start = expect("keyword", "assert");
6951
7106
  const argument = parseExpression();
@@ -7359,7 +7514,7 @@
7359
7514
  }, startLocFromNode(left), endLocFromNode(right));
7360
7515
  }
7361
7516
  function parseUnary() {
7362
- 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)) {
7517
+ 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)) {
7363
7518
  const op = current();
7364
7519
  index++;
7365
7520
  const argument = op.value === "\\" ? parseReferenceTarget() : parseUnary();
@@ -7481,10 +7636,7 @@
7481
7636
  const key = current();
7482
7637
  index++;
7483
7638
  property = withLoc(
7484
- key.type === "identifier" ? {
7485
- type: "BraceIdentifier",
7486
- name: key.value
7487
- } : {
7639
+ {
7488
7640
  type: "StringLiteral",
7489
7641
  value: key.value
7490
7642
  },
@@ -8687,15 +8839,7 @@ globalThis[${JSON.stringify(node.id.name)}] = ${name2};` : declaration;
8687
8839
  return emitSpecialFunctionPreamble(signature);
8688
8840
  }
8689
8841
  const lines = [];
8690
- const required = params.reduce((count, param) => {
8691
- if (param.type === "Parameter") {
8692
- return count + (!param.optional && param.defaultValue == null && !param.rest ? 1 : 0);
8693
- }
8694
- if (param.type === "SpecialParameter" && param.special === "lead_rest") {
8695
- return count + 1;
8696
- }
8697
- return count;
8698
- }, 0);
8842
+ const required = minimumAcceptedArgumentCount(params);
8699
8843
  lines.push("const __argc__ = arguments.length;");
8700
8844
  lines.push(`if ( arguments.length < ${required} ) { throw new Error( "Wrong number of arguments" ); }`);
8701
8845
  let argIndex = 0;
@@ -9242,7 +9386,7 @@ ${cleanup}
9242
9386
  const valueNames = entries.map(() => `__zuzu_unpack_value_${loopCounter++}`);
9243
9387
  for (let i = 0; i < entries.length; i++) {
9244
9388
  prelude.push(
9245
- `const ${valueNames[i]} = ${emitUnpackEntryValue(sourceName, entries[i])};`
9389
+ `const ${valueNames[i]} = ${emitUnpackEntryValue(sourceName, entries[i], i)};`
9246
9390
  );
9247
9391
  }
9248
9392
  if (node.init && expressionRetainsCollectionValues(node.init)) {
@@ -9266,7 +9410,7 @@ ${cleanup}
9266
9410
  const valueNames = entries.map(() => `__zuzu_unpack_value_${loopCounter++}`);
9267
9411
  for (let i = 0; i < entries.length; i++) {
9268
9412
  lines.push(
9269
- `const ${valueNames[i]} = ${emitUnpackEntryValue(sourceName, entries[i])};`
9413
+ `const ${valueNames[i]} = ${emitUnpackEntryValue(sourceName, entries[i], i)};`
9270
9414
  );
9271
9415
  }
9272
9416
  if (node.init && expressionRetainsCollectionValues(node.init)) {
@@ -9277,9 +9421,9 @@ ${cleanup}
9277
9421
  }
9278
9422
  return lines.join("\n");
9279
9423
  }
9280
- function emitUnpackEntryValue(sourceName, entry) {
9424
+ function emitUnpackEntryValue(sourceName, entry, index) {
9281
9425
  const defaultThunk = entry.defaultValue ? `() => ${emitExpression(entry.defaultValue)}` : "null";
9282
- return `__zuzu_unpack_value( ${sourceName}, ${emitExpression(entry.key)}, ${defaultThunk}, ${JSON.stringify(entry.name)}, ${entry.declaredType ? JSON.stringify(entry.declaredType) : "null"}, ${entry.isWeakStorage ? "true" : "false"} )`;
9426
+ return `__zuzu_unpack_value( ${sourceName}, () => ${emitExpression(entry.key)}, ${defaultThunk}, ${JSON.stringify(entry.name)}, ${entry.declaredType ? JSON.stringify(entry.declaredType) : "null"}, ${entry.isWeakStorage ? "true" : "false"}, ${index} )`;
9283
9427
  }
9284
9428
  function emitBlockStatement(node, cleanupNames, options = {}) {
9285
9429
  if (node.type === "VariableDeclaration" && node.id && cleanupNames.includes(node.id.name)) {
@@ -9291,30 +9435,25 @@ ${cleanup}
9291
9435
  return emitStatement(node, options);
9292
9436
  }
9293
9437
  function emitSwitchStatement(node, options = {}) {
9438
+ const switchHereName = "__zuzu_switch_value";
9439
+ const emitSwitchTest = (section, index) => withEmitContext({
9440
+ ...currentEmitContext(),
9441
+ chainHereName: switchHereName
9442
+ }, () => emitSwitchTestExpression(section, index, node.comparator));
9443
+ const emitSwitchBody = (block) => emitBlock(block, {
9444
+ ...options,
9445
+ chainHereName: switchHereName,
9446
+ inSwitchSection: true,
9447
+ loopDepth: 0
9448
+ });
9294
9449
  if (options.asyncContext && !options.syncEval) {
9295
- 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, {
9296
- ...options,
9297
- inSwitchSection: true,
9298
- loopDepth: 0
9299
- })} }`);
9300
- const defaultBody2 = node.defaultCase ? `async function() ${emitBlock(node.defaultCase.consequent, {
9301
- ...options,
9302
- inSwitchSection: true,
9303
- loopDepth: 0
9304
- })}` : "null";
9450
+ const cases2 = node.cases.map((section) => `{ tests: [ ${section.values.map((value, index) => `async function( ${switchHereName} ) { return __zuzu_truthy( ${emitSwitchTest(section, index)} ); }`).join(", ")} ], body: async function( ${switchHereName} ) ${emitSwitchBody(section.consequent)} }`);
9451
+ const defaultBody2 = node.defaultCase ? `async function( ${switchHereName} ) ${emitSwitchBody(node.defaultCase.consequent)}` : "null";
9305
9452
  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; }" : "";
9306
9453
  return `{ let __zuzu_switch_result = await __zuzu_switch_async( ${emitExpression(node.discriminant)}, ${JSON.stringify(node.comparator)}, [ ${cases2.join(", ")} ], ${defaultBody2} ); ${tail2} }`;
9307
9454
  }
9308
- 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, {
9309
- ...options,
9310
- inSwitchSection: true,
9311
- loopDepth: 0
9312
- })} }`);
9313
- const defaultBody = node.defaultCase ? `function() ${emitBlock(node.defaultCase.consequent, {
9314
- ...options,
9315
- inSwitchSection: true,
9316
- loopDepth: 0
9317
- })}` : "null";
9455
+ const cases = node.cases.map((section) => `{ tests: [ ${section.values.map((value, index) => `function( ${switchHereName} ) { return __zuzu_truthy( ${emitSwitchTest(section, index)} ); }`).join(", ")} ], body: function( ${switchHereName} ) ${emitSwitchBody(section.consequent)} }`);
9456
+ const defaultBody = node.defaultCase ? `function( ${switchHereName} ) ${emitSwitchBody(node.defaultCase.consequent)}` : "null";
9318
9457
  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; }" : "";
9319
9458
  return `{ let __zuzu_switch_result = __zuzu_switch( ${emitExpression(node.discriminant)}, ${JSON.stringify(node.comparator)}, [ ${cases.join(", ")} ], ${defaultBody} ); ${tail} }`;
9320
9459
  }
@@ -9363,7 +9502,7 @@ ${cleanup}
9363
9502
  if (node.isPredeclared) {
9364
9503
  return `__zuzu_bodyless_function( ${JSON.stringify(node.id.name)} )`;
9365
9504
  }
9366
- return `( ${emitFunctionLike(node, `${node.isAsync ? "async " : ""}function()`, {
9505
+ const fn2 = emitFunctionLike(node, `${node.isAsync ? "async " : ""}function()`, {
9367
9506
  ...meta,
9368
9507
  asyncContext: node.isAsync === true,
9369
9508
  extraPreamble: [
@@ -9376,7 +9515,37 @@ ${cleanup}
9376
9515
  scopeNames: /* @__PURE__ */ new Set(["self", "__zuzu_super_class__", "__zuzu_super_method__", "__zuzu_super_static__"]),
9377
9516
  fieldNames: meta.fieldNames || [],
9378
9517
  methodSelfName: meta.methodSelfName || "self"
9379
- })} )`;
9518
+ });
9519
+ const min = minimumAcceptedArgumentCount(node.params);
9520
+ const max = maximumAcceptedArgumentCount(node.params);
9521
+ const maxLiteral = max == null ? "null" : max;
9522
+ return [
9523
+ "( () => {",
9524
+ `const __zuzu_method = ( ${fn2} );`,
9525
+ `Object.defineProperty( __zuzu_method, "__zuzu_min_args", { value: ${min} } );`,
9526
+ `Object.defineProperty( __zuzu_method, "__zuzu_max_args", { value: ${maxLiteral} } );`,
9527
+ "return __zuzu_method;",
9528
+ "} )()"
9529
+ ].join(" ");
9530
+ }
9531
+ function minimumAcceptedArgumentCount(params) {
9532
+ return params.reduce((count, param) => {
9533
+ if (param.type === "Parameter") {
9534
+ return count + (!param.optional && param.defaultValue == null && !param.rest ? 1 : 0);
9535
+ }
9536
+ if (param.type === "SpecialParameter" && param.special === "lead_rest") {
9537
+ return count + 1;
9538
+ }
9539
+ return count;
9540
+ }, 0);
9541
+ }
9542
+ function maximumAcceptedArgumentCount(params) {
9543
+ for (const param of params) {
9544
+ if (param.rest || param.type === "SpecialParameter") {
9545
+ return null;
9546
+ }
9547
+ }
9548
+ return params.length;
9380
9549
  }
9381
9550
  function emitClassDeclarationWithName(node, runtimeName, options = {}) {
9382
9551
  if (node.shorthand && node.traits.length === 0) {
@@ -9751,6 +9920,9 @@ ${cleanup}
9751
9920
  if (node.operator === "length") {
9752
9921
  return `__zuzu_length( ${emitExpression(node.argument)} )`;
9753
9922
  }
9923
+ if (node.operator === "#") {
9924
+ return `__zuzu_cardinality( ${emitExpression(node.argument)} )`;
9925
+ }
9754
9926
  if (node.operator === "uc") {
9755
9927
  return `__zuzu_uc( ${emitExpression(node.argument)} )`;
9756
9928
  }
@@ -10408,6 +10580,9 @@ ${cleanup}
10408
10580
  validateExpression(node.iterable, scope);
10409
10581
  validateForBody(node, scope);
10410
10582
  return;
10583
+ case "SwitchStatement":
10584
+ validateSwitchStatement(node, scope);
10585
+ return;
10411
10586
  case "ExpressionStatement":
10412
10587
  validateExpression(node.expression, scope);
10413
10588
  return;
@@ -10448,6 +10623,18 @@ ${cleanup}
10448
10623
  validateStatement(node.body, loopScope);
10449
10624
  validateStatement(node.elseBlock, new Scope(scope));
10450
10625
  }
10626
+ function validateSwitchStatement(node, scope) {
10627
+ validateExpression(node.discriminant, scope);
10628
+ const switchScope = new Scope(scope);
10629
+ switchScope.declare("^^", false, node);
10630
+ for (const caseNode of node.cases || []) {
10631
+ for (const value of caseNode.values || []) {
10632
+ validateExpression(value, switchScope);
10633
+ }
10634
+ validateStatement(caseNode.consequent, switchScope);
10635
+ }
10636
+ validateStatement(node.defaultCase, switchScope);
10637
+ }
10451
10638
  function validateFunctionBody(node, parentScope) {
10452
10639
  const scope = new Scope(parentScope);
10453
10640
  for (const param of node.params || []) {
@@ -11563,7 +11750,7 @@ ${cleanup}
11563
11750
  "package.json"(exports2, module2) {
11564
11751
  module2.exports = {
11565
11752
  name: "zuzu-js",
11566
- version: "0.6.0",
11753
+ version: "0.7.1",
11567
11754
  description: "JavaScript runtime, compiler, and browser bundle for ZuzuScript.",
11568
11755
  main: "lib/zuzu.js",
11569
11756
  bin: {
@@ -12343,6 +12530,23 @@ ${cleanup}
12343
12530
  }
12344
12531
  return String(value);
12345
12532
  }
12533
+ function outputString(value) {
12534
+ value = resolveWeakValue(value);
12535
+ if (value == null) {
12536
+ return "";
12537
+ }
12538
+ if (typeof value === "number" || Object.prototype.toString.call(value) === "[object Number]") {
12539
+ const numeric = Number(value);
12540
+ if (Number.isNaN(numeric)) {
12541
+ return "NaN";
12542
+ }
12543
+ if (!Number.isFinite(numeric)) {
12544
+ return numeric > 0 ? "Inf" : "-Inf";
12545
+ }
12546
+ return String(numeric);
12547
+ }
12548
+ return zuzuStringify(value);
12549
+ }
12346
12550
  function zuzuOperatorString(value) {
12347
12551
  return operatorString(value);
12348
12552
  }
@@ -12584,20 +12788,22 @@ ${cleanup}
12584
12788
  }
12585
12789
  };
12586
12790
  let runNext = false;
12791
+ let matched = false;
12587
12792
  for (const section of cases) {
12588
- let matched = false;
12793
+ let sectionMatched = false;
12589
12794
  if (Array.isArray(section.tests)) {
12590
12795
  for (const test of section.tests) {
12591
12796
  if (zuzuTruthy(await taskRuntime2.awaitValue(test(value)))) {
12592
- matched = true;
12797
+ sectionMatched = true;
12593
12798
  break;
12594
12799
  }
12595
12800
  }
12596
12801
  } else {
12597
- matched = section.values.some((item) => cmp(value, item));
12802
+ sectionMatched = section.values.some((item) => cmp(value, item));
12598
12803
  }
12599
- if (matched || runNext) {
12600
- const result = await taskRuntime2.awaitValue(section.body());
12804
+ if (sectionMatched || runNext) {
12805
+ matched = true;
12806
+ const result = await taskRuntime2.awaitValue(section.body(value));
12601
12807
  runNext = result === true;
12602
12808
  if (!runNext && result && typeof result === "object" && result.__zuzu_return) {
12603
12809
  return result;
@@ -12607,8 +12813,8 @@ ${cleanup}
12607
12813
  }
12608
12814
  }
12609
12815
  }
12610
- if (defaultBody) {
12611
- const result = await taskRuntime2.awaitValue(defaultBody());
12816
+ if (defaultBody && (!matched || runNext)) {
12817
+ const result = await taskRuntime2.awaitValue(defaultBody(value));
12612
12818
  if (result && typeof result === "object" && result.__zuzu_return) {
12613
12819
  return result;
12614
12820
  }
@@ -12651,6 +12857,16 @@ ${cleanup}
12651
12857
  }
12652
12858
  return [...zuzuOperatorString(value)].length;
12653
12859
  }
12860
+ function operatorCardinality(value) {
12861
+ value = resolveWeakValue(value);
12862
+ if (Array.isArray(value) || isPairListLike(value) || value instanceof ZuzuBag || isSetLike(value) || value && typeof value === "object" && value.constructor && value.constructor.name === "Object") {
12863
+ return lengthOf(value);
12864
+ }
12865
+ if (value && value.constructor && value.constructor.__zuzu_class_name && typeof value.count === "function") {
12866
+ return value.count();
12867
+ }
12868
+ return operatorLength(value);
12869
+ }
12654
12870
  function regexReplaceValue(current, pattern, replacement) {
12655
12871
  const source = zuzuOperatorString(current);
12656
12872
  const regex = operatorRegexp(pattern);
@@ -13923,6 +14139,25 @@ ${cleanup}
13923
14139
  }
13924
14140
  proto = Object.getPrototypeOf(proto);
13925
14141
  }
14142
+ if (object && object.constructor && object.constructor.__zuzu_class_name && typeof object.__call__ === "function") {
14143
+ const minArgs = Number(object.__call__.__zuzu_min_args || 0);
14144
+ const maxArgs = object.__call__.__zuzu_max_args;
14145
+ if (minArgs > 3 || maxArgs != null && Number(maxArgs) < 3) {
14146
+ throw new Error("Wrong number of arguments");
14147
+ }
14148
+ const fallbackArgs = args.slice();
14149
+ let namedArgs = makePairList([]);
14150
+ const lastArg = fallbackArgs.length > 0 ? fallbackArgs[fallbackArgs.length - 1] : null;
14151
+ if (isPairListLike(lastArg) && lastArg.__zuzu_temporary_call_args === true) {
14152
+ namedArgs = lastArg;
14153
+ fallbackArgs.pop();
14154
+ }
14155
+ return object.__call__(
14156
+ String(property),
14157
+ makeArray(fallbackArgs),
14158
+ namedArgs
14159
+ );
14160
+ }
13926
14161
  throw new TypeError(`${String(property)} is not a function`);
13927
14162
  }
13928
14163
  function zuzuMaybeDemolish(value, preserved = null) {
@@ -14499,12 +14734,7 @@ ${cleanup}
14499
14734
  }
14500
14735
  const moduleSearchRoots = this.getModuleSearchRoots();
14501
14736
  const emit = (value) => {
14502
- let line = String(value);
14503
- if (line === "Infinity") {
14504
- line = "Inf";
14505
- } else if (line === "-Infinity") {
14506
- line = "-Inf";
14507
- }
14737
+ const line = outputString(value);
14508
14738
  if (this.outputLines) {
14509
14739
  this.outputLines.push(line);
14510
14740
  }
@@ -14515,6 +14745,19 @@ ${cleanup}
14515
14745
  this.host.consoleLog(line);
14516
14746
  }
14517
14747
  };
14748
+ const emitNoNewline = (value) => {
14749
+ const line = outputString(value);
14750
+ if (this.outputLines) {
14751
+ this.outputLines.push(line);
14752
+ }
14753
+ if (typeof this.stdoutHandler === "function") {
14754
+ this.stdoutHandler(line);
14755
+ } else if (typeof process !== "undefined" && process.stdout) {
14756
+ process.stdout.write(line);
14757
+ } else {
14758
+ this.host.consoleLog(line);
14759
+ }
14760
+ };
14518
14761
  const emitStderr = (value) => {
14519
14762
  const line = String(value);
14520
14763
  if (typeof this.stderrHandler === "function") {
@@ -14593,29 +14836,36 @@ ${cleanup}
14593
14836
  };
14594
14837
  const unpackDeclarationSource = (input) => {
14595
14838
  const value = resolveWeakValue(input);
14596
- if (isPairListLike(value) || zuzuTypeof(value) === "Dict") {
14839
+ if (Array.isArray(value) || isPairListLike(value) || zuzuTypeof(value) === "Dict") {
14597
14840
  return value;
14598
14841
  }
14599
14842
  throw new ZuzuTypeException(
14600
- `Declaration unpacking expects Dict or PairList, got ${zuzuTypeof(value)}`
14843
+ `Declaration unpacking expects Dict, PairList, or Array, got ${zuzuTypeof(value)}`
14601
14844
  );
14602
14845
  };
14603
- const unpackDeclarationValue = (source, key, defaultThunk, name2, typeName2, isWeakStorage) => {
14846
+ const unpackDeclarationValue = (source, keyThunk, defaultThunk, name2, typeName2, isWeakStorage, index) => {
14604
14847
  const valueSource = unpackDeclarationSource(source);
14605
- const normalized = normalizeDictKey(key);
14606
14848
  let value;
14607
14849
  let found = false;
14608
- if (isPairListLike(valueSource)) {
14609
- const pair = valueSource.list.find(
14610
- (entry) => entry[0] === normalized
14611
- );
14612
- if (pair) {
14613
- value = pair[1];
14850
+ if (Array.isArray(valueSource)) {
14851
+ if (index >= 0 && index < valueSource.length) {
14852
+ value = resolveWeakValue(valueSource[index]);
14853
+ found = true;
14854
+ }
14855
+ } else {
14856
+ const normalized = normalizeDictKey(keyThunk());
14857
+ if (isPairListLike(valueSource)) {
14858
+ const pair = valueSource.list.find(
14859
+ (entry) => entry[0] === normalized
14860
+ );
14861
+ if (pair) {
14862
+ value = pair[1];
14863
+ found = true;
14864
+ }
14865
+ } else if (Object.prototype.hasOwnProperty.call(valueSource, normalized)) {
14866
+ value = valueSource[normalized];
14614
14867
  found = true;
14615
14868
  }
14616
- } else if (Object.prototype.hasOwnProperty.call(valueSource, normalized)) {
14617
- value = valueSource[normalized];
14618
- found = true;
14619
14869
  }
14620
14870
  if (!found) {
14621
14871
  value = typeof defaultThunk === "function" ? defaultThunk() : null;
@@ -14930,7 +15180,7 @@ ${cleanup}
14930
15180
  for (let i = 0; i < value.length; i++) {
14931
15181
  out += value[i];
14932
15182
  if (i < parts.length) {
14933
- out += String(parts[i]);
15183
+ out += outputString(parts[i]);
14934
15184
  }
14935
15185
  }
14936
15186
  emit(out);
@@ -14938,6 +15188,20 @@ ${cleanup}
14938
15188
  }
14939
15189
  emit(value);
14940
15190
  },
15191
+ print(value, ...parts) {
15192
+ if (Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, "raw")) {
15193
+ let out = "";
15194
+ for (let i = 0; i < value.length; i++) {
15195
+ out += value[i];
15196
+ if (i < parts.length) {
15197
+ out += outputString(parts[i]);
15198
+ }
15199
+ }
15200
+ emitNoNewline(out);
15201
+ return;
15202
+ }
15203
+ emitNoNewline(value);
15204
+ },
14941
15205
  __zuzu_switch: runSwitch,
14942
15206
  __zuzu_switch_async: runSwitchAsync,
14943
15207
  __zuzu_match: runMatch,
@@ -15244,6 +15508,7 @@ ${cleanup}
15244
15508
  return asIterable(value);
15245
15509
  },
15246
15510
  __zuzu_length: operatorLength,
15511
+ __zuzu_cardinality: operatorCardinality,
15247
15512
  __zuzu_num(value) {
15248
15513
  return zuzuToNumber(value);
15249
15514
  },
@@ -41613,9 +41878,9 @@ ${lines.join("\n")}
41613
41878
  }
41614
41879
  });
41615
41880
 
41616
- // ../../../../../tmp/zuzu-browser-build.UGYrnC/browser-stdlib.generated.js
41881
+ // ../../../../../tmp/zuzu-browser-build.3mYmJh/browser-stdlib.generated.js
41617
41882
  var require_browser_stdlib_generated = __commonJS({
41618
- "../../../../../tmp/zuzu-browser-build.UGYrnC/browser-stdlib.generated.js"(exports2, module2) {
41883
+ "../../../../../tmp/zuzu-browser-build.3mYmJh/browser-stdlib.generated.js"(exports2, module2) {
41619
41884
  "use strict";
41620
41885
  function createBrowserStdlib2() {
41621
41886
  const jsModules = /* @__PURE__ */ Object.create(null);
@@ -47853,7 +48118,7 @@ class ZZTemplate extends ZTemplate {
47853
48118
  }
47854
48119
  });
47855
48120
 
47856
- // ../../../../../tmp/zuzu-browser-build.UGYrnC/browser-worker-entry.generated.js
48121
+ // ../../../../../tmp/zuzu-browser-build.3mYmJh/browser-worker-entry.generated.js
47857
48122
  var { createBrowserStdlib } = require_browser_stdlib_generated();
47858
48123
  globalThis.__ZUZU_BROWSER_DEFAULT_RUNTIME_OPTIONS__ = createBrowserStdlib();
47859
48124
  var { installBrowserWorker } = require_browser_worker_entry();