gofront 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +13 -13
  2. package/package.json +8 -37
  3. package/src/backend/js/expressions.js +1341 -148
  4. package/src/backend/js/fmt-runtime.js +573 -0
  5. package/src/backend/js/index.js +375 -57
  6. package/src/backend/js/runtime.js +1460 -133
  7. package/src/backend/js/statements.js +900 -86
  8. package/src/backend/js/stdlib/bits.js +87 -14
  9. package/src/backend/js/stdlib/builder.js +41 -6
  10. package/src/backend/js/stdlib/bytes.js +253 -7
  11. package/src/backend/js/stdlib/errors.js +2 -1
  12. package/src/backend/js/stdlib/fmt.js +349 -10
  13. package/src/backend/js/stdlib/index.js +8 -3
  14. package/src/backend/js/stdlib/json.js +247 -52
  15. package/src/backend/js/stdlib/maps.js +0 -8
  16. package/src/backend/js/stdlib/math.js +17 -1
  17. package/src/backend/js/stdlib/simd.js +10 -0
  18. package/src/backend/js/stdlib/slices.js +36 -6
  19. package/src/backend/js/stdlib/strconv.js +10 -5
  20. package/src/backend/js/stdlib/strings.js +83 -4
  21. package/src/backend/js/stdlib/testing.js +7 -0
  22. package/src/backend/js/stdlib/time.js +79 -55
  23. package/src/backend/js/stdlib/unicode.js +1 -1
  24. package/src/backend/js/stdlib/utf8.js +1 -1
  25. package/src/backend/js/templ.js +38 -76
  26. package/src/backend/js/type-info.js +272 -0
  27. package/src/backend/shared/fmt-types.js +188 -0
  28. package/src/backend/wasm/boundary.js +436 -80
  29. package/src/backend/wasm/emit-builtins.js +303 -13
  30. package/src/backend/wasm/emit-exprs.js +1397 -203
  31. package/src/backend/wasm/emit-maps.js +61 -13
  32. package/src/backend/wasm/emit-stmts.js +1359 -164
  33. package/src/backend/wasm/emit.js +512 -77
  34. package/src/backend/wasm/encode.js +43 -13
  35. package/src/backend/wasm/globals.js +452 -0
  36. package/src/backend/wasm/index.js +194 -2489
  37. package/src/backend/wasm/method-expr.js +381 -0
  38. package/src/backend/wasm/module-emitter.js +2240 -0
  39. package/src/backend/wasm/monomorph.js +62 -4
  40. package/src/backend/wasm/prescan.js +397 -0
  41. package/src/backend/wasm/stdlib/bytes.js +1804 -127
  42. package/src/backend/wasm/stdlib/core.js +1574 -199
  43. package/src/backend/wasm/stdlib/index.js +0 -5
  44. package/src/backend/wasm/stdlib/io.js +1567 -150
  45. package/src/backend/wasm/stdlib/packages.js +2 -0
  46. package/src/backend/wasm/stdlib/simd.js +293 -28
  47. package/src/backend/wasm/stdlib/time.js +1041 -12
  48. package/src/backend/wasm/types.js +200 -15
  49. package/src/backend/wasm/variadic.js +93 -0
  50. package/src/backend/wasm/wat.js +47 -20
  51. package/src/{cli-core.js → cli/cli-core.js} +236 -10
  52. package/src/{test-runner.js → cli/test-runner.js} +332 -39
  53. package/src/{vendor.js → cli/vendor.js} +3 -4
  54. package/src/compiler.js +107 -269
  55. package/src/index.js +15 -169
  56. package/src/{lexer.js → lexer/lexer.js} +102 -55
  57. package/src/{tokens.js → lexer/tokens.js} +1 -0
  58. package/src/link/sourcemap.js +97 -0
  59. package/src/link/stdlib.js +515 -0
  60. package/src/link/wasm.js +294 -0
  61. package/src/lower/bounds.js +394 -0
  62. package/src/lower/boxing.js +1 -1
  63. package/src/lower/captures.js +176 -32
  64. package/src/lower/index.js +26 -18
  65. package/src/lower/json-codecs.js +1398 -0
  66. package/src/lower/ownership.js +22 -1
  67. package/src/lower/range.js +86 -1
  68. package/src/lower/reachability.js +132 -0
  69. package/src/parser/declarations.js +58 -13
  70. package/src/parser/expressions.js +29 -7
  71. package/src/parser/index.js +2 -1
  72. package/src/parser/statements.js +37 -22
  73. package/src/{templ-parser.js → parser/templ.js} +138 -15
  74. package/src/parser/types.js +69 -9
  75. package/src/resolver.js +22 -1
  76. package/src/typechecker/assignability.js +176 -17
  77. package/src/typechecker/const-fold.js +356 -0
  78. package/src/typechecker/constants.js +256 -0
  79. package/src/typechecker/expressions.js +931 -122
  80. package/src/typechecker/index.js +459 -67
  81. package/src/typechecker/init-order.js +330 -0
  82. package/src/typechecker/resolve.js +451 -56
  83. package/src/typechecker/statements.js +90 -9
  84. package/src/typechecker/stdlib/core.js +333 -55
  85. package/src/typechecker/stdlib/excluded.js +898 -0
  86. package/src/typechecker/stdlib/extended.js +322 -26
  87. package/src/typechecker/{stdlib.js → stdlib/index.js} +5 -5
  88. package/src/typechecker/stdlib/simd.js +65 -15
  89. package/src/typechecker/termination.js +1 -1
  90. package/src/typechecker/types.js +149 -25
  91. package/stdlib/bytes/iter.go +192 -0
  92. package/stdlib/bytes/search.go +240 -0
  93. package/stdlib/bytes/split.go +218 -0
  94. package/stdlib/cmp/cmp.go +65 -0
  95. package/stdlib/encoding/json/errors.go +31 -0
  96. package/stdlib/encoding/json/indent.go +71 -0
  97. package/stdlib/encoding/json/number.go +12 -0
  98. package/stdlib/encoding/json/stream.go +173 -0
  99. package/stdlib/errors/overlay.go +12 -0
  100. package/stdlib/hash/hash.go +53 -0
  101. package/stdlib/internal/jsonrt/dec.go +738 -0
  102. package/stdlib/internal/jsonrt/enc.go +366 -0
  103. package/stdlib/internal/jsonrt/indent.go +135 -0
  104. package/stdlib/internal/jsonrt/number.go +27 -0
  105. package/stdlib/internal/jsonrt/reader.go +73 -0
  106. package/stdlib/internal/jsonrt/scanner.go +649 -0
  107. package/stdlib/io/io.go +346 -0
  108. package/stdlib/iter/iter.go +18 -0
  109. package/stdlib/maps/iter.go +65 -0
  110. package/stdlib/math/extra.go +270 -0
  111. package/stdlib/slices/extra.go +73 -0
  112. package/stdlib/slices/iter.go +113 -0
  113. package/stdlib/sort/sort.go +561 -0
  114. package/stdlib/strconv/quote.go +341 -0
  115. package/stdlib/strings/extra.go +35 -0
  116. package/stdlib/strings/iter.go +122 -0
  117. package/stdlib/sync/extra.go +105 -0
  118. package/stdlib/unicode/unicode.go +112 -0
  119. package/stdlib/unicode/utf8/bytes.go +239 -0
  120. package/src/backend/wasm/const-fold.js +0 -205
  121. package/src/backend/wasm/emit-stdlib.js +0 -13
  122. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  123. /package/src/{colors.js → cli/colors.js} +0 -0
  124. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  125. /package/src/{minifier.js → cli/minifier.js} +0 -0
  126. /package/src/{project-config.js → cli/project-config.js} +0 -0
  127. /package/src/{pwa.js → cli/pwa.js} +0 -0
  128. /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
@@ -3,37 +3,110 @@
3
3
 
4
4
  /** @typedef {import('../index.js').CodeGen} CodeGen */
5
5
 
6
+ function toBig64(x) {
7
+ const trimmed = String(x).trim();
8
+ if (/^-?(0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|\d+)n?$/.test(trimmed)) {
9
+ return trimmed.endsWith("n") ? trimmed : `${trimmed}n`;
10
+ }
11
+ return `BigInt(${x})`;
12
+ }
13
+
6
14
  const BITS_MAP = {
15
+ Add32: ([x, y, c]) =>
16
+ `((() => { const s = BigInt((${x}) >>> 0) + BigInt((${y}) >>> 0) + BigInt((${c}) >>> 0); return [Number(s & 0xffffffffn), Number(s >> 32n)]; })())`,
17
+ Add64: ([x, y, c]) =>
18
+ `((() => { const s = BigInt.asUintN(64, ${toBig64(x)}) + BigInt.asUintN(64, ${toBig64(y)}) + BigInt.asUintN(64, ${toBig64(c)}); return [Number(BigInt.asUintN(64, s)), Number(s >> 64n)]; })())`,
19
+ Add: (args) => BITS_MAP.Add64(args),
20
+
21
+ Sub32: ([x, y, b]) =>
22
+ `((() => { const diff = BigInt((${x}) >>> 0) - BigInt((${y}) >>> 0) - BigInt((${b}) >>> 0); return [Number(BigInt.asUintN(32, diff)), diff < 0n ? 1 : 0]; })())`,
23
+ Sub64: ([x, y, b]) =>
24
+ `((() => { const diff = BigInt.asUintN(64, ${toBig64(x)}) - BigInt.asUintN(64, ${toBig64(y)}) - BigInt.asUintN(64, ${toBig64(b)}); return [Number(BigInt.asUintN(64, diff)), diff < 0n ? 1 : 0]; })())`,
25
+ Sub: (args) => BITS_MAP.Sub64(args),
26
+
27
+ Mul32: ([x, y]) =>
28
+ `((() => { const p = BigInt((${x}) >>> 0) * BigInt((${y}) >>> 0); return [Number(p >> 32n), Number(p & 0xffffffffn)]; })())`,
29
+ Mul64: ([x, y]) =>
30
+ `((() => { const xB = BigInt.asUintN(64, ${toBig64(x)}); const yB = BigInt.asUintN(64, ${toBig64(y)}); const mask32 = 0xffffffffn; const x0 = xB & mask32, x1 = xB >> 32n; const y0 = yB & mask32, y1 = yB >> 32n; const w0 = x0 * y0; const t = x1 * y0 + (w0 >> 32n); const w1 = (t & mask32) + x0 * y1; const hi = x1 * y1 + (t >> 32n) + (w1 >> 32n); const lo = BigInt.asUintN(64, xB * yB); return [Number(hi), Number(lo)]; })())`,
31
+ Mul: (args) => BITS_MAP.Mul64(args),
32
+
33
+ Div32: ([hi, lo, y]) =>
34
+ `((() => { const yu = (${y}) >>> 0; if (yu === 0) throw new Error("runtime error: integer divide by zero"); const hiu = (${hi}) >>> 0; if (hiu >= yu) throw new Error("runtime error: integer overflow"); const z = (BigInt(hiu) << 32n) | BigInt((${lo}) >>> 0); const yB = BigInt(yu); return [Number(z / yB), Number(z % yB)]; })())`,
35
+ Div64: ([hi, lo, y]) =>
36
+ `((() => { const yB = BigInt.asUintN(64, ${toBig64(y)}); if (yB === 0n) throw new Error("runtime error: integer divide by zero"); const hiB = BigInt.asUintN(64, ${toBig64(hi)}); if (hiB >= yB) throw new Error("runtime error: integer overflow"); const loB = BigInt.asUintN(64, ${toBig64(lo)}); const z = (hiB << 64n) | loB; return [Number(BigInt.asUintN(64, z / yB)), Number(BigInt.asUintN(64, z % yB))]; })())`,
37
+ Div: (args) => BITS_MAP.Div64(args),
38
+
39
+ Rem32: ([hi, lo, y]) =>
40
+ `((() => { const yu = (${y}) >>> 0; if (yu === 0) throw new Error("runtime error: integer divide by zero"); const z = (BigInt((${hi}) >>> 0) << 32n) | BigInt((${lo}) >>> 0); return Number(z % BigInt(yu)); })())`,
41
+ Rem64: ([hi, lo, y]) =>
42
+ `((() => { const yB = BigInt.asUintN(64, ${toBig64(y)}); if (yB === 0n) throw new Error("runtime error: integer divide by zero"); const z = ((BigInt.asUintN(64, ${toBig64(hi)}) % yB) << 64n) | BigInt.asUintN(64, ${toBig64(lo)}); return Number(BigInt.asUintN(64, z % yB)); })())`,
43
+ Rem: (args) => BITS_MAP.Rem64(args),
44
+
45
+ LeadingZeros8: ([x]) =>
46
+ `((() => { const v = (${x}) & 0xff; return v === 0 ? 8 : Math.clz32(v) - 24; })())`,
47
+ LeadingZeros16: ([x]) =>
48
+ `((() => { const v = (${x}) & 0xffff; return v === 0 ? 16 : Math.clz32(v) - 16; })())`,
7
49
  LeadingZeros32: ([x]) => `Math.clz32((${x}) >>> 0)`,
50
+ LeadingZeros64: ([x]) =>
51
+ `((() => { const v = BigInt.asUintN(64, ${toBig64(x)}); if (v === 0n) return 64; const hi = Number(v >> 32n); return hi !== 0 ? Math.clz32(hi) : 32 + Math.clz32(Number(v & 0xffffffffn)); })())`,
52
+ LeadingZeros: (args) => BITS_MAP.LeadingZeros64(args),
53
+
54
+ TrailingZeros8: ([x]) =>
55
+ `((() => { const v = (${x}) & 0xff; return v === 0 ? 8 : 31 - Math.clz32(v & -v); })())`,
56
+ TrailingZeros16: ([x]) =>
57
+ `((() => { const v = (${x}) & 0xffff; return v === 0 ? 16 : 31 - Math.clz32(v & -v); })())`,
8
58
  TrailingZeros32: ([x]) =>
9
59
  `((() => { const v = (${x}) >>> 0; return v === 0 ? 32 : 31 - Math.clz32(v & -v); })())`,
60
+ TrailingZeros64: ([x]) =>
61
+ `((() => { const v = BigInt.asUintN(64, ${toBig64(x)}); if (v === 0n) return 64; const lo = Number(v & 0xffffffffn); if (lo !== 0) return 31 - Math.clz32(lo & -lo); const hi = Number((v >> 32n) & 0xffffffffn); return 32 + (31 - Math.clz32(hi & -hi)); })())`,
62
+ TrailingZeros: (args) => BITS_MAP.TrailingZeros64(args),
63
+
64
+ OnesCount8: ([x]) =>
65
+ `((() => { let v = (${x}) & 0xff; v = v - ((v >>> 1) & 0x55); v = (v & 0x33) + ((v >>> 2) & 0x33); return (v + (v >>> 4)) & 0x0f; })())`,
66
+ OnesCount16: ([x]) =>
67
+ `((() => { let v = (${x}) & 0xffff; v = v - ((v >>> 1) & 0x5555); v = (v & 0x3333) + ((v >>> 2) & 0x3333); return ((Math.imul((v + (v >>> 4)) & 0x0f0f, 0x0101)) >>> 8) & 0xff; })())`,
10
68
  OnesCount32: ([x]) =>
11
69
  `((() => { let v = (${x}) >>> 0; v = v - ((v >>> 1) & 0x55555555); v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); return (Math.imul((v + (v >>> 4)) & 0x0f0f0f0f, 0x01010101)) >>> 24; })())`,
70
+ OnesCount64: ([x]) =>
71
+ `((() => { let v = BigInt.asUintN(64, ${toBig64(x)}); let c = 0; while (v > 0n) { if (v & 1n) c++; v >>= 1n; } return c; })())`,
72
+ OnesCount: (args) => BITS_MAP.OnesCount64(args),
73
+
74
+ RotateLeft8: ([x, k]) =>
75
+ `((() => { const s = (${k}) & 7; const v = (${x}) & 0xff; return ((v << s) | (v >>> ((8 - s) & 7))) & 0xff; })())`,
76
+ RotateLeft16: ([x, k]) =>
77
+ `((() => { const s = (${k}) & 15; const v = (${x}) & 0xffff; return ((v << s) | (v >>> ((16 - s) & 15))) & 0xffff; })())`,
12
78
  RotateLeft32: ([x, k]) =>
13
79
  `((() => { const s = (${k}) & 31; const v = (${x}) >>> 0; return ((v << s) | (v >>> ((32 - s) & 31))) >>> 0; })())`,
14
-
15
- LeadingZeros64: ([x]) =>
16
- `((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 64; const hi = Number(v >> 32n); return hi !== 0 ? Math.clz32(hi) : 32 + Math.clz32(Number(v & 0xffffffffn)); })())`,
17
- TrailingZeros64: ([x]) =>
18
- `((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 64; const lo = Number(v & 0xffffffffn); if (lo !== 0) return 31 - Math.clz32(lo & -lo); const hi = Number((v >> 32n) & 0xffffffffn); return 32 + (31 - Math.clz32(hi & -hi)); })())`,
19
- OnesCount64: ([x]) =>
20
- `((() => { let v = BigInt.asUintN(64, BigInt(${x})); let c = 0; while (v > 0n) { if (v & 1n) c++; v >>= 1n; } return c; })())`,
21
80
  RotateLeft64: ([x, k]) =>
22
- `((() => { const s = BigInt(${k}) & 63n; const v = BigInt.asUintN(64, BigInt(${x})); return Number(BigInt.asUintN(64, (v << s) | (v >> ((64n - s) & 63n)))); })())`,
81
+ `((() => { const s = ${toBig64(k)} & 63n; const v = BigInt.asUintN(64, ${toBig64(x)}); return Number(BigInt.asUintN(64, (v << s) | (v >> ((64n - s) & 63n)))); })())`,
82
+ RotateLeft: (args) => BITS_MAP.RotateLeft64(args),
23
83
 
84
+ Len8: ([x]) =>
85
+ `((() => { const v = (${x}) & 0xff; return v === 0 ? 0 : 32 - Math.clz32(v); })())`,
86
+ Len16: ([x]) =>
87
+ `((() => { const v = (${x}) & 0xffff; return v === 0 ? 0 : 32 - Math.clz32(v); })())`,
24
88
  Len32: ([x]) => `((v => 32 - Math.clz32(v >>> 0))(${x}))`,
25
89
  Len64: ([x]) =>
26
- `((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 0; const hi = Number(v >> 32n); return hi !== 0 ? 64 - Math.clz32(hi) : 32 - Math.clz32(Number(v & 0xffffffffn)); })())`,
90
+ `((() => { const v = BigInt.asUintN(64, ${toBig64(x)}); if (v === 0n) return 0; const hi = Number(v >> 32n); return hi !== 0 ? 64 - Math.clz32(hi) : 32 - Math.clz32(Number(v & 0xffffffffn)); })())`,
91
+ Len: (args) => BITS_MAP.Len64(args),
92
+
93
+ Reverse8: ([x]) =>
94
+ `((() => { let v = (${x}) & 0xff; v = ((v >>> 1) & 0x55) | ((v & 0x55) << 1); v = ((v >>> 2) & 0x33) | ((v & 0x33) << 2); return (((v >>> 4) & 0x0f) | ((v & 0x0f) << 4)) & 0xff; })())`,
95
+ Reverse16: ([x]) =>
96
+ `((() => { let v = (${x}) & 0xffff; v = ((v >>> 1) & 0x5555) | ((v & 0x5555) << 1); v = ((v >>> 2) & 0x3333) | ((v & 0x3333) << 2); v = ((v >>> 4) & 0x0f0f) | ((v & 0x0f0f) << 4); return (((v >>> 8) & 0x00ff) | ((v & 0x00ff) << 8)) & 0xffff; })())`,
97
+ Reverse32: ([x]) =>
98
+ `((() => { let v = (${x}) >>> 0; v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; })())`,
99
+ Reverse64: ([x]) =>
100
+ `((() => { const rev32 = (v) => { v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; }; const v = BigInt.asUintN(64, ${toBig64(x)}); const lo = Number(v & 0xffffffffn); const hi = Number((v >> 32n) & 0xffffffffn); return Number((BigInt(rev32(lo)) << 32n) | BigInt(rev32(hi))); })())`,
101
+ Reverse: (args) => BITS_MAP.Reverse64(args),
102
+
27
103
  ReverseBytes16: ([x]) =>
28
104
  `((v => ((v & 0xff) << 8) | ((v >>> 8) & 0xff))((${x}) & 0xffff))`,
29
105
  ReverseBytes32: ([x]) =>
30
106
  `((v => (((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v >>> 8) & 0xff00) | ((v >>> 24) & 0xff)) >>> 0)((${x}) >>> 0))`,
31
107
  ReverseBytes64: ([x]) =>
32
- `((() => { const v = BigInt.asUintN(64, BigInt(${x})); let r = 0n; for (let i = 0n; i < 8n; i++) r = (r << 8n) | ((v >> (i * 8n)) & 0xffn); return Number(r); })())`,
33
- Reverse32: ([x]) =>
34
- `((() => { let v = (${x}) >>> 0; v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; })())`,
35
- Reverse64: ([x]) =>
36
- `((() => { const rev32 = (v) => { v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; }; const v = BigInt.asUintN(64, BigInt(${x})); const lo = Number(v & 0xffffffffn); const hi = Number((v >> 32n) & 0xffffffffn); return Number((BigInt(rev32(lo)) << 32n) | BigInt(rev32(hi))); })())`,
108
+ `((() => { const v = BigInt.asUintN(64, ${toBig64(x)}); let r = 0n; for (let i = 0n; i < 8n; i++) r = (r << 8n) | ((v >> (i * 8n)) & 0xffn); return Number(r); })())`,
109
+ ReverseBytes: (args) => BITS_MAP.ReverseBytes64(args),
37
110
  };
38
111
 
39
112
  /** @type {ThisType<CodeGen>} */
@@ -20,16 +20,41 @@ const BUILDER_STR = {
20
20
  };
21
21
  const BUILDER_BYTES = {
22
22
  WriteString: (b, a) =>
23
- `((buf, s) => { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
24
- WriteByte: (b, a) => `(${b}._buf.push(${a[0]}), null)`,
23
+ `((buf, s) => { buf._lastOp = 0; const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
24
+ WriteByte: (b, a) =>
25
+ `((buf, c) => { buf._lastOp = 0; buf._buf.push(c); return null; })(${b}, ${a[0]})`,
25
26
  WriteRune: (b, a) =>
26
- `((buf, cp) => { const r = (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) ? 0xfffd : cp; const bytes = new TextEncoder().encode(String.fromCodePoint(r)); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
27
+ `((buf, cp) => { buf._lastOp = 0; const r = (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) ? 0xfffd : cp; const bytes = new TextEncoder().encode(String.fromCodePoint(r)); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
27
28
  Write: (b, a) =>
28
- `((buf, d) => { for (let i = 0; i < d.length; i++) buf._buf.push(d[i]); return [d.length, null]; })(${b}, ${a[0]})`,
29
+ `((buf, d) => { buf._lastOp = 0; for (let i = 0; i < d.length; i++) buf._buf.push(d[i]); return [d.length, null]; })(${b}, ${a[0]})`,
29
30
  String: (b) => `new TextDecoder().decode(new Uint8Array(${b}._buf))`,
30
31
  Reset: (b) => `(${b}._buf = [])`,
31
32
  Read: (b, a) =>
32
- `((buf, p) => { if (buf._buf.length === 0) return [0, __io_eof]; const n = Math.min(p.length, buf._buf.length); for (let i = 0; i < n; i++) p[i] = buf._buf.shift(); return [n, null]; })(${b}, ${a[0]})`,
33
+ `((buf, p) => { if (!buf._buf || buf._buf.length === 0) return [0, __io_eof]; const n = Math.min(p.length, buf._buf.length); for (let i = 0; i < n; i++) p[i] = buf._buf.shift(); if (n > 0) { buf._lastOp = 1; buf._lastByte = p[n - 1]; } else { buf._lastOp = 0; } return [n, null]; })(${b}, ${a[0]})`,
34
+ ReadByte: (b) =>
35
+ `((buf) => { if (!buf._buf || buf._buf.length === 0) return [0, __io_eof]; const c = buf._buf.shift(); buf._lastOp = 1; buf._lastByte = c; return [c, null]; })(${b})`,
36
+ UnreadByte: (b) =>
37
+ `((buf) => { if (buf._lastOp !== 1) return __error("bytes.Buffer: UnreadByte: previous operation was not a successful read"); buf._buf.unshift(buf._lastByte); buf._lastOp = 0; return null; })(${b})`,
38
+ ReadRune: (b) =>
39
+ `((buf) => { if (!buf._buf || buf._buf.length === 0) return [0, 0, __io_eof]; const u8 = new Uint8Array(buf._buf); const s = new TextDecoder().decode(u8); const cp = s.codePointAt(0); const runeStr = s.slice(0, cp > 0xffff ? 2 : 1); const sz = new TextEncoder().encode(runeStr).length; for (let i = 0; i < sz; i++) buf._buf.shift(); buf._lastOp = 2; buf._lastRune = runeStr; return [cp, sz, null]; })(${b})`,
40
+ UnreadRune: (b) =>
41
+ `((buf) => { if (buf._lastOp !== 2) return __error("bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune"); const bts = new TextEncoder().encode(buf._lastRune); for (let i = bts.length - 1; i >= 0; i--) buf._buf.unshift(bts[i]); buf._lastOp = 0; return null; })(${b})`,
42
+ ReadBytes: (b, a) =>
43
+ `((buf, delim) => { const idx = buf._buf.indexOf(delim); if (idx < 0) { const rem = Uint8Array.from(buf._buf); buf._buf = []; return [rem, __io_eof]; } const line = Uint8Array.from(buf._buf.splice(0, idx + 1)); return [line, null]; })(${b}, ${a[0]})`,
44
+ ReadString: (b, a) =>
45
+ `((buf, delim) => { const idx = buf._buf.indexOf(delim); if (idx < 0) { const rem = new TextDecoder().decode(Uint8Array.from(buf._buf)); buf._buf = []; return [rem, __io_eof]; } const line = new TextDecoder().decode(Uint8Array.from(buf._buf.splice(0, idx + 1))); return [line, null]; })(${b}, ${a[0]})`,
46
+ ReadFrom: (b, a) =>
47
+ `((buf, r) => { let total = 0n; const tmp = new Uint8Array(4096); while (true) { const [n, err] = r.Read(tmp); if (n > 0) { for (let i = 0; i < n; i++) buf._buf.push(tmp[i]); total += BigInt(n); } if (err) { return [total, (err === __io_eof || err?.Error?.() === "EOF") ? null : err]; } } })(${b}, ${a[0]})`,
48
+ WriteTo: (b, a) =>
49
+ `((buf, w) => { if (!buf._buf || buf._buf.length === 0) return [0n, null]; const bytes = Uint8Array.from(buf._buf); const [n, err] = w.Write(bytes); if (n > 0) buf._buf.splice(0, n); return [BigInt(n), err]; })(${b}, ${a[0]})`,
50
+ Next: (b, a) =>
51
+ `((buf, n) => { const cnt = Math.min(Math.max(0, n), buf._buf.length); return Uint8Array.from(buf._buf.splice(0, cnt)); })(${b}, ${a[0]})`,
52
+ Truncate: (b, a) =>
53
+ `((buf, n) => { if (n < 0 || n > buf._buf.length) throw new Error("bytes.Buffer: truncation out of range"); buf._buf.length = n; })(${b}, ${a[0]})`,
54
+ Available: (b) => `Math.max(0, (${b}._cap ?? 0) - ${b}._buf.length)`,
55
+ AvailableBuffer: () => `new Uint8Array(0)`,
56
+ Peek: (b, a) =>
57
+ `((buf, n) => { if (n < 0) throw new Error("runtime error: slice bounds out of range"); if (n > buf._buf.length) return [Uint8Array.from(buf._buf), __io_eof]; return [Uint8Array.from(buf._buf.slice(0, n)), null]; })(${b}, ${a[0]})`,
33
58
  };
34
59
  const BUILDER_COMMON = {
35
60
  Bytes: (b) => `new Uint8Array(${b}._buf)`,
@@ -45,7 +70,17 @@ export const builderMethods = {
45
70
  const recv = expr.func.expr;
46
71
  const base = this._unboxWriter(this.genExpr(recv));
47
72
  const args = expr.args.map((a) => this.genExpr(a));
48
- if (method === "Read") {
73
+ if (
74
+ method === "Read" ||
75
+ method === "ReadByte" ||
76
+ method === "ReadRune" ||
77
+ method === "ReadBytes" ||
78
+ method === "ReadString" ||
79
+ method === "ReadFrom" ||
80
+ method === "UnreadByte" ||
81
+ method === "UnreadRune" ||
82
+ method === "Peek"
83
+ ) {
49
84
  this.useHelper("ioEOF");
50
85
  this.useHelper("error");
51
86
  }
@@ -6,14 +6,100 @@ const __bs = `(b => typeof TextDecoder !== "undefined" ? new TextDecoder().decod
6
6
  const __sb = `(s => typeof TextEncoder !== "undefined" ? new TextEncoder().encode(s) : new Uint8Array([...s].map(c => c.charCodeAt(0))))`;
7
7
 
8
8
  const BYTES_DISPATCH = {
9
- Contains: (a) => `${__bs}(${a[0]}).includes(${__bs}(${a[1]}))`,
9
+ Contains: (a) =>
10
+ `((b, sep) => {
11
+ b = b || new Uint8Array(0);
12
+ sep = sep || new Uint8Array(0);
13
+ if (sep.length === 0) return true;
14
+ if (sep.length === 1) return (b.indexOf ? b.indexOf(sep[0]) : Array.prototype.indexOf.call(b, sep[0])) >= 0;
15
+ if (sep.length > b.length) return false;
16
+ const first = sep[0];
17
+ const last = sep[sep.length - 1];
18
+ let i = 0;
19
+ while (i <= b.length - sep.length) {
20
+ const idx = b.indexOf ? b.indexOf(first, i) : Array.prototype.indexOf.call(b, first, i);
21
+ if (idx < 0 || idx > b.length - sep.length) return false;
22
+ if (b[idx + sep.length - 1] === last) {
23
+ let match = true;
24
+ for (let j = 1; j < sep.length - 1; j++) {
25
+ if (b[idx + j] !== sep[j]) { match = false; break; }
26
+ }
27
+ if (match) return true;
28
+ }
29
+ i = idx + 1;
30
+ }
31
+ return false;
32
+ })(${a[0]}, ${a[1]})`,
10
33
  HasPrefix: (a) =>
11
34
  `((b, p) => { for (let i = 0; i < p.length; i++) if (b[i] !== p[i]) return false; return b.length >= p.length; })(${a[0]}, ${a[1]})`,
12
35
  HasSuffix: (a) =>
13
36
  `((b, s) => { const off = b.length - s.length; if (off < 0) return false; for (let i = 0; i < s.length; i++) if (b[off + i] !== s[i]) return false; return true; })(${a[0]}, ${a[1]})`,
14
- Index: (a) => `${__bs}(${a[0]}).indexOf(${__bs}(${a[1]}))`,
37
+ Index: (a) =>
38
+ `((b, sep) => {
39
+ b = b || new Uint8Array(0);
40
+ sep = sep || new Uint8Array(0);
41
+ const n = b.length;
42
+ const m = sep.length;
43
+ if (m === 0) return 0;
44
+ if (m === 1) return b.indexOf ? b.indexOf(sep[0]) : Array.prototype.indexOf.call(b, sep[0]);
45
+ if (m > n) return -1;
46
+ if (m === n) {
47
+ for (let k = 0; k < m; k++) if (b[k] !== sep[k]) return -1;
48
+ return 0;
49
+ }
50
+ const first = sep[0];
51
+ const last = sep[m - 1];
52
+ let i = 0;
53
+ while (i <= n - m) {
54
+ const idx = b.indexOf ? b.indexOf(first, i) : Array.prototype.indexOf.call(b, first, i);
55
+ if (idx < 0 || idx > n - m) return -1;
56
+ if (b[idx + m - 1] === last) {
57
+ let match = true;
58
+ for (let j = 1; j < m - 1; j++) {
59
+ if (b[idx + j] !== sep[j]) { match = false; break; }
60
+ }
61
+ if (match) return idx;
62
+ }
63
+ i = idx + 1;
64
+ }
65
+ return -1;
66
+ })(${a[0]}, ${a[1]})`,
15
67
  Count: (a) =>
16
- `((b, sep) => sep.length === 0 ? b.length + 1 : ${__bs}(b).split(${__bs}(sep)).length - 1)(${a[0]}, ${a[1]})`,
68
+ `((b, sep) => {
69
+ b = b || new Uint8Array(0);
70
+ sep = sep || new Uint8Array(0);
71
+ if (sep.length === 0) {
72
+ let runes = 0;
73
+ for (let i = 0; i < b.length; i++) if ((b[i] & 0xc0) !== 0x80) runes++;
74
+ return runes + 1;
75
+ }
76
+ let cnt = 0;
77
+ if (sep.length === 1) {
78
+ const c = sep[0];
79
+ for (let i = 0; i < b.length; i++) if (b[i] === c) cnt++;
80
+ return cnt;
81
+ }
82
+ let i = 0;
83
+ const first = sep[0];
84
+ const last = sep[sep.length - 1];
85
+ while (i <= b.length - sep.length) {
86
+ const idx = b.indexOf ? b.indexOf(first, i) : Array.prototype.indexOf.call(b, first, i);
87
+ if (idx < 0 || idx > b.length - sep.length) break;
88
+ if (b[idx + sep.length - 1] === last) {
89
+ let match = true;
90
+ for (let j = 1; j < sep.length - 1; j++) {
91
+ if (b[idx + j] !== sep[j]) { match = false; break; }
92
+ }
93
+ if (match) {
94
+ cnt++;
95
+ i = idx + sep.length;
96
+ continue;
97
+ }
98
+ }
99
+ i = idx + 1;
100
+ }
101
+ return cnt;
102
+ })(${a[0]}, ${a[1]})`,
17
103
  Repeat: (a) => `${__sb}(${__bs}(${a[0]}).repeat(${a[1]}))`,
18
104
  Replace: (a) =>
19
105
  `((b, o, n, cnt) => { let str = ${__bs}(b), os = ${__bs}(o), nw = ${__bs}(n); if (cnt < 0) return ${__sb}(str.replaceAll(os, () => nw)); let r = ""; let i = 0; for (; cnt > 0; cnt--) { const j = str.indexOf(os, i); if (j < 0) break; r += str.slice(i, j) + nw; i = j + os.length; if (os.length === 0) { if (i >= str.length) break; r += str[i]; i++; } } return ${__sb}(r + str.slice(i)); })(${a[0]}, ${a[1]}, ${a[2]}, ${a[3]})`,
@@ -45,10 +131,38 @@ const BYTES_DISPATCH = {
45
131
  `((b, f) => { const s = new TextDecoder().decode(new Uint8Array(b)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && f(chars[l].codePointAt(0))) l++; while (r > l && f(chars[r - 1].codePointAt(0))) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
46
132
  IndexByte: (a) => `(${a[0]}).indexOf(${a[1]})`,
47
133
  LastIndex: (a) =>
48
- `((b, s) => { for (let i = b.length - s.length; i >= 0; i--) if (s.every((v, j) => b[i + j] === v)) return i; return -1; })(${a[0]}, ${a[1]})`,
134
+ `((b, sep) => {
135
+ b = b || new Uint8Array(0);
136
+ sep = sep || new Uint8Array(0);
137
+ const n = b.length;
138
+ const m = sep.length;
139
+ if (m === 0) return n;
140
+ if (m === 1) return b.lastIndexOf ? b.lastIndexOf(sep[0]) : Array.prototype.lastIndexOf.call(b, sep[0]);
141
+ if (m > n) return -1;
142
+ if (m === n) {
143
+ for (let k = 0; k < m; k++) if (b[k] !== sep[k]) return -1;
144
+ return 0;
145
+ }
146
+ const first = sep[0];
147
+ const last = sep[m - 1];
148
+ let i = n - m;
149
+ while (i >= 0) {
150
+ const idx = b.lastIndexOf ? b.lastIndexOf(first, i) : Array.prototype.lastIndexOf.call(b, first, i);
151
+ if (idx < 0) return -1;
152
+ if (b[idx + m - 1] === last) {
153
+ let match = true;
154
+ for (let j = 1; j < m - 1; j++) {
155
+ if (b[idx + j] !== sep[j]) { match = false; break; }
156
+ }
157
+ if (match) return idx;
158
+ }
159
+ i = idx - 1;
160
+ }
161
+ return -1;
162
+ })(${a[0]}, ${a[1]})`,
49
163
  LastIndexByte: (a) => `(${a[0]}).lastIndexOf(${a[1]})`,
50
164
  Fields: (a) =>
51
- `((b) => { const s = new TextDecoder().decode(new Uint8Array(b ?? [])).trim(); return s === '' ? [] : s.split(/\\s+/).map(w => new TextEncoder().encode(w)); })(${a[0]})`,
165
+ `((b) => { const s = new TextDecoder().decode(new Uint8Array(b ?? [])); return s.split(/[ \\t\\n\\v\\f\\r\\u0085\\u00A0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+/).filter(p => p !== "").map(w => new TextEncoder().encode(w)); })(${a[0]})`,
52
166
  FieldsFunc: (a) =>
53
167
  `((b, fn) => { const s = new TextDecoder().decode(new Uint8Array(b ?? [])); const res = []; let cur = ""; for (const ch of s) { const cp = ch.codePointAt(0); if (fn(cp)) { if (cur.length > 0) { res.push(new TextEncoder().encode(cur)); cur = ""; } } else { cur += ch; } } if (cur.length > 0) res.push(new TextEncoder().encode(cur)); return res; })(${a[0]}, ${a[1]})`,
54
168
  Clone: (a) =>
@@ -108,14 +222,146 @@ const BYTES_DISPATCH = {
108
222
  r.push(b.slice(i));
109
223
  return r;
110
224
  })(${a[0]}, ${a[1]}, ${a[2]})`,
225
+ NewBuffer: (a) => `({ _buf: Array.from(${a[0]} ?? []) })`,
226
+ NewBufferString: (a) =>
227
+ `({ _buf: Array.from(new TextEncoder().encode(${a[0]} ?? "")) })`,
228
+ ToValidUTF8: (a) =>
229
+ `((b, repl) => {
230
+ if (!b) return new Uint8Array(0);
231
+ repl = repl || new Uint8Array(0);
232
+ const res = [];
233
+ let i = 0;
234
+ let inInvalid = false;
235
+ while (i < b.length) {
236
+ const b0 = b[i];
237
+ let sz = 0;
238
+ let valid = false;
239
+ if (b0 < 0x80) {
240
+ sz = 1;
241
+ valid = true;
242
+ } else if (b0 >= 0xC2 && b0 <= 0xDF) {
243
+ if (i + 1 < b.length && (b[i+1] & 0xC0) === 0x80) {
244
+ sz = 2;
245
+ valid = true;
246
+ }
247
+ } else if (b0 >= 0xE0 && b0 <= 0xEF) {
248
+ if (i + 2 < b.length && (b[i+1] & 0xC0) === 0x80 && (b[i+2] & 0xC0) === 0x80) {
249
+ const r = ((b0 & 0x0F) << 12) | ((b[i+1] & 0x3F) << 6) | (b[i+2] & 0x3F);
250
+ if (r >= 0x800 && (r < 0xD800 || r > 0xDFFF)) {
251
+ sz = 3;
252
+ valid = true;
253
+ }
254
+ }
255
+ } else if (b0 >= 0xF0 && b0 <= 0xF4) {
256
+ if (i + 3 < b.length && (b[i+1] & 0xC0) === 0x80 && (b[i+2] & 0xC0) === 0x80 && (b[i+3] & 0xC0) === 0x80) {
257
+ const r = ((b0 & 0x07) << 18) | ((b[i+1] & 0x3F) << 12) | ((b[i+2] & 0x3F) << 6) | (b[i+3] & 0x3F);
258
+ if (r >= 0x10000 && r <= 0x10FFFF) {
259
+ sz = 4;
260
+ valid = true;
261
+ }
262
+ }
263
+ }
264
+ if (valid) {
265
+ if (inInvalid) {
266
+ for (let k = 0; k < repl.length; k++) res.push(repl[k]);
267
+ inInvalid = false;
268
+ }
269
+ for (let k = 0; k < sz; k++) res.push(b[i + k]);
270
+ i += sz;
271
+ } else {
272
+ inInvalid = true;
273
+ i += 1;
274
+ }
275
+ }
276
+ if (inInvalid) {
277
+ for (let k = 0; k < repl.length; k++) res.push(repl[k]);
278
+ }
279
+ return new Uint8Array(res);
280
+ })(${a[0]}, ${a[1]})`,
111
281
  NewReader: (a) =>
112
- `((b) => ({ _src: b, _pos: 0, Read(p) { if (this._pos >= this._src.length) return [0, __io_eof]; const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src[this._pos + i]; this._pos += n; return [n, null]; }, Len() { return Math.max(0, this._src.length - this._pos); }, Reset(b2) { this._src = b2; this._pos = 0; } }))(${a[0]})`,
282
+ `((b) => ({
283
+ _src: b,
284
+ _pos: 0,
285
+ _prevRune: -1,
286
+ Read(p) {
287
+ if (this._pos >= this._src.length) return [0, __io_eof];
288
+ const n = Math.min(p.length, this._src.length - this._pos);
289
+ for (let i = 0; i < n; i++) p[i] = this._src[this._pos + i];
290
+ this._pos += n;
291
+ this._prevRune = -1;
292
+ return [n, null];
293
+ },
294
+ ReadAt(p, off) {
295
+ const o = Number(off);
296
+ if (o < 0) return [0, __error("bytes.Reader.ReadAt: negative offset")];
297
+ if (o >= this._src.length) return [0, __io_eof];
298
+ const n = Math.min(p.length, this._src.length - o);
299
+ for (let i = 0; i < n; i++) p[i] = this._src[o + i];
300
+ return [n, n < p.length ? __io_eof : null];
301
+ },
302
+ ReadByte() {
303
+ if (this._pos >= this._src.length) return [0, __io_eof];
304
+ this._prevRune = -1;
305
+ return [this._src[this._pos++], null];
306
+ },
307
+ UnreadByte() {
308
+ if (this._pos <= 0) return __error("bytes.Reader.UnreadByte: at beginning of slice");
309
+ this._prevRune = -1;
310
+ this._pos--;
311
+ return null;
312
+ },
313
+ ReadRune() {
314
+ if (this._pos >= this._src.length) return [0, 0, __io_eof];
315
+ const rem = this._src.subarray ? this._src.subarray(this._pos) : new Uint8Array(this._src.slice(this._pos));
316
+ const s = new TextDecoder().decode(rem);
317
+ const cp = s.codePointAt(0);
318
+ const runeStr = s.slice(0, cp > 0xffff ? 2 : 1);
319
+ const sz = new TextEncoder().encode(runeStr).length;
320
+ this._prevRune = this._pos;
321
+ this._pos += sz;
322
+ return [cp, sz, null];
323
+ },
324
+ UnreadRune() {
325
+ if (this._prevRune === undefined || this._prevRune < 0 || this._prevRune >= this._pos) {
326
+ return __error("bytes.Reader.UnreadRune: previous operation was not ReadRune");
327
+ }
328
+ this._pos = this._prevRune;
329
+ this._prevRune = -1;
330
+ return null;
331
+ },
332
+ Seek(offset, whence) {
333
+ const off = BigInt(offset);
334
+ const w = Number(whence);
335
+ let newPos;
336
+ if (w === 0) newPos = off;
337
+ else if (w === 1) newPos = BigInt(this._pos) + off;
338
+ else if (w === 2) newPos = BigInt(this._src.length) + off;
339
+ else return [0n, __error("bytes.Reader.Seek: invalid whence")];
340
+ if (newPos < 0n) return [0n, __error("bytes.Reader.Seek: negative position")];
341
+ this._pos = Number(newPos);
342
+ this._prevRune = -1;
343
+ return [newPos, null];
344
+ },
345
+ Size() { return BigInt(this._src.length); },
346
+ WriteTo(w) {
347
+ if (this._pos >= this._src.length) return [0, null];
348
+ const rem = this._src.subarray ? this._src.subarray(this._pos) : new Uint8Array(this._src.slice(this._pos));
349
+ const [n, err] = w.Write(rem);
350
+ this._pos += n;
351
+ return [n, err];
352
+ },
353
+ Len() { return Math.max(0, this._src.length - this._pos); },
354
+ Reset(b2) { this._src = b2; this._pos = 0; this._prevRune = -1; }
355
+ }))(${a[0]})`,
113
356
  };
114
357
 
115
358
  /** @type {ThisType<CodeGen>} */
116
359
  export const bytesMethods = {
117
360
  _genBytes(fn, a) {
118
- if (fn === "NewReader") this.useHelper("ioEOF");
361
+ if (fn === "NewReader") {
362
+ this.useHelper("ioEOF");
363
+ this.useHelper("error");
364
+ }
119
365
  const gen = BYTES_DISPATCH[fn];
120
366
  return gen ? gen(a()) : undefined;
121
367
  },
@@ -14,7 +14,8 @@ export const errorsMethods = {
14
14
  this.useHelper("errorIs");
15
15
  return `__errorIs(${args[0]}, ${args[1]})`;
16
16
  }
17
- if (fn === "Unwrap") return `(${args[0]}?._cause ?? null)`;
17
+ if (fn === "Unwrap")
18
+ return `((e) => typeof e?.Unwrap === "function" ? e.Unwrap() : (e?._cause ?? null))(${args[0]})`;
18
19
  if (fn === "As") {
19
20
  this.useHelper("errorAs");
20
21
  const targetGoType = expr?.args?.[1]?._type;