gofront 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/package.json +10 -38
- package/src/backend/js/expressions.js +2060 -389
- package/src/backend/js/index.js +586 -174
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +936 -1644
- package/src/backend/js/statements.js +1349 -132
- package/src/backend/js/stdlib/index.js +51 -94
- package/src/backend/js/templ.js +67 -118
- package/src/backend/js/type-info.js +436 -0
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +80 -0
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +753 -872
- package/src/backend/wasm/emit-builtins.js +914 -237
- package/src/backend/wasm/emit-exprs.js +1456 -195
- package/src/backend/wasm/emit-maps.js +78 -380
- package/src/backend/wasm/emit-stmts.js +1659 -214
- package/src/backend/wasm/emit.js +614 -88
- package/src/backend/wasm/encode.js +43 -13
- package/src/backend/wasm/globals.js +491 -0
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +406 -3195
- package/src/backend/wasm/method-expr.js +392 -0
- package/src/backend/wasm/module-emitter.js +1615 -0
- package/src/backend/wasm/monomorph.js +164 -9
- package/src/backend/wasm/natives.js +596 -0
- package/src/backend/wasm/prescan.js +249 -0
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -37
- package/src/backend/wasm/stdlib/simd.js +293 -28
- package/src/backend/wasm/types.js +260 -27
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +47 -20
- package/src/{cli-core.js → cli/cli-core.js} +241 -11
- package/src/{test-runner.js → cli/test-runner.js} +188 -122
- package/src/{vendor.js → cli/vendor.js} +3 -4
- package/src/compiler.js +202 -386
- package/src/index.js +15 -169
- package/src/{lexer.js → lexer/lexer.js} +203 -62
- package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
- package/src/{tokens.js → lexer/tokens.js} +2 -0
- package/src/link/sourcemap.js +97 -0
- package/src/link/stdlib.js +737 -0
- package/src/link/type-names.js +148 -0
- package/src/link/wasm.js +318 -0
- package/src/lower/bounds.js +547 -0
- package/src/lower/boxing.js +1 -1
- package/src/lower/captures.js +267 -64
- package/src/lower/embedding.js +32 -3
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +905 -0
- package/src/lower/functions.js +2 -0
- package/src/lower/gen-types.js +274 -0
- package/src/lower/index.js +33 -19
- package/src/lower/json-codecs.js +1379 -0
- package/src/lower/ownership.js +47 -8
- package/src/lower/range.js +86 -1
- package/src/lower/reachability.js +150 -0
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +83 -15
- package/src/parser/expressions.js +110 -18
- package/src/parser/index.js +2 -1
- package/src/parser/statements.js +38 -22
- package/src/{templ-parser.js → parser/templ.js} +179 -17
- package/src/parser/types.js +70 -9
- package/src/resolver.js +21 -1
- package/src/typechecker/assignability.js +291 -19
- package/src/typechecker/const-fold.js +399 -0
- package/src/typechecker/constants.js +282 -0
- package/src/typechecker/expressions.js +1220 -183
- package/src/typechecker/index.js +659 -92
- package/src/typechecker/init-order.js +426 -0
- package/src/typechecker/operand-text.js +40 -0
- package/src/typechecker/resolve.js +613 -62
- package/src/typechecker/statements.js +212 -20
- package/src/typechecker/stdlib/excluded.js +902 -0
- package/src/typechecker/stdlib/index.js +38 -0
- package/src/typechecker/stdlib/simd.js +65 -15
- package/src/typechecker/termination.js +11 -2
- package/src/typechecker/types.js +268 -514
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/cmp/cmp.go +65 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/errors.go +31 -0
- package/stdlib/encoding/json/indent.go +71 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/encoding/json/number.go +12 -0
- package/stdlib/encoding/json/stream.go +173 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/hash/hash.go +53 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +871 -0
- package/stdlib/internal/jsonrt/enc.go +516 -0
- package/stdlib/internal/jsonrt/indent.go +135 -0
- package/stdlib/internal/jsonrt/number.go +27 -0
- package/stdlib/internal/jsonrt/reader.go +73 -0
- package/stdlib/internal/jsonrt/scanner.go +658 -0
- package/stdlib/io/io.go +502 -0
- package/stdlib/iter/iter.go +18 -0
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +272 -0
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +500 -0
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +526 -0
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +250 -0
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -46
- package/src/backend/js/stdlib/builder.js +0 -63
- package/src/backend/js/stdlib/bytes.js +0 -122
- package/src/backend/js/stdlib/errors.js +0 -44
- package/src/backend/js/stdlib/fmt.js +0 -178
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -972
- package/src/backend/js/stdlib/maps.js +0 -45
- package/src/backend/js/stdlib/math.js +0 -69
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -24
- package/src/backend/js/stdlib/slices.js +0 -77
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -74
- package/src/backend/js/stdlib/strings.js +0 -222
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -34
- package/src/backend/js/stdlib/time.js +0 -128
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/const-fold.js +0 -205
- package/src/backend/wasm/emit-stdlib.js +0 -13
- package/src/backend/wasm/stdlib/bytes.js +0 -5039
- package/src/backend/wasm/stdlib/core.js +0 -8903
- package/src/backend/wasm/stdlib/io.js +0 -2161
- package/src/backend/wasm/stdlib/packages.js +0 -2400
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -1200
- package/src/typechecker/stdlib/core.js +0 -801
- package/src/typechecker/stdlib/extended.js +0 -914
- package/src/typechecker/stdlib.js +0 -22
- /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
- /package/src/{colors.js → cli/colors.js} +0 -0
- /package/src/{dev-server.js → cli/dev-server.js} +0 -0
- /package/src/{minifier.js → cli/minifier.js} +0 -0
- /package/src/{project-config.js → cli/project-config.js} +0 -0
- /package/src/{pwa.js → cli/pwa.js} +0 -0
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// src/backend/js/stdlib/base64.js
|
|
2
|
-
// CodeGen for Go encoding/base64 package.
|
|
3
|
-
|
|
4
|
-
export const base64Methods = {
|
|
5
|
-
_genBase64(fn, a) {
|
|
6
|
-
this.useHelper("base64");
|
|
7
|
-
this.useHelper("error");
|
|
8
|
-
const args = a();
|
|
9
|
-
if (fn === "NewEncoding") return `__base64_make(${args[0]}, "=")`;
|
|
10
|
-
return undefined;
|
|
11
|
-
},
|
|
12
|
-
};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
// src/backend/js/stdlib/binary.js
|
|
2
|
-
// CodeGen for Go encoding/binary package.
|
|
3
|
-
|
|
4
|
-
function sizeOfGoType(gt) {
|
|
5
|
-
if (!gt) return -1;
|
|
6
|
-
if (gt.kind === "basic") {
|
|
7
|
-
switch (gt.name) {
|
|
8
|
-
case "bool":
|
|
9
|
-
case "int8":
|
|
10
|
-
case "uint8":
|
|
11
|
-
case "byte":
|
|
12
|
-
return 1;
|
|
13
|
-
case "int16":
|
|
14
|
-
case "uint16":
|
|
15
|
-
return 2;
|
|
16
|
-
case "int32":
|
|
17
|
-
case "uint32":
|
|
18
|
-
case "float32":
|
|
19
|
-
case "rune":
|
|
20
|
-
return 4;
|
|
21
|
-
case "int64":
|
|
22
|
-
case "uint64":
|
|
23
|
-
case "float64":
|
|
24
|
-
case "int":
|
|
25
|
-
case "uint":
|
|
26
|
-
case "uintptr":
|
|
27
|
-
return 8;
|
|
28
|
-
default:
|
|
29
|
-
return -1;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (gt.kind === "array" || gt.kind === "ArrayType") {
|
|
33
|
-
const es = sizeOfGoType(gt.elem);
|
|
34
|
-
const len = gt.len ?? gt.size ?? 0;
|
|
35
|
-
return es > 0 ? es * len : -1;
|
|
36
|
-
}
|
|
37
|
-
if (
|
|
38
|
-
gt.kind === "pointer" ||
|
|
39
|
-
gt.kind === "PointerType" ||
|
|
40
|
-
gt.kind === "StarExpr"
|
|
41
|
-
) {
|
|
42
|
-
return sizeOfGoType(gt.base ?? gt.expr ?? gt.operand);
|
|
43
|
-
}
|
|
44
|
-
if (gt.kind === "struct" || gt.kind === "StructType") {
|
|
45
|
-
let total = 0;
|
|
46
|
-
if (gt.fields instanceof Map) {
|
|
47
|
-
for (const fType of gt.fields.values()) {
|
|
48
|
-
const s = sizeOfGoType(fType);
|
|
49
|
-
if (s < 0) return -1;
|
|
50
|
-
total += s;
|
|
51
|
-
}
|
|
52
|
-
return total;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return -1;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const binaryMethods = {
|
|
59
|
-
_genBinary(fn, a, expr) {
|
|
60
|
-
this.useHelper("binary");
|
|
61
|
-
this.useHelper("error");
|
|
62
|
-
const args = a();
|
|
63
|
-
if (fn === "Read") {
|
|
64
|
-
const targetType = expr?.args?.[2]?._type;
|
|
65
|
-
const baseType = targetType?.base ?? targetType;
|
|
66
|
-
const resolved =
|
|
67
|
-
baseType?.kind === "named"
|
|
68
|
-
? (baseType.underlying ?? baseType)
|
|
69
|
-
: baseType;
|
|
70
|
-
const sz = sizeOfGoType(resolved);
|
|
71
|
-
const typeTag =
|
|
72
|
-
resolved?.name ??
|
|
73
|
-
(resolved?.kind === "basic" ? resolved.name : (baseType?.name ?? ""));
|
|
74
|
-
return `__binary_read(${args[0]}, ${args[1]}, ${args[2]}${sz > 0 ? `, ${sz}` : ", 0"}, "${typeTag}")`;
|
|
75
|
-
}
|
|
76
|
-
if (fn === "Write") {
|
|
77
|
-
const targetType = expr?.args?.[2]?._type;
|
|
78
|
-
const baseType = targetType?.base ?? targetType;
|
|
79
|
-
const resolved =
|
|
80
|
-
baseType?.kind === "named"
|
|
81
|
-
? (baseType.underlying ?? baseType)
|
|
82
|
-
: baseType;
|
|
83
|
-
const sz = sizeOfGoType(resolved);
|
|
84
|
-
const typeTag =
|
|
85
|
-
resolved?.name ??
|
|
86
|
-
(resolved?.kind === "basic" ? resolved.name : (baseType?.name ?? ""));
|
|
87
|
-
return `__binary_write(${args[0]}, ${args[1]}, ${args[2]}${sz > 0 ? `, ${sz}` : ", 0"}, "${typeTag}")`;
|
|
88
|
-
}
|
|
89
|
-
if (fn === "Size") {
|
|
90
|
-
const sz = sizeOfGoType(expr?.args?.[0]?._type);
|
|
91
|
-
if (sz >= 0) return `${sz}`;
|
|
92
|
-
return `__binary_size(${args[0]})`;
|
|
93
|
-
}
|
|
94
|
-
if (fn === "AppendUint16")
|
|
95
|
-
return `__binary_le.AppendUint16(${args[0]}, ${args[1]})`;
|
|
96
|
-
if (fn === "AppendUint32")
|
|
97
|
-
return `__binary_le.AppendUint32(${args[0]}, ${args[1]})`;
|
|
98
|
-
if (fn === "AppendUint64")
|
|
99
|
-
return `__binary_le.AppendUint64(${args[0]}, ${args[1]})`;
|
|
100
|
-
return undefined;
|
|
101
|
-
},
|
|
102
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// src/backend/js/stdlib/bits.js
|
|
2
|
-
// CodeGen for Go `math/bits` package.
|
|
3
|
-
|
|
4
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
5
|
-
|
|
6
|
-
const BITS_MAP = {
|
|
7
|
-
LeadingZeros32: ([x]) => `Math.clz32((${x}) >>> 0)`,
|
|
8
|
-
TrailingZeros32: ([x]) =>
|
|
9
|
-
`((() => { const v = (${x}) >>> 0; return v === 0 ? 32 : 31 - Math.clz32(v & -v); })())`,
|
|
10
|
-
OnesCount32: ([x]) =>
|
|
11
|
-
`((() => { let v = (${x}) >>> 0; v = v - ((v >>> 1) & 0x55555555); v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); return (Math.imul((v + (v >>> 4)) & 0x0f0f0f0f, 0x01010101)) >>> 24; })())`,
|
|
12
|
-
RotateLeft32: ([x, k]) =>
|
|
13
|
-
`((() => { 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
|
-
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)))); })())`,
|
|
23
|
-
|
|
24
|
-
Len32: ([x]) => `((v => 32 - Math.clz32(v >>> 0))(${x}))`,
|
|
25
|
-
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)); })())`,
|
|
27
|
-
ReverseBytes16: ([x]) =>
|
|
28
|
-
`((v => ((v & 0xff) << 8) | ((v >>> 8) & 0xff))((${x}) & 0xffff))`,
|
|
29
|
-
ReverseBytes32: ([x]) =>
|
|
30
|
-
`((v => (((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v >>> 8) & 0xff00) | ((v >>> 24) & 0xff)) >>> 0)((${x}) >>> 0))`,
|
|
31
|
-
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))); })())`,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/** @type {ThisType<CodeGen>} */
|
|
40
|
-
export const bitsMethods = {
|
|
41
|
-
_genBits(fn, a) {
|
|
42
|
-
const args = a();
|
|
43
|
-
const gen = BITS_MAP[fn];
|
|
44
|
-
return gen ? gen(args) : undefined;
|
|
45
|
-
},
|
|
46
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
// CodeGen for `strings.Builder` and `bytes.Buffer` method calls.
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
|
-
|
|
5
|
-
const BUILDER_STR = {
|
|
6
|
-
WriteString: (b, a) =>
|
|
7
|
-
`((__s) => { ${b}._buf += __s; return [new TextEncoder().encode(__s).length, null]; })(${a[0]})`,
|
|
8
|
-
WriteByte: (b, a) => `(${b}._buf += String.fromCodePoint(${a[0]}), null)`,
|
|
9
|
-
WriteRune: (b, a) =>
|
|
10
|
-
`((cp) => { const r = (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) ? 0xfffd : cp; const s = String.fromCodePoint(r); ${b}._buf += s; return [new TextEncoder().encode(s).length, null]; })(${a[0]})`,
|
|
11
|
-
Write: (b, a) =>
|
|
12
|
-
`(${b}._buf += new TextDecoder().decode(new Uint8Array(${a[0]})), [${a[0]}.length, null])`,
|
|
13
|
-
String: (b) => `${b}._buf`,
|
|
14
|
-
Reset: (b) => `(${b}._buf = "")`,
|
|
15
|
-
Len: (b) => `new TextEncoder().encode(${b}._buf).length`,
|
|
16
|
-
Cap: (b) =>
|
|
17
|
-
`Math.max(${b}._cap ?? 0, new TextEncoder().encode(${b}._buf).length)`,
|
|
18
|
-
Grow: (b, a) =>
|
|
19
|
-
`((n) => { if (n < 0) throw new Error("strings.Builder.Grow: negative count"); ${b}._cap = Math.max(${b}._cap ?? 0, new TextEncoder().encode(${b}._buf).length) + n; })(${a[0]})`,
|
|
20
|
-
};
|
|
21
|
-
const BUILDER_BYTES = {
|
|
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)`,
|
|
25
|
-
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
|
-
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
|
-
String: (b) => `new TextDecoder().decode(new Uint8Array(${b}._buf))`,
|
|
30
|
-
Reset: (b) => `(${b}._buf = [])`,
|
|
31
|
-
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
|
-
};
|
|
34
|
-
const BUILDER_COMMON = {
|
|
35
|
-
Bytes: (b) => `new Uint8Array(${b}._buf)`,
|
|
36
|
-
Len: (b) => `${b}._buf.length`,
|
|
37
|
-
Cap: (b) => `Math.max(${b}._cap ?? 0, ${b}._buf.length)`,
|
|
38
|
-
Grow: (b, a) =>
|
|
39
|
-
`((n) => { if (n < 0) throw new Error("bytes.Buffer.Grow: negative count"); ${b}._cap = Math.max(${b}._cap ?? 0, ${b}._buf.length) + n; })(${a[0]})`,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/** @type {ThisType<CodeGen>} */
|
|
43
|
-
export const builderMethods = {
|
|
44
|
-
_genBuilderCall(typeName, method, expr) {
|
|
45
|
-
const recv = expr.func.expr;
|
|
46
|
-
const base = this._unboxWriter(this.genExpr(recv));
|
|
47
|
-
const args = expr.args.map((a) => this.genExpr(a));
|
|
48
|
-
if (method === "Read") {
|
|
49
|
-
this.useHelper("ioEOF");
|
|
50
|
-
this.useHelper("error");
|
|
51
|
-
}
|
|
52
|
-
const isStr = typeName === "strings.Builder";
|
|
53
|
-
const table = isStr ? BUILDER_STR : BUILDER_BYTES;
|
|
54
|
-
const gen = table[method] ?? BUILDER_COMMON[method];
|
|
55
|
-
return gen ? gen(base, args) : undefined;
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
// Accepts a Builder/Buffer or a pointer box around one; evaluates `js` once.
|
|
59
|
-
_unboxWriter(js) {
|
|
60
|
-
if (/^[\w$.]+$/.test(js)) return `(${js}?.value ?? ${js})`;
|
|
61
|
-
return `((__w) => __w?.value ?? __w)(${js})`;
|
|
62
|
-
},
|
|
63
|
-
};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
// CodeGen for Go `bytes` package.
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
|
-
|
|
5
|
-
const __bs = `(b => typeof TextDecoder !== "undefined" ? new TextDecoder().decode(b instanceof Uint8Array ? b : new Uint8Array(b)) : String.fromCharCode.apply(null, b))`;
|
|
6
|
-
const __sb = `(s => typeof TextEncoder !== "undefined" ? new TextEncoder().encode(s) : new Uint8Array([...s].map(c => c.charCodeAt(0))))`;
|
|
7
|
-
|
|
8
|
-
const BYTES_DISPATCH = {
|
|
9
|
-
Contains: (a) => `${__bs}(${a[0]}).includes(${__bs}(${a[1]}))`,
|
|
10
|
-
HasPrefix: (a) =>
|
|
11
|
-
`((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
|
-
HasSuffix: (a) =>
|
|
13
|
-
`((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]}))`,
|
|
15
|
-
Count: (a) =>
|
|
16
|
-
`((b, sep) => sep.length === 0 ? b.length + 1 : ${__bs}(b).split(${__bs}(sep)).length - 1)(${a[0]}, ${a[1]})`,
|
|
17
|
-
Repeat: (a) => `${__sb}(${__bs}(${a[0]}).repeat(${a[1]}))`,
|
|
18
|
-
Replace: (a) =>
|
|
19
|
-
`((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]})`,
|
|
20
|
-
ToUpper: (a) =>
|
|
21
|
-
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toUpperCase())`,
|
|
22
|
-
ToLower: (a) =>
|
|
23
|
-
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toLowerCase())`,
|
|
24
|
-
ToTitle: (a) =>
|
|
25
|
-
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toUpperCase())`,
|
|
26
|
-
TrimSpace: (a) =>
|
|
27
|
-
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).trim())`,
|
|
28
|
-
Trim: (a) =>
|
|
29
|
-
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && cs.has(chars[l])) l++; while (r > l && cs.has(chars[r - 1])) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
30
|
-
Equal: (a) =>
|
|
31
|
-
`((a, b) => { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false; return true; })(${a[0]}, ${a[1]})`,
|
|
32
|
-
Split: (a) => `${__bs}(${a[0]}).split(${__bs}(${a[1]})).map(p => ${__sb}(p))`,
|
|
33
|
-
Join: (a) => `${__sb}(${a[0]}.map(p => ${__bs}(p)).join(${__bs}(${a[1]})))`,
|
|
34
|
-
ReplaceAll: (a) =>
|
|
35
|
-
`((b, o, n) => { const r = []; let i = 0; while (i <= b.length - o.length) { if (o.length > 0 && o.every((v, j) => b[i + j] === v)) { r.push(...n); i += o.length; } else { r.push(b[i++]); } } for (; i < b.length; i++) r.push(b[i]); return new Uint8Array(r); })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
36
|
-
TrimPrefix: (a) =>
|
|
37
|
-
`((b, p) => p.every((v, i) => b[i] === v) ? b.slice(p.length) : b.slice())(${a[0]}, ${a[1]})`,
|
|
38
|
-
TrimSuffix: (a) =>
|
|
39
|
-
`((b, s) => s.length && s.every((v, i) => b[b.length - s.length + i] === v) ? b.slice(0, -s.length) : b.slice())(${a[0]}, ${a[1]})`,
|
|
40
|
-
TrimLeft: (a) =>
|
|
41
|
-
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && cs.has(chars[l])) l++; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
42
|
-
TrimRight: (a) =>
|
|
43
|
-
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (r > l && cs.has(chars[r - 1])) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
44
|
-
TrimFunc: (a) =>
|
|
45
|
-
`((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
|
-
IndexByte: (a) => `(${a[0]}).indexOf(${a[1]})`,
|
|
47
|
-
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]})`,
|
|
49
|
-
LastIndexByte: (a) => `(${a[0]}).lastIndexOf(${a[1]})`,
|
|
50
|
-
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]})`,
|
|
52
|
-
FieldsFunc: (a) =>
|
|
53
|
-
`((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
|
-
Clone: (a) =>
|
|
55
|
-
`(${a[0]} ? (${a[0]}.slice ? ${a[0]}.slice() : Array.from(${a[0]})) : null)`,
|
|
56
|
-
Cut: (a) =>
|
|
57
|
-
`((b, sep) => { for (let i = 0; i <= b.length - sep.length; i++) if (sep.every((v, j) => b[i + j] === v)) return [b.slice(0, i), b.slice(i + sep.length), true]; return [b.slice(), new Uint8Array(0), false]; })(${a[0]}, ${a[1]})`,
|
|
58
|
-
ContainsAny: (a) =>
|
|
59
|
-
`((b, chars) => { const s = new TextDecoder().decode(new Uint8Array(b)); for (const c of chars) if (s.includes(c)) return true; return false; })(${a[0]}, ${a[1]})`,
|
|
60
|
-
ContainsRune: (a) =>
|
|
61
|
-
`((b, r) => { const s = new TextDecoder().decode(new Uint8Array(b)); return s.includes(String.fromCodePoint(r < 0 || r > 0x10ffff || (r >= 0xd800 && r <= 0xdfff) ? 0xfffd : r)); })(${a[0]}, ${a[1]})`,
|
|
62
|
-
Map: (a) =>
|
|
63
|
-
`((f, b) => { const s = new TextDecoder().decode(new Uint8Array(b)); let res = ""; for (const c of s) { const r = f(c.codePointAt(0)); if (r >= 0) res += String.fromCodePoint(r); } return new TextEncoder().encode(res); })(${a[0]}, ${a[1]})`,
|
|
64
|
-
SplitN: (a) =>
|
|
65
|
-
`((b, sep, n) => {
|
|
66
|
-
if (n === 0) return null;
|
|
67
|
-
if (sep.length === 0) {
|
|
68
|
-
if (n < 0 || b.length <= n) {
|
|
69
|
-
const r = [];
|
|
70
|
-
for (let k = 0; k < b.length; k++) r.push(b.slice(k, k + 1));
|
|
71
|
-
return r;
|
|
72
|
-
}
|
|
73
|
-
const r = [];
|
|
74
|
-
for (let k = 0; k < n - 1; k++) r.push(b.slice(k, k + 1));
|
|
75
|
-
r.push(b.slice(n - 1));
|
|
76
|
-
return r;
|
|
77
|
-
}
|
|
78
|
-
const findNext = (start) => {
|
|
79
|
-
for (let k = start; k <= b.length - sep.length; k++) {
|
|
80
|
-
let match = true;
|
|
81
|
-
for (let l = 0; l < sep.length; l++) {
|
|
82
|
-
if (b[k + l] !== sep[l]) { match = false; break; }
|
|
83
|
-
}
|
|
84
|
-
if (match) return k;
|
|
85
|
-
}
|
|
86
|
-
return -1;
|
|
87
|
-
};
|
|
88
|
-
if (n < 0) {
|
|
89
|
-
const r = [];
|
|
90
|
-
let i = 0;
|
|
91
|
-
while (i <= b.length) {
|
|
92
|
-
const j = findNext(i);
|
|
93
|
-
if (j < 0) break;
|
|
94
|
-
r.push(b.slice(i, j));
|
|
95
|
-
i = j + sep.length;
|
|
96
|
-
}
|
|
97
|
-
r.push(b.slice(i));
|
|
98
|
-
return r;
|
|
99
|
-
}
|
|
100
|
-
const r = [];
|
|
101
|
-
let i = 0;
|
|
102
|
-
for (let c = 1; c < n; c++) {
|
|
103
|
-
const j = findNext(i);
|
|
104
|
-
if (j < 0) break;
|
|
105
|
-
r.push(b.slice(i, j));
|
|
106
|
-
i = j + sep.length;
|
|
107
|
-
}
|
|
108
|
-
r.push(b.slice(i));
|
|
109
|
-
return r;
|
|
110
|
-
})(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
111
|
-
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]})`,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/** @type {ThisType<CodeGen>} */
|
|
116
|
-
export const bytesMethods = {
|
|
117
|
-
_genBytes(fn, a) {
|
|
118
|
-
if (fn === "NewReader") this.useHelper("ioEOF");
|
|
119
|
-
const gen = BYTES_DISPATCH[fn];
|
|
120
|
-
return gen ? gen(a()) : undefined;
|
|
121
|
-
},
|
|
122
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// CodeGen for Go `errors` package.
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
|
-
|
|
5
|
-
/** @type {ThisType<CodeGen>} */
|
|
6
|
-
export const errorsMethods = {
|
|
7
|
-
_genErrors(fn, a, expr) {
|
|
8
|
-
const args = a();
|
|
9
|
-
if (fn === "New") {
|
|
10
|
-
this.useHelper("error");
|
|
11
|
-
return `__error(${args[0]})`;
|
|
12
|
-
}
|
|
13
|
-
if (fn === "Is") {
|
|
14
|
-
this.useHelper("errorIs");
|
|
15
|
-
return `__errorIs(${args[0]}, ${args[1]})`;
|
|
16
|
-
}
|
|
17
|
-
if (fn === "Unwrap") return `(${args[0]}?._cause ?? null)`;
|
|
18
|
-
if (fn === "As") {
|
|
19
|
-
this.useHelper("errorAs");
|
|
20
|
-
const targetGoType = expr?.args?.[1]?._type;
|
|
21
|
-
const baseGoType = targetGoType?.base ?? targetGoType;
|
|
22
|
-
const concreteGoType = baseGoType?.base ?? baseGoType;
|
|
23
|
-
const typeName = concreteGoType?.name;
|
|
24
|
-
if (concreteGoType?.kind === "interface" || typeName === "error") {
|
|
25
|
-
return `__errorAs(${args[0]}, ${args[1]}, (x) => x !== null && (typeof x === "object" ? typeof x.Error === "function" : true))`;
|
|
26
|
-
}
|
|
27
|
-
// Named non-struct error types sit in interfaces as boxes; store the raw value.
|
|
28
|
-
const namedBox = this._namedBoxInfo(concreteGoType);
|
|
29
|
-
if (namedBox) {
|
|
30
|
-
return `__errorAs(${args[0]}, ${args[1]}, (x) => x instanceof ${namedBox.cls}, (x) => x.__gfUnbox())`;
|
|
31
|
-
}
|
|
32
|
-
if (typeName) {
|
|
33
|
-
return `__errorAs(${args[0]}, ${args[1]}, (x) => (typeof ${typeName} === "function" && x instanceof ${typeName}) || x?.constructor?.name === "${typeName}" || x?.__struct === "${typeName}")`;
|
|
34
|
-
}
|
|
35
|
-
return `__errorAs(${args[0]}, ${args[1]})`;
|
|
36
|
-
}
|
|
37
|
-
if (fn === "Join") {
|
|
38
|
-
this.useHelper("error");
|
|
39
|
-
this.useHelper("errorJoin");
|
|
40
|
-
return `__errorJoin(${args.join(", ")})`;
|
|
41
|
-
}
|
|
42
|
-
return undefined;
|
|
43
|
-
},
|
|
44
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// CodeGen for Go `fmt` package — installed onto CodeGen.prototype via stdlibGenMethods.
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
|
-
|
|
5
|
-
const _SSCAN_LOOP =
|
|
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; } } ` +
|
|
15
|
-
`else p.value = t; n++; }`;
|
|
16
|
-
|
|
17
|
-
/** @type {ThisType<CodeGen>} */
|
|
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
|
-
|
|
26
|
-
_genFmt(fn, _a, expr) {
|
|
27
|
-
const fmtArgs = expr.args
|
|
28
|
-
.map((e, idx) => (idx === 0 ? this.genExpr(e) : this._fmtArgJs(e)))
|
|
29
|
-
.join(", ");
|
|
30
|
-
switch (fn) {
|
|
31
|
-
case "Sprintf":
|
|
32
|
-
this.useHelper("sprintf");
|
|
33
|
-
return `__sprintf(${fmtArgs})`;
|
|
34
|
-
case "Errorf": {
|
|
35
|
-
this.useHelper("sprintf");
|
|
36
|
-
this.useHelper("error");
|
|
37
|
-
const fmtStr = expr.args[0];
|
|
38
|
-
if (fmtStr?.kind === "BasicLit" && fmtStr.value?.includes("%w")) {
|
|
39
|
-
const lastArg = this.genExpr(expr.args[expr.args.length - 1]);
|
|
40
|
-
return `__error(__sprintf(${fmtArgs}), ${lastArg})`;
|
|
41
|
-
}
|
|
42
|
-
return `__error(__sprintf(${fmtArgs}))`;
|
|
43
|
-
}
|
|
44
|
-
case "Printf":
|
|
45
|
-
this.useHelper("sprintf");
|
|
46
|
-
return this._genStdoutWrite(`__sprintf(${fmtArgs})`);
|
|
47
|
-
case "Print":
|
|
48
|
-
this.useHelper("sprintf");
|
|
49
|
-
return this._genStdoutWrite(this._genPrintOperands(expr, "", ""));
|
|
50
|
-
case "Println":
|
|
51
|
-
this.useHelper("sprintf");
|
|
52
|
-
// console.log supplies the trailing newline.
|
|
53
|
-
return `console.log(${this._genPrintOperands(expr, " ", "")})`;
|
|
54
|
-
case "Fprintf":
|
|
55
|
-
case "Fprintln":
|
|
56
|
-
case "Fprint":
|
|
57
|
-
return this._genFmtFprint(fn, expr);
|
|
58
|
-
case "Sscan": {
|
|
59
|
-
this.useHelper("error");
|
|
60
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
61
|
-
const restArgs = expr.args
|
|
62
|
-
.slice(1)
|
|
63
|
-
.map((e) => this.genExpr(e))
|
|
64
|
-
.join(", ");
|
|
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})`;
|
|
66
|
-
}
|
|
67
|
-
case "Sscanln": {
|
|
68
|
-
this.useHelper("error");
|
|
69
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
70
|
-
const restArgs = expr.args
|
|
71
|
-
.slice(1)
|
|
72
|
-
.map((e) => this.genExpr(e))
|
|
73
|
-
.join(", ");
|
|
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})`;
|
|
75
|
-
}
|
|
76
|
-
case "Sscanf": {
|
|
77
|
-
this.useHelper("error");
|
|
78
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
79
|
-
const fmtArg = this.genExpr(expr.args[1]);
|
|
80
|
-
const restArgs = expr.args
|
|
81
|
-
.slice(2)
|
|
82
|
-
.map((e) => this.genExpr(e))
|
|
83
|
-
.join(", ");
|
|
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
|
-
);
|
|
125
|
-
}
|
|
126
|
-
default:
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
_genFmtFprint(fn, expr) {
|
|
132
|
-
this.useHelper("sprintf");
|
|
133
|
-
const writerArg = expr.args[0];
|
|
134
|
-
const rest = expr.args.slice(1);
|
|
135
|
-
const restJs = rest.map((e) => this._fmtArgJs(e)).join(", ");
|
|
136
|
-
const writerType = writerArg._type;
|
|
137
|
-
const targetTypeName =
|
|
138
|
-
writerType?.name ??
|
|
139
|
-
(writerType?.kind === "pointer" ? writerType.base?.name : null);
|
|
140
|
-
const sprintfCall = this._buildFprintSprintfCall(fn, rest.length, restJs);
|
|
141
|
-
if (targetTypeName === "strings.Builder") {
|
|
142
|
-
const w = this.genExpr(writerArg);
|
|
143
|
-
const base = this._unboxWriter(w);
|
|
144
|
-
return `((__b, __s) => { __b._buf += __s; return [__s.length, null]; })(${base}, ${sprintfCall})`;
|
|
145
|
-
}
|
|
146
|
-
if (targetTypeName === "bytes.Buffer") {
|
|
147
|
-
const w = this.genExpr(writerArg);
|
|
148
|
-
const base = this._unboxWriter(w);
|
|
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})`;
|
|
150
|
-
}
|
|
151
|
-
// Generic io.Writer fallback — call .WriteString if available
|
|
152
|
-
const w = this.genExpr(writerArg);
|
|
153
|
-
return `((__w, __s) => typeof __w.WriteString === "function" ? __w.WriteString(__s) : __w.Write(new TextEncoder().encode(__s)))(${w}, ${sprintfCall})`;
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
_genStdoutWrite(strJs) {
|
|
157
|
-
return `((__s) => (typeof process !== "undefined" && process?.stdout?.write ? process.stdout.write(__s) : console.log(__s)))(${strJs})`;
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
// Formats Print/Println operands with %v so the first operand is never
|
|
161
|
-
// mistaken for a format string.
|
|
162
|
-
_genPrintOperands(expr, sep, suffix) {
|
|
163
|
-
const argc = expr.args.length;
|
|
164
|
-
if (argc === 0) return JSON.stringify(suffix);
|
|
165
|
-
const fmt = Array(argc).fill("%v").join(sep) + suffix;
|
|
166
|
-
const args = expr.args.map((e) => this._fmtArgJs(e)).join(", ");
|
|
167
|
-
return `__sprintf(${JSON.stringify(fmt)}, ${args})`;
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
_buildFprintSprintfCall(fn, argc, restJs) {
|
|
171
|
-
if (fn === "Fprintf") return `__sprintf(${restJs})`;
|
|
172
|
-
if (argc === 0) return fn === "Fprintln" ? '"\\n"' : '""';
|
|
173
|
-
const sep = fn === "Fprintln" ? " " : "";
|
|
174
|
-
const suffix = fn === "Fprintln" ? "\\n" : "";
|
|
175
|
-
const fmt = Array(argc).fill("%v").join(sep) + suffix;
|
|
176
|
-
return `__sprintf("${fmt}", ${restJs})`;
|
|
177
|
-
},
|
|
178
|
-
};
|