gofront 1.6.0 → 1.6.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.
- package/package.json +1 -1
- package/src/backend/js/expressions.js +238 -109
- package/src/backend/js/index.js +38 -1
- package/src/backend/js/runtime.js +953 -53
- package/src/backend/js/statements.js +55 -67
- package/src/backend/js/stdlib/base64.js +12 -0
- package/src/backend/js/stdlib/binary.js +102 -0
- package/src/backend/js/stdlib/bits.js +15 -1
- package/src/backend/js/stdlib/builder.js +28 -9
- package/src/backend/js/stdlib/bytes.js +75 -18
- package/src/backend/js/stdlib/errors.js +20 -1
- package/src/backend/js/stdlib/fmt.js +70 -13
- package/src/backend/js/stdlib/hex.js +17 -0
- package/src/backend/js/stdlib/html.js +1 -1
- package/src/backend/js/stdlib/index.js +16 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/math.js +13 -1
- package/src/backend/js/stdlib/path.js +18 -4
- package/src/backend/js/stdlib/rand.js +10 -5
- package/src/backend/js/stdlib/sha256.js +12 -0
- package/src/backend/js/stdlib/slices.js +52 -26
- package/src/backend/js/stdlib/strconv.js +21 -5
- package/src/backend/js/stdlib/strings.js +148 -15
- package/src/backend/js/stdlib/sync.js +13 -0
- package/src/backend/js/stdlib/time.js +90 -19
- package/src/backend/js/stdlib/unicode.js +2 -2
- package/src/backend/wasm/boundary.js +1207 -41
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +203 -76
- package/src/backend/wasm/emit-exprs.js +464 -276
- package/src/backend/wasm/emit-maps.js +144 -8
- package/src/backend/wasm/emit-stdlib.js +12 -3005
- package/src/backend/wasm/emit-stmts.js +264 -270
- package/src/backend/wasm/emit.js +115 -87
- package/src/backend/wasm/encode.js +55 -29
- package/src/backend/wasm/index.js +1001 -32
- package/src/backend/wasm/optimize.js +13 -4
- package/src/backend/wasm/stdlib/bytes.js +5039 -0
- package/src/backend/wasm/stdlib/core.js +8903 -0
- package/src/backend/wasm/stdlib/index.js +40 -0
- package/src/backend/wasm/stdlib/io.js +2161 -0
- package/src/backend/wasm/stdlib/packages.js +2400 -0
- package/src/backend/wasm/stdlib/pure.js +720 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +153 -1
- package/src/cli-core.js +1 -1
- package/src/compiler.js +18 -4
- package/src/dts-parser.js +79 -126
- package/src/index.js +2 -6
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +1 -2
- package/src/lower/captures.js +2 -6
- package/src/lower/ownership.js +30 -9
- package/src/minifier.js +20 -68
- package/src/parser/declarations.js +3 -6
- package/src/parser/expressions.js +3 -8
- package/src/parser/index.js +18 -3
- package/src/parser/statements.js +25 -38
- package/src/parser/types.js +1 -2
- package/src/resolver.js +2 -27
- package/src/templ-lexer.js +29 -63
- package/src/templ-parser.js +22 -45
- package/src/typechecker/assignability.js +81 -13
- package/src/typechecker/expressions.js +102 -2
- package/src/typechecker/resolve.js +36 -6
- package/src/typechecker/stdlib/core.js +280 -89
- package/src/typechecker/stdlib/extended.js +453 -1
- package/src/typechecker/types.js +344 -6
|
@@ -3,16 +3,30 @@
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
5
|
const _SSCAN_LOOP =
|
|
6
|
-
`let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
|
|
7
|
-
`const
|
|
8
|
-
`if (
|
|
9
|
-
`else if (
|
|
6
|
+
`let n = 0, err = null; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
|
|
7
|
+
`const item = tokens[i]; const t = typeof item === "object" && item !== null ? item.t : item; const verb = item?.verb; const p = ptrs[i]; ` +
|
|
8
|
+
`if (verb === "%c") { p.value = t.codePointAt ? t.codePointAt(0) : t; } ` +
|
|
9
|
+
`else if (verb === "%x" || verb === "%X") { const clean = t.replace(/^0[xX]/, ""); const v = parseInt(clean, 16); if (isNaN(v)) { err = __error("expected hex number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0x" + clean) : v; } ` +
|
|
10
|
+
`else if (verb === "%o") { const clean = t.replace(/^0[oO]?/, ""); const v = parseInt(clean, 8); if (isNaN(v)) { err = __error("expected octal number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0o" + clean) : v; } ` +
|
|
11
|
+
`else if (verb === "%b") { const clean = t.replace(/^0[bB]/, ""); const v = parseInt(clean, 2); if (isNaN(v)) { err = __error("expected binary number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0b" + clean) : v; } ` +
|
|
12
|
+
`else if (typeof p.value === "number") { const v = Number(t); if (Number.isNaN(v) || !/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/.test(t)) { err = __error("expected number"); break; } p.value = v; } ` +
|
|
13
|
+
`else if (typeof p.value === "bigint") { try { if (!/^[+-]?\\d+$/.test(t)) throw 1; p.value = BigInt(t); } catch { err = __error("expected integer"); break; } } ` +
|
|
14
|
+
`else if (typeof p.value === "boolean") { const tl = String(t).toLowerCase(); if (tl === "true" || tl === "1" || tl === "t") p.value = true; else if (tl === "false" || tl === "0" || tl === "f") p.value = false; else { err = __error("expected boolean"); break; } } ` +
|
|
10
15
|
`else p.value = t; n++; }`;
|
|
11
16
|
|
|
12
17
|
/** @type {ThisType<CodeGen>} */
|
|
13
18
|
export const fmtMethods = {
|
|
19
|
+
_fmtArgJs(e) {
|
|
20
|
+
const js = this.genExpr(e);
|
|
21
|
+
const base =
|
|
22
|
+
e?._type?.kind === "named" ? (e._type.underlying ?? e._type) : e?._type;
|
|
23
|
+
return base?.kind === "slice" ? `(${js} ?? [])` : js;
|
|
24
|
+
},
|
|
25
|
+
|
|
14
26
|
_genFmt(fn, _a, expr) {
|
|
15
|
-
const fmtArgs = expr.args
|
|
27
|
+
const fmtArgs = expr.args
|
|
28
|
+
.map((e, idx) => (idx === 0 ? this.genExpr(e) : this._fmtArgJs(e)))
|
|
29
|
+
.join(", ");
|
|
16
30
|
switch (fn) {
|
|
17
31
|
case "Sprintf":
|
|
18
32
|
this.useHelper("sprintf");
|
|
@@ -42,29 +56,72 @@ export const fmtMethods = {
|
|
|
42
56
|
case "Fprint":
|
|
43
57
|
return this._genFmtFprint(fn, expr);
|
|
44
58
|
case "Sscan": {
|
|
59
|
+
this.useHelper("error");
|
|
45
60
|
const strArg = this.genExpr(expr.args[0]);
|
|
46
61
|
const restArgs = expr.args
|
|
47
62
|
.slice(1)
|
|
48
63
|
.map((e) => this.genExpr(e))
|
|
49
64
|
.join(", ");
|
|
50
|
-
return `((str, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
|
|
65
|
+
return `((str, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, err ? err : (n < ptrs.length ? __error("unexpected EOF") : null)]; })(${strArg}, ${restArgs})`;
|
|
51
66
|
}
|
|
52
67
|
case "Sscanln": {
|
|
68
|
+
this.useHelper("error");
|
|
53
69
|
const strArg = this.genExpr(expr.args[0]);
|
|
54
70
|
const restArgs = expr.args
|
|
55
71
|
.slice(1)
|
|
56
72
|
.map((e) => this.genExpr(e))
|
|
57
73
|
.join(", ");
|
|
58
|
-
return `((str, ...ptrs) => { const tokens = str.split("\\n")[0].trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
|
|
74
|
+
return `((str, ...ptrs) => { const tokens = str.split("\\n")[0].trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, err ? err : (n < ptrs.length ? __error("unexpected EOF") : null)]; })(${strArg}, ${restArgs})`;
|
|
59
75
|
}
|
|
60
76
|
case "Sscanf": {
|
|
77
|
+
this.useHelper("error");
|
|
61
78
|
const strArg = this.genExpr(expr.args[0]);
|
|
62
79
|
const fmtArg = this.genExpr(expr.args[1]);
|
|
63
80
|
const restArgs = expr.args
|
|
64
81
|
.slice(2)
|
|
65
82
|
.map((e) => this.genExpr(e))
|
|
66
83
|
.join(", ");
|
|
67
|
-
return
|
|
84
|
+
return (
|
|
85
|
+
`((str, fmt, ...ptrs) => { ` +
|
|
86
|
+
`const s = String(str); const f = String(fmt); ` +
|
|
87
|
+
`let si = 0, fi = 0; const tokens = []; let parseErr = null; ` +
|
|
88
|
+
`while (fi < f.length) { ` +
|
|
89
|
+
`if (/\\s/.test(f[fi])) { ` +
|
|
90
|
+
`while (fi < f.length && /\\s/.test(f[fi])) fi++; ` +
|
|
91
|
+
`while (si < s.length && /\\s/.test(s[si])) si++; ` +
|
|
92
|
+
`continue; ` +
|
|
93
|
+
`} ` +
|
|
94
|
+
`if (f[fi] === "%") { ` +
|
|
95
|
+
`if (fi + 1 < f.length && f[fi + 1] === "%") { ` +
|
|
96
|
+
`if (s[si] !== "%") { parseErr = __error("input does not match format"); break; } ` +
|
|
97
|
+
`si++; fi += 2; continue; ` +
|
|
98
|
+
`} ` +
|
|
99
|
+
`const vm = f.slice(fi).match(/^%[vdsfqtxXbcoeEfFgG]/); ` +
|
|
100
|
+
`if (vm) { ` +
|
|
101
|
+
`const verb = vm[0]; fi += verb.length; ` +
|
|
102
|
+
`if (verb !== "%c") { while (si < s.length && /\\s/.test(s[si])) si++; } ` +
|
|
103
|
+
`if (si >= s.length) break; ` +
|
|
104
|
+
`let tokRe = /^\\S+/; ` +
|
|
105
|
+
`if (verb === "%d" || verb === "%i") tokRe = /^[+-]?\\d+/; ` +
|
|
106
|
+
`else if (verb === "%o") tokRe = /^[+-]?(?:0[oO])?[0-7]+/; ` +
|
|
107
|
+
`else if (verb === "%b") tokRe = /^[+-]?(?:0[bB])?[01]+/; ` +
|
|
108
|
+
`else if (verb === "%f" || verb === "%F" || verb === "%e" || verb === "%E" || verb === "%g" || verb === "%G") tokRe = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?/; ` +
|
|
109
|
+
`else if (verb === "%t") tokRe = /^(?:true|false|1|0|t|f|T|F|TRUE|FALSE)/; ` +
|
|
110
|
+
`else if (verb === "%x" || verb === "%X") tokRe = /^[+-]?(?:0x)?[0-9a-fA-F]+/; ` +
|
|
111
|
+
`else if (verb === "%c") tokRe = /^[\\s\\S]/; ` +
|
|
112
|
+
`const m = s.slice(si).match(tokRe); ` +
|
|
113
|
+
`if (!m) { parseErr = __error("input does not match format"); break; } ` +
|
|
114
|
+
`tokens.push({ t: m[0], verb }); si += m[0].length; continue; ` +
|
|
115
|
+
`} ` +
|
|
116
|
+
`} ` +
|
|
117
|
+
`if (si >= s.length) break; ` +
|
|
118
|
+
`if (s[si] !== f[fi]) { parseErr = __error("input does not match format"); break; } ` +
|
|
119
|
+
`si++; fi++; ` +
|
|
120
|
+
`} ` +
|
|
121
|
+
`${_SSCAN_LOOP} ` +
|
|
122
|
+
`return [n, parseErr || err || (n < ptrs.length ? __error("unexpected EOF") : null)]; ` +
|
|
123
|
+
`})(${strArg}, ${fmtArg}, ${restArgs})`
|
|
124
|
+
);
|
|
68
125
|
}
|
|
69
126
|
default:
|
|
70
127
|
return undefined;
|
|
@@ -75,7 +132,7 @@ export const fmtMethods = {
|
|
|
75
132
|
this.useHelper("sprintf");
|
|
76
133
|
const writerArg = expr.args[0];
|
|
77
134
|
const rest = expr.args.slice(1);
|
|
78
|
-
const restJs = rest.map((e) => this.
|
|
135
|
+
const restJs = rest.map((e) => this._fmtArgJs(e)).join(", ");
|
|
79
136
|
const writerType = writerArg._type;
|
|
80
137
|
const targetTypeName =
|
|
81
138
|
writerType?.name ??
|
|
@@ -84,16 +141,16 @@ export const fmtMethods = {
|
|
|
84
141
|
if (targetTypeName === "strings.Builder") {
|
|
85
142
|
const w = this.genExpr(writerArg);
|
|
86
143
|
const base = this._unboxWriter(w);
|
|
87
|
-
return `(
|
|
144
|
+
return `((__b, __s) => { __b._buf += __s; return [__s.length, null]; })(${base}, ${sprintfCall})`;
|
|
88
145
|
}
|
|
89
146
|
if (targetTypeName === "bytes.Buffer") {
|
|
90
147
|
const w = this.genExpr(writerArg);
|
|
91
148
|
const base = this._unboxWriter(w);
|
|
92
|
-
return `((__b,__s)=>{
|
|
149
|
+
return `((__b, __s) => { const __bytes = new TextEncoder().encode(__s); for (let i = 0; i < __bytes.length; i++) __b._buf.push(__bytes[i]); return [__bytes.length, null]; })(${base}, ${sprintfCall})`;
|
|
93
150
|
}
|
|
94
151
|
// Generic io.Writer fallback — call .WriteString if available
|
|
95
152
|
const w = this.genExpr(writerArg);
|
|
96
|
-
return
|
|
153
|
+
return `((__w, __s) => typeof __w.WriteString === "function" ? __w.WriteString(__s) : __w.Write(new TextEncoder().encode(__s)))(${w}, ${sprintfCall})`;
|
|
97
154
|
},
|
|
98
155
|
|
|
99
156
|
_genStdoutWrite(strJs) {
|
|
@@ -106,7 +163,7 @@ export const fmtMethods = {
|
|
|
106
163
|
const argc = expr.args.length;
|
|
107
164
|
if (argc === 0) return JSON.stringify(suffix);
|
|
108
165
|
const fmt = Array(argc).fill("%v").join(sep) + suffix;
|
|
109
|
-
const args = expr.args.map((e) => this.
|
|
166
|
+
const args = expr.args.map((e) => this._fmtArgJs(e)).join(", ");
|
|
110
167
|
return `__sprintf(${JSON.stringify(fmt)}, ${args})`;
|
|
111
168
|
},
|
|
112
169
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/backend/js/stdlib/hex.js
|
|
2
|
+
// CodeGen for Go encoding/hex package.
|
|
3
|
+
|
|
4
|
+
export const hexMethods = {
|
|
5
|
+
_genHex(fn, a) {
|
|
6
|
+
this.useHelper("hex");
|
|
7
|
+
this.useHelper("error");
|
|
8
|
+
const args = a();
|
|
9
|
+
if (fn === "EncodeToString") return `__hex_encode_to_string(${args[0]})`;
|
|
10
|
+
if (fn === "DecodeString") return `__hex_decode_string(${args[0]})`;
|
|
11
|
+
if (fn === "Encode") return `__hex_encode(${args[0]}, ${args[1]})`;
|
|
12
|
+
if (fn === "Decode") return `__hex_decode(${args[0]}, ${args[1]})`;
|
|
13
|
+
if (fn === "EncodedLen") return `(${args[0]} * 2)`;
|
|
14
|
+
if (fn === "DecodedLen") return `Math.floor(${args[0]} / 2)`;
|
|
15
|
+
return undefined;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -12,7 +12,7 @@ export const htmlMethods = {
|
|
|
12
12
|
}
|
|
13
13
|
case "UnescapeString": {
|
|
14
14
|
const [s] = a();
|
|
15
|
-
return
|
|
15
|
+
return `(${s}).replace(/&(?:quot|apos|#39|#34|gt|lt|amp|#(?:[0-9]+|[xX][0-9a-fA-F]+));/g, m => { switch (m) { case """: case """: return '"'; case "'": case "'": return "'"; case ">": return ">"; case "<": return "<"; case "&": return "&"; default: { if (m.startsWith("&#")) { const raw = m.slice(2, -1); const cp = (raw.startsWith("x") || raw.startsWith("X")) ? parseInt(raw.slice(1), 16) : parseInt(raw, 10); return (cp >= 0 && cp <= 0x10FFFF && !(cp >= 0xD800 && cp <= 0xDFFF)) ? String.fromCodePoint(cp) : "\\uFFFD"; } return m; } } })`;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
return undefined;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
// CodeGen stdlib call generation — installed as a mixin on CodeGen.prototype.
|
|
2
2
|
// One file per Go package under ./stdlib/. This index merges them.
|
|
3
3
|
|
|
4
|
+
import { base64Methods } from "./base64.js";
|
|
5
|
+
import { binaryMethods } from "./binary.js";
|
|
4
6
|
import { bitsMethods } from "./bits.js";
|
|
5
7
|
import { builderMethods } from "./builder.js";
|
|
6
8
|
import { bytesMethods } from "./bytes.js";
|
|
7
9
|
import { errorsMethods } from "./errors.js";
|
|
8
10
|
import { fmtMethods } from "./fmt.js";
|
|
9
11
|
import { gomMethods } from "./gom.js";
|
|
12
|
+
import { hexMethods } from "./hex.js";
|
|
10
13
|
import { htmlMethods } from "./html.js";
|
|
11
14
|
import { ioMethods } from "./io.js";
|
|
12
15
|
import { mapsMethods } from "./maps.js";
|
|
@@ -15,11 +18,13 @@ import { osMethods } from "./os.js";
|
|
|
15
18
|
import { pathMethods } from "./path.js";
|
|
16
19
|
import { randMethods } from "./rand.js";
|
|
17
20
|
import { regexpMethods } from "./regexp.js";
|
|
21
|
+
import { sha256Methods } from "./sha256.js";
|
|
18
22
|
import { sharedMethods } from "./shared.js";
|
|
19
23
|
import { slicesMethods } from "./slices.js";
|
|
20
24
|
import { sortMethods } from "./sort.js";
|
|
21
25
|
import { strconvMethods } from "./strconv.js";
|
|
22
26
|
import { stringsMethods } from "./strings.js";
|
|
27
|
+
import { syncMethods } from "./sync.js";
|
|
23
28
|
import { testingMethods } from "./testing.js";
|
|
24
29
|
import { timeMethods } from "./time.js";
|
|
25
30
|
import { unicodeMethods } from "./unicode.js";
|
|
@@ -49,8 +54,14 @@ const STDLIB_METHOD_MAP = {
|
|
|
49
54
|
rand: "_genRand",
|
|
50
55
|
utf8: "_genUtf8",
|
|
51
56
|
path: "_genPath",
|
|
57
|
+
filepath: "_genPath",
|
|
52
58
|
testing: "_genTesting",
|
|
53
59
|
shared: "_genShared",
|
|
60
|
+
sync: "_genSync",
|
|
61
|
+
sha256: "_genSha256",
|
|
62
|
+
binary: "_genBinary",
|
|
63
|
+
hex: "_genHex",
|
|
64
|
+
base64: "_genBase64",
|
|
54
65
|
};
|
|
55
66
|
|
|
56
67
|
const dispatchMethods = {
|
|
@@ -103,5 +114,10 @@ export const stdlibGenMethods = {
|
|
|
103
114
|
...unicodeMethods,
|
|
104
115
|
...utf8Methods,
|
|
105
116
|
...testingMethods,
|
|
117
|
+
...syncMethods,
|
|
118
|
+
...sha256Methods,
|
|
119
|
+
...binaryMethods,
|
|
120
|
+
...hexMethods,
|
|
121
|
+
...base64Methods,
|
|
106
122
|
...dispatchMethods,
|
|
107
123
|
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
/** @type {ThisType<CodeGen>} */
|
|
6
6
|
export const ioMethods = {
|
|
7
7
|
_genIo(fn, _a, expr) {
|
|
8
|
+
if (fn === "ReadAll") this.useHelper("error");
|
|
8
9
|
switch (fn) {
|
|
9
10
|
case "WriteString": {
|
|
10
11
|
const writerArg = expr.args[0];
|
|
@@ -19,15 +20,116 @@ export const ioMethods = {
|
|
|
19
20
|
return `((b,s) => { b._buf += s; return [s.length, null]; })(${base}, ${s})`;
|
|
20
21
|
}
|
|
21
22
|
if (typeName === "bytes.Buffer") {
|
|
22
|
-
return `((b,s) => {
|
|
23
|
+
return `((b,s) => { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) b._buf.push(bytes[i]); return [bytes.length, null]; })(${base}, ${s})`;
|
|
23
24
|
}
|
|
24
25
|
// Generic: auto-dereference pointer, then dispatch on concrete writer type.
|
|
25
26
|
// strings.Builder has { _buf: string }, bytes.Buffer has { _buf: [] }.
|
|
26
|
-
return `((b,s) => { const w = b?.value ?? b; if (typeof w.WriteString === "function") return
|
|
27
|
+
return `((b,s) => { const w = b?.value ?? b; if (typeof w.WriteString === "function") return w.WriteString(s); if (typeof w._buf === "string") { w._buf += s; return [s.length, null]; } if (Array.isArray(w._buf)) { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) w._buf.push(bytes[i]); return [bytes.length, null]; } if (typeof w.Write === "function") return w.Write(new TextEncoder().encode(s)); return [0, "io.WriteString: unsupported writer"]; })(${w}, ${s})`;
|
|
27
28
|
}
|
|
28
29
|
case "ReadAll": {
|
|
30
|
+
this.useHelper("ioEOF");
|
|
29
31
|
const r = this.genExpr(expr.args[0]);
|
|
30
|
-
return `((r) => { const w = r?.value ?? r;
|
|
32
|
+
return `((r) => { const w = r?.value ?? r; const chunks = []; const buf = new Uint8Array(512); let err = null; while (!err) { const [n, e] = w.Read(buf); if (n > 0) { for (let i = 0; i < n; i++) chunks.push(buf[i]); } if (n === 0 && !e) break; err = e; } return [new Uint8Array(chunks), (err === "EOF" || err === __io_eof || err?._msg === "EOF") ? null : err]; })(${r})`;
|
|
33
|
+
}
|
|
34
|
+
case "LimitReader": {
|
|
35
|
+
this.useHelper("ioEOF");
|
|
36
|
+
const r = this.genExpr(expr.args[0]);
|
|
37
|
+
const n = this.genExpr(expr.args[1]);
|
|
38
|
+
return `((r, n) => {
|
|
39
|
+
let rem = typeof n === "bigint" ? Number(n) : Number(n);
|
|
40
|
+
const reader = r?.value ?? r;
|
|
41
|
+
return {
|
|
42
|
+
Read(buf) {
|
|
43
|
+
if (rem <= 0) return [0, __io_eof];
|
|
44
|
+
const max = buf.length > rem ? rem : buf.length;
|
|
45
|
+
const slice = buf.subarray ? buf.subarray(0, max) : buf.slice(0, max);
|
|
46
|
+
const [readN, err] = reader.Read(slice);
|
|
47
|
+
if (readN > 0) {
|
|
48
|
+
if (buf.set && slice !== buf) buf.set(slice.subarray(0, readN), 0);
|
|
49
|
+
rem -= readN;
|
|
50
|
+
}
|
|
51
|
+
return [readN, err];
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
})(${r}, ${n})`;
|
|
55
|
+
}
|
|
56
|
+
case "Copy": {
|
|
57
|
+
this.useHelper("ioEOF");
|
|
58
|
+
const dst = this.genExpr(expr.args[0]);
|
|
59
|
+
const src = this.genExpr(expr.args[1]);
|
|
60
|
+
return `((dst, src) => {
|
|
61
|
+
const w = dst?.value ?? dst;
|
|
62
|
+
const r = src?.value ?? src;
|
|
63
|
+
const writeChunk = (chunk) => {
|
|
64
|
+
if (typeof w?.Write === "function") return w.Write(chunk);
|
|
65
|
+
if (Array.isArray(w?._buf)) {
|
|
66
|
+
for (let i = 0; i < chunk.length; i++) w._buf.push(chunk[i]);
|
|
67
|
+
return [chunk.length, null];
|
|
68
|
+
}
|
|
69
|
+
if (typeof w?._buf === "string") {
|
|
70
|
+
w._buf += new TextDecoder().decode(chunk);
|
|
71
|
+
return [chunk.length, null];
|
|
72
|
+
}
|
|
73
|
+
return [0, "unsupported writer"];
|
|
74
|
+
};
|
|
75
|
+
const buf = new Uint8Array(32 * 1024);
|
|
76
|
+
let total = 0;
|
|
77
|
+
while (true) {
|
|
78
|
+
const [n, rerr] = r.Read(buf);
|
|
79
|
+
if (n > 0) {
|
|
80
|
+
const chunk = buf.subarray(0, n);
|
|
81
|
+
const [wn, werr] = writeChunk(chunk);
|
|
82
|
+
total += wn;
|
|
83
|
+
if (werr) return [total, werr];
|
|
84
|
+
}
|
|
85
|
+
if (rerr) {
|
|
86
|
+
if (rerr === "EOF" || rerr === __io_eof || rerr?._msg === "EOF") return [total, null];
|
|
87
|
+
return [total, rerr];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})(${dst}, ${src})`;
|
|
91
|
+
}
|
|
92
|
+
case "CopyN": {
|
|
93
|
+
this.useHelper("ioEOF");
|
|
94
|
+
const dst = this.genExpr(expr.args[0]);
|
|
95
|
+
const src = this.genExpr(expr.args[1]);
|
|
96
|
+
const n = this.genExpr(expr.args[2]);
|
|
97
|
+
return `((dst, src, n) => {
|
|
98
|
+
const w = dst?.value ?? dst;
|
|
99
|
+
const r = src?.value ?? src;
|
|
100
|
+
const writeChunk = (chunk) => {
|
|
101
|
+
if (typeof w?.Write === "function") return w.Write(chunk);
|
|
102
|
+
if (Array.isArray(w?._buf)) {
|
|
103
|
+
for (let i = 0; i < chunk.length; i++) w._buf.push(chunk[i]);
|
|
104
|
+
return [chunk.length, null];
|
|
105
|
+
}
|
|
106
|
+
if (typeof w?._buf === "string") {
|
|
107
|
+
w._buf += new TextDecoder().decode(chunk);
|
|
108
|
+
return [chunk.length, null];
|
|
109
|
+
}
|
|
110
|
+
return [0, "unsupported writer"];
|
|
111
|
+
};
|
|
112
|
+
let rem = typeof n === "bigint" ? Number(n) : Number(n);
|
|
113
|
+
let total = 0;
|
|
114
|
+
const buf = new Uint8Array(32 * 1024);
|
|
115
|
+
while (rem > 0) {
|
|
116
|
+
const toRead = rem < buf.length ? rem : buf.length;
|
|
117
|
+
const [rn, rerr] = r.Read(buf.subarray(0, toRead));
|
|
118
|
+
if (rn > 0) {
|
|
119
|
+
const [wn, werr] = writeChunk(buf.subarray(0, rn));
|
|
120
|
+
total += wn;
|
|
121
|
+
rem -= wn;
|
|
122
|
+
if (werr) return [total, werr];
|
|
123
|
+
}
|
|
124
|
+
if (rerr) {
|
|
125
|
+
if ((rerr === "EOF" || rerr === __io_eof || rerr?._msg === "EOF") && rem === 0) {
|
|
126
|
+
return [total, null];
|
|
127
|
+
}
|
|
128
|
+
return [total, rerr];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return [total, null];
|
|
132
|
+
})(${dst}, ${src}, ${n})`;
|
|
31
133
|
}
|
|
32
134
|
}
|
|
33
135
|
return undefined;
|
|
@@ -19,6 +19,9 @@ const MATH1 = {
|
|
|
19
19
|
Acos: "acos",
|
|
20
20
|
Exp: "exp",
|
|
21
21
|
Trunc: "trunc",
|
|
22
|
+
Sinh: "sinh",
|
|
23
|
+
Cosh: "cosh",
|
|
24
|
+
Tanh: "tanh",
|
|
22
25
|
};
|
|
23
26
|
const MATH2 = {
|
|
24
27
|
Pow: "pow",
|
|
@@ -41,7 +44,16 @@ const MATH_EXTRA = {
|
|
|
41
44
|
Copysign: ([x, y]) =>
|
|
42
45
|
`(Math.abs(${x}) * (${y} < 0 || Object.is(${y}, -0) ? -1 : 1))`,
|
|
43
46
|
Dim: ([x, y]) => `Math.max(${x} - ${y}, 0)`,
|
|
44
|
-
Remainder: ([x, y]) =>
|
|
47
|
+
Remainder: ([x, y]) =>
|
|
48
|
+
`((x, y) => { if (isNaN(x) || isNaN(y) || y === 0 || !isFinite(x)) return NaN; if (!isFinite(y)) return x; const q = x / y; const r = Math.round(q); const diff = Math.abs(q - r); const n = (diff === 0.5 && (r % 2 !== 0)) ? (r < q ? r + 1 : r - 1) : r; return x - n * y; })(${x}, ${y})`,
|
|
49
|
+
Float64bits: ([x]) =>
|
|
50
|
+
`((f) => { const b = new ArrayBuffer(8); new Float64Array(b)[0] = f; return Number(new BigUint64Array(b)[0]); })(${x})`,
|
|
51
|
+
Float64frombits: ([b]) =>
|
|
52
|
+
`((u) => { const buf = new ArrayBuffer(8); new BigUint64Array(buf)[0] = BigInt(u); return new Float64Array(buf)[0]; })(${b})`,
|
|
53
|
+
Float32bits: ([x]) =>
|
|
54
|
+
`((f) => { const b = new ArrayBuffer(4); new Float32Array(b)[0] = f; return new Uint32Array(b)[0]; })(${x})`,
|
|
55
|
+
Float32frombits: ([b]) =>
|
|
56
|
+
`((u) => { const buf = new ArrayBuffer(4); new Uint32Array(buf)[0] = Number(u) >>> 0; return new Float32Array(buf)[0]; })(${b})`,
|
|
45
57
|
};
|
|
46
58
|
|
|
47
59
|
/** @type {ThisType<CodeGen>} */
|
|
@@ -6,23 +6,37 @@ const PATH_DISPATCH = {
|
|
|
6
6
|
Base: (a) =>
|
|
7
7
|
`((p) => { if (!p) return "."; const stripped = p.replace(/\\/+$/, ""); if (!stripped) return "/"; const i = stripped.lastIndexOf("/"); return i < 0 ? stripped : stripped.slice(i + 1) || "/"; })(${a[0]})`,
|
|
8
8
|
Dir: (a) =>
|
|
9
|
-
`((p) => { const i = p.lastIndexOf("/"); if (i < 0) return ".";
|
|
9
|
+
`((p) => { const i = p.lastIndexOf("/"); if (i < 0) return "."; const res = p.slice(0, i); return res === "" ? "/" : __pathClean(res); })(${a[0]})`,
|
|
10
10
|
Ext: (a) =>
|
|
11
11
|
`((p) => { const b = p.slice(p.lastIndexOf("/") + 1); const i = b.lastIndexOf("."); return i <= 0 ? "" : b.slice(i); })(${a[0]})`,
|
|
12
12
|
IsAbs: (a) => `(${a[0]}).startsWith("/")`,
|
|
13
13
|
Split: (a) =>
|
|
14
14
|
`((p) => { const i = p.lastIndexOf("/"); return i < 0 ? ["", p] : [p.slice(0, i + 1), p.slice(i + 1)]; })(${a[0]})`,
|
|
15
15
|
Match: (a) =>
|
|
16
|
-
`((pat, name) => {
|
|
16
|
+
`((pat, name) => { const [m, err] = __pathMatch(pat, name); return [m, err ? __path_err_bad_pattern : null]; })(${a[0]}, ${a[1]})`,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
/** @type {ThisType<CodeGen>} */
|
|
20
20
|
export const pathMethods = {
|
|
21
21
|
_genPath(fn, a, expr) {
|
|
22
|
+
if (fn === "Match") {
|
|
23
|
+
this.useHelper("error");
|
|
24
|
+
this.useHelper("pathError");
|
|
25
|
+
this.useHelper("pathClean");
|
|
26
|
+
}
|
|
27
|
+
if (fn === "Dir") {
|
|
28
|
+
this.useHelper("pathClean");
|
|
29
|
+
}
|
|
22
30
|
if (fn === "Join") {
|
|
23
31
|
this.useHelper("pathClean");
|
|
24
|
-
const allArgs = expr.args
|
|
25
|
-
|
|
32
|
+
const allArgs = expr.args
|
|
33
|
+
.map((e) =>
|
|
34
|
+
e._spread || expr.ellipsis
|
|
35
|
+
? `...(${this.genExpr(e)})`
|
|
36
|
+
: this.genExpr(e),
|
|
37
|
+
)
|
|
38
|
+
.join(", ");
|
|
39
|
+
return `((arr) => arr.length === 0 ? "" : __pathClean(arr.join("/")))([${allArgs}].filter(x => x !== ""))`;
|
|
26
40
|
}
|
|
27
41
|
if (fn === "Clean") {
|
|
28
42
|
this.useHelper("pathClean");
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
5
|
const RAND_DISPATCH = {
|
|
6
|
-
Intn: (a) =>
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Intn: (a) =>
|
|
7
|
+
`((n) => { if (n <= 0) throw new Error("invalid argument to Intn"); return Math.floor(Math.random() * n); })(${a[0]})`,
|
|
8
|
+
Int63n: (a) =>
|
|
9
|
+
`((n) => { if (n <= 0) throw new Error("invalid argument to Int63n"); return Math.floor(Math.random() * n); })(${a[0]})`,
|
|
10
|
+
Int31n: (a) =>
|
|
11
|
+
`((n) => { if (n <= 0) throw new Error("invalid argument to Int31n"); return Math.floor(Math.random() * n); })(${a[0]})`,
|
|
9
12
|
Float64: () => "Math.random()",
|
|
10
13
|
Float32: () => "Math.random()",
|
|
11
14
|
Int: () => "Math.floor(Math.random() * 2147483647)",
|
|
@@ -13,14 +16,16 @@ const RAND_DISPATCH = {
|
|
|
13
16
|
Int63: () => "Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)",
|
|
14
17
|
Seed: () => "(void 0)",
|
|
15
18
|
Shuffle: (a) =>
|
|
16
|
-
`((n, f) => { for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); f(i, j); } })(${a[0]}, ${a[1]})`,
|
|
19
|
+
`((n, f) => { if (n < 0) throw new Error("invalid argument to Shuffle"); for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); f(i, j); } })(${a[0]}, ${a[1]})`,
|
|
17
20
|
Perm: (a) =>
|
|
18
|
-
`((n) => { const a = Array.from({length: n}, (_, i) => i); for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; })(${a[0]})`,
|
|
21
|
+
`((n) => { if (n < 0) throw new Error("invalid argument to Perm"); const a = Array.from({length: n}, (_, i) => i); for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; })(${a[0]})`,
|
|
22
|
+
Read: (a) => `__crypto_rand_read(${a[0]})`,
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
/** @type {ThisType<CodeGen>} */
|
|
22
26
|
export const randMethods = {
|
|
23
27
|
_genRand(fn, a) {
|
|
28
|
+
if (fn === "Read") this.useHelper("cryptoRand");
|
|
24
29
|
const gen = RAND_DISPATCH[fn];
|
|
25
30
|
return gen ? gen(a()) : undefined;
|
|
26
31
|
},
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/backend/js/stdlib/sha256.js
|
|
2
|
+
// CodeGen for Go crypto/sha256 package.
|
|
3
|
+
|
|
4
|
+
export const sha256Methods = {
|
|
5
|
+
_genSha256(fn, a) {
|
|
6
|
+
this.useHelper("sha256");
|
|
7
|
+
const args = a();
|
|
8
|
+
if (fn === "Sum256") return `__sha256.Sum256(${args[0]})`;
|
|
9
|
+
if (fn === "New") return "__sha256.New()";
|
|
10
|
+
return undefined;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -1,51 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
import { isTypedArraySlice } from "../../../typechecker/types.js";
|
|
2
2
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
5
|
const SLICES_DISPATCH = {
|
|
6
6
|
Contains: (a) => `${a[0]}.includes(${a[1]})`,
|
|
7
|
+
ContainsFunc: (a) =>
|
|
8
|
+
`((s, f) => { s = s || []; for (let i = 0; i < s.length; i++) { if (f(s[i])) return true; } return false; })(${a[0]}, ${a[1]})`,
|
|
7
9
|
Index: (a) => `${a[0]}.indexOf(${a[1]})`,
|
|
10
|
+
IndexFunc: (a) =>
|
|
11
|
+
`((s, f) => { s = s || []; for (let i = 0; i < s.length; i++) { if (f(s[i])) return i; } return -1; })(${a[0]}, ${a[1]})`,
|
|
12
|
+
BinarySearch: (a) =>
|
|
13
|
+
`((s, target) => { s = s || []; let i = 0, j = s.length; while (i < j) { const h = (i + j) >>> 1; if (s[h] < target) i = h + 1; else j = h; } return [i, i < s.length && s[i] === target]; })(${a[0]}, ${a[1]})`,
|
|
14
|
+
BinarySearchFunc: (a) =>
|
|
15
|
+
`((s, target, cmp) => { s = s || []; let i = 0, j = s.length; while (i < j) { const h = (i + j) >>> 1; if (cmp(s[h], target) < 0) i = h + 1; else j = h; } return [i, i < s.length && cmp(s[i], target) === 0]; })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
8
16
|
Compare: (a) =>
|
|
9
|
-
`((a, b) => { for (let i = 0; i < a.length && i < b.length; i++) {
|
|
10
|
-
Sort: (a) =>
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
`((a, b) => { a = a || []; b = b || []; for (let i = 0; i < a.length && i < b.length; i++) { const x = a[i], y = b[i]; const xN = typeof x === "number" && isNaN(x), yN = typeof y === "number" && isNaN(y); if (xN && yN) continue; if (xN) return -1; if (yN) return 1; if (x < y) return -1; if (x > y) return 1; } return a.length < b.length ? -1 : a.length > b.length ? 1 : 0; })(${a[0]}, ${a[1]})`,
|
|
18
|
+
Sort: (a) =>
|
|
19
|
+
`((s) => s ? s.sort((a, b) => a < b ? -1 : a > b ? 1 : 0) : null)(${a[0]})`,
|
|
20
|
+
SortFunc: (a) => `((s, f) => s ? s.sort(f) : null)(${a[0]}, ${a[1]})`,
|
|
21
|
+
SortStableFunc: (a) => `((s, f) => s ? s.sort(f) : null)(${a[0]}, ${a[1]})`,
|
|
13
22
|
IsSorted: (a) =>
|
|
14
|
-
`((s) => { for (let i =
|
|
23
|
+
`((s) => { s = s || []; for (let i = 0; i < s.length; i++) { if (typeof s[i] === "number" && isNaN(s[i])) return false; if (i > 0 && s[i] < s[i-1]) return false; } return true; })(${a[0]})`,
|
|
15
24
|
IsSortedFunc: (a) =>
|
|
16
|
-
`((s, f) => { for (let i = 1; i < s.length; i++) { if (f(s[i], s[i-1]) < 0) return false; } return true; })(${a[0]}, ${a[1]})`,
|
|
17
|
-
Reverse: (a) =>
|
|
18
|
-
Max: (a) =>
|
|
19
|
-
|
|
25
|
+
`((s, f) => { s = s || []; for (let i = 1; i < s.length; i++) { if (f(s[i], s[i-1]) < 0) return false; } return true; })(${a[0]}, ${a[1]})`,
|
|
26
|
+
Reverse: (a) => `((s) => s ? s.reverse() : null)(${a[0]})`,
|
|
27
|
+
Max: (a) =>
|
|
28
|
+
`((s) => { if (!s || s.length === 0) throw new Error("slices.Max: empty list"); let m = s[0]; for (let i = 1; i < s.length; i++) { const x = s[i]; if ((typeof x === "number" && isNaN(x)) || x > m || (x === 0 && m === 0 && Object.is(m, -0) && !Object.is(x, -0))) m = x; } return m; })(${a[0]})`,
|
|
29
|
+
Min: (a) =>
|
|
30
|
+
`((s) => { if (!s || s.length === 0) throw new Error("slices.Min: empty list"); let m = s[0]; for (let i = 1; i < s.length; i++) { const x = s[i]; if ((typeof x === "number" && isNaN(x)) || x < m || (x === 0 && m === 0 && Object.is(x, -0))) m = x; } return m; })(${a[0]})`,
|
|
20
31
|
MaxFunc: (a) =>
|
|
21
|
-
`((s, f) => s.reduce((m, x) => f(x, m) > 0 ? x : m))(${a[0]}, ${a[1]})`,
|
|
32
|
+
`((s, f) => { if (!s || s.length === 0) throw new Error("slices.MaxFunc: empty list"); return s.reduce((m, x) => f(x, m) > 0 ? x : m); })(${a[0]}, ${a[1]})`,
|
|
22
33
|
MinFunc: (a) =>
|
|
23
|
-
`((s, f) => s.reduce((m, x) => f(x, m) < 0 ? x : m))(${a[0]}, ${a[1]})`,
|
|
24
|
-
Clone: (a) =>
|
|
34
|
+
`((s, f) => { if (!s || s.length === 0) throw new Error("slices.MinFunc: empty list"); return s.reduce((m, x) => f(x, m) < 0 ? x : m); })(${a[0]}, ${a[1]})`,
|
|
35
|
+
Clone: (a) => `((s) => s ? s.slice() : null)(${a[0]})`,
|
|
25
36
|
Compact: (a) =>
|
|
26
|
-
`((s) => s.
|
|
37
|
+
`((s) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (s[i] !== s[k - 1]) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]})`,
|
|
27
38
|
CompactFunc: (a) =>
|
|
28
|
-
`((s, f) => s.
|
|
29
|
-
Concat: (a) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
`((s, f) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (!f(s[i], s[k - 1])) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
40
|
+
Concat: (a) =>
|
|
41
|
+
a.length === 0
|
|
42
|
+
? "null"
|
|
43
|
+
: `((...slices) => { const nonNull = slices.filter(Boolean); if (nonNull.length === 0) return slices[0] === null ? null : []; if (ArrayBuffer.isView(nonNull[0])) { const totalLen = nonNull.reduce((sum, s) => sum + s.length, 0); const out = new nonNull[0].constructor(totalLen); let off = 0; for (const s of nonNull) { out.set(s, off); off += s.length; } return out; } return [].concat(...slices.map(s => s ? (ArrayBuffer.isView(s) ? Array.from(s) : s) : [])); })(${a.map((x) => `(${x})`).join(", ")})`,
|
|
44
|
+
Delete: (a) =>
|
|
45
|
+
`((s, i, j) => { if (!s && i === 0 && j === 0) return s; s = s || []; if (i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { s.copyWithin(i, j); return s.subarray(0, s.length - (j - i)); } s.splice(i, j - i); return s; })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
46
|
+
DeleteFunc: (a) =>
|
|
47
|
+
`((s, f) => { if (!s || s.length === 0) return s; let k = 0; for (let i = 0; i < s.length; i++) { if (!f(s[i])) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
48
|
+
Insert: (a, isTyped) => {
|
|
49
|
+
const items = a.slice(2);
|
|
50
|
+
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
51
|
+
return `((s, i, ...v) => { if (!s && i === 0) s = ${nilInit}; if (!s || i < 0 || i > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(i), i + v.length); return res; } s.splice(i, 0, ...v); return s; })(${a[0]}, ${a[1]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
52
|
+
},
|
|
53
|
+
Replace: (a, isTyped) => {
|
|
54
|
+
const items = a.slice(3);
|
|
55
|
+
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
56
|
+
return `((s, i, j, ...v) => { if (!s && i === 0 && j === 0) s = ${nilInit}; if (!s || i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length - (j - i) + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(j), i + v.length); return res; } s.splice(i, j - i, ...v); return s; })(${a[0]}, ${a[1]}, ${a[2]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
57
|
+
},
|
|
58
|
+
Grow: (a, isTyped) => {
|
|
59
|
+
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
60
|
+
return `((s, n) => { if (n < 0) throw new Error("runtime error: makeslice: len out of range"); if (!s) return ${nilInit}; return s.slice(); })(${a[0]}, ${a[1]})`;
|
|
61
|
+
},
|
|
62
|
+
Clip: (a) => `((s) => s ? s.slice() : null)(${a[0]})`,
|
|
38
63
|
};
|
|
39
64
|
|
|
40
65
|
/** @type {ThisType<CodeGen>} */
|
|
41
66
|
export const slicesMethods = {
|
|
42
|
-
_genSlices(fn, a) {
|
|
67
|
+
_genSlices(fn, a, expr) {
|
|
43
68
|
if (fn === "Equal") {
|
|
44
69
|
this.useHelper("equal");
|
|
45
70
|
const [a1, b1] = a();
|
|
46
71
|
return `__equal(${a1}, ${b1})`;
|
|
47
72
|
}
|
|
73
|
+
const isTyped = isTypedArraySlice(expr?.args?.[0]?._type);
|
|
48
74
|
const gen = SLICES_DISPATCH[fn];
|
|
49
|
-
return gen ? gen(a()) : undefined;
|
|
75
|
+
return gen ? gen(a(), isTyped) : undefined;
|
|
50
76
|
},
|
|
51
77
|
};
|