gofront 1.8.0 → 1.9.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/README.md +3 -3
- package/package.json +6 -5
- package/src/backend/js/expressions.js +1157 -408
- package/src/backend/js/index.js +327 -153
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +559 -2552
- package/src/backend/js/statements.js +670 -158
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +298 -19
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +91 -170
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +884 -256
- package/src/backend/wasm/emit-exprs.js +185 -77
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-shared.js +4 -1
- package/src/backend/wasm/emit-stmts.js +524 -240
- package/src/backend/wasm/emit.js +176 -38
- package/src/backend/wasm/globals.js +48 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +44 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +299 -770
- package/src/backend/wasm/monomorph.js +139 -8
- package/src/backend/wasm/natives.js +600 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +97 -20
- package/src/backend/wasm/variadic.js +9 -4
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +113 -130
- package/src/lexer/lexer.js +106 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +355 -132
- package/src/link/type-names.js +204 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +62 -5
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +929 -0
- package/src/lower/functions.js +225 -7
- package/src/lower/gen-types.js +293 -0
- package/src/lower/index.js +14 -2
- package/src/lower/json-codecs.js +334 -245
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +30 -5
- package/src/parser/expressions.js +111 -57
- package/src/parser/statements.js +108 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +12 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +214 -19
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +156 -8
- package/src/typechecker/expressions.js +490 -108
- package/src/typechecker/index.js +346 -42
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +41 -0
- package/src/typechecker/resolve.js +490 -65
- package/src/typechecker/statements.js +288 -27
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +287 -575
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -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/json.go +62 -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/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- 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 +391 -452
- 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 +235 -50
- 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 +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- 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 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- 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 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- 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 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
|
@@ -1,517 +0,0 @@
|
|
|
1
|
-
// CodeGen for Go `fmt` package — installed onto CodeGen.prototype via stdlibGenMethods.
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
fmtDescHasFloat,
|
|
5
|
-
fmtDescIsSeq,
|
|
6
|
-
fmtTypeDesc,
|
|
7
|
-
fmtWantsTypes,
|
|
8
|
-
structOwnFields,
|
|
9
|
-
} from "../../shared/fmt-types.js";
|
|
10
|
-
|
|
11
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
12
|
-
|
|
13
|
-
const _SSCAN_LOOP =
|
|
14
|
-
`let n = 0, err = null; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
|
|
15
|
-
`const item = tokens[i]; const t = typeof item === "object" && item !== null ? item.t : item; const verb = item?.verb; const p = ptrs[i]; ` +
|
|
16
|
-
`if (verb === "%c") { p.value = t.codePointAt ? t.codePointAt(0) : t; } ` +
|
|
17
|
-
`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; } ` +
|
|
18
|
-
`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; } ` +
|
|
19
|
-
`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; } ` +
|
|
20
|
-
`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; } ` +
|
|
21
|
-
`else if (typeof p.value === "bigint") { try { if (!/^[+-]?\\d+$/.test(t)) throw 1; p.value = BigInt(t); } catch { err = __error("expected integer"); break; } } ` +
|
|
22
|
-
`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; } } ` +
|
|
23
|
-
`else p.value = t; n++; }`;
|
|
24
|
-
|
|
25
|
-
const FMT_METHODS = ["Error", "String"];
|
|
26
|
-
const isExportedName = (n) => /^\p{Lu}/u.test(n);
|
|
27
|
-
// Descriptor of a struct value whose class has a pointer-receiver Error/String:
|
|
28
|
-
// a value element or field must not be taken for a pointer because an earlier
|
|
29
|
-
// &x tagged the same object (see isPointer in __sprintf).
|
|
30
|
-
const FMT_STRUCT_VALUE = "{ sv: 1 }";
|
|
31
|
-
|
|
32
|
-
/** @type {ThisType<CodeGen>} */
|
|
33
|
-
export const fmtMethods = {
|
|
34
|
-
// ── Stringer/error dispatch metadata (read by __sprintf) ─────────────
|
|
35
|
-
//
|
|
36
|
-
// Named non-struct values are raw numbers/strings/arrays inside slices,
|
|
37
|
-
// maps and struct fields, and a struct and a pointer to it share one class.
|
|
38
|
-
// The type is therefore carried two ways, both only where a method can be
|
|
39
|
-
// called: a descriptor of the container's element types, attached when a
|
|
40
|
-
// slice/array/map is converted to an interface (static type passing, see
|
|
41
|
-
// __ifd), and per-class metadata for struct fields (__ff) and for
|
|
42
|
-
// pointer-receiver Error/String methods (__pr).
|
|
43
|
-
|
|
44
|
-
// JS source of the fmt descriptor for static type `t`, or null when no
|
|
45
|
-
// value of the type needs one:
|
|
46
|
-
// { b: Class, n } a raw value of a named type with a value-receiver
|
|
47
|
-
// Error/String; Class boxes it, n: numeric (map keys)
|
|
48
|
-
// { sv: 1 } a struct value with a pointer-receiver Error/String
|
|
49
|
-
// { e } elements of a slice or array
|
|
50
|
-
// { k, v } keys and values of a map
|
|
51
|
-
// { np: obj } a *T whose Error/String has a pointer receiver: obj
|
|
52
|
-
// stands in for a nil element (see _fmtNilPtrOperand)
|
|
53
|
-
// { m: 1, ... } a map that is not boxed itself (a struct field or an
|
|
54
|
-
// element): the object map carries no marker of its own
|
|
55
|
-
// `bare`: the value is the operand being boxed (a map is then marked by
|
|
56
|
-
// the boxing itself).
|
|
57
|
-
_fmtDesc(t, seen = new Set(), bare = true) {
|
|
58
|
-
t = this.checker?.resolveType?.(t) ?? t;
|
|
59
|
-
if (!t || seen.has(t)) return null;
|
|
60
|
-
const next = new Set(seen).add(t);
|
|
61
|
-
if (t.kind === "named") return this._fmtNamedDesc(t, next, bare);
|
|
62
|
-
if (t.kind === "slice" || t.kind === "array") {
|
|
63
|
-
const e = this._fmtDesc(t.elem, next, false);
|
|
64
|
-
return e ? `{ e: ${e} }` : null;
|
|
65
|
-
}
|
|
66
|
-
if (t.kind === "struct") return this._fmtAnonStructDesc(t, next);
|
|
67
|
-
if (t.kind === "pointer") {
|
|
68
|
-
if (bare) return null;
|
|
69
|
-
const np = this._fmtNilPtrOperand(t);
|
|
70
|
-
return np ? `{ np: ${np} }` : null;
|
|
71
|
-
}
|
|
72
|
-
if (t.kind !== "map") return null;
|
|
73
|
-
const parts = [
|
|
74
|
-
["k", this._fmtDesc(t.key, next, false)],
|
|
75
|
-
["v", this._fmtDesc(t.value, next, false)],
|
|
76
|
-
].filter(([, d]) => d);
|
|
77
|
-
if (!bare) parts.unshift(["m", "1"]);
|
|
78
|
-
return parts.length
|
|
79
|
-
? `{ ${parts.map(([n, d]) => `${n}: ${d}`).join(", ")} }`
|
|
80
|
-
: null;
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
// An anonymous struct has no class to carry field descriptors: { ff } holds
|
|
84
|
-
// them, keyed by field name.
|
|
85
|
-
_fmtAnonStructDesc(st, seen) {
|
|
86
|
-
const fields = [];
|
|
87
|
-
for (const [fname, ftype] of structOwnFields(st)) {
|
|
88
|
-
const desc = this._fmtDesc(ftype, seen, false);
|
|
89
|
-
if (desc) fields.push(`${JSON.stringify(fname)}: ${desc}`);
|
|
90
|
-
}
|
|
91
|
-
return fields.length > 0 ? `{ ff: { ${fields.join(", ")} } }` : null;
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
_fmtNamedDesc(t, seen, bare = true) {
|
|
95
|
-
const u = this.checker?.resolveType?.(t.underlying) ?? t.underlying;
|
|
96
|
-
const info = this._namedBoxInfo(t);
|
|
97
|
-
if (
|
|
98
|
-
info &&
|
|
99
|
-
FMT_METHODS.some((m) => info.methods.get(m)?._ptrRecv === false)
|
|
100
|
-
) {
|
|
101
|
-
const numeric = u?.kind === "basic" && /^(u?int|float)/.test(u.name);
|
|
102
|
-
return `{ b: ${info.cls}, n: ${numeric ? 1 : 0} }`;
|
|
103
|
-
}
|
|
104
|
-
if (u?.kind === "struct" && this._fmtHasPtrMethod(u))
|
|
105
|
-
return FMT_STRUCT_VALUE;
|
|
106
|
-
if (!u || u.kind === "struct" || u.kind === "interface") return null;
|
|
107
|
-
return this._fmtDesc(u, seen, bare);
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
// Whether struct `st` has a pointer-receiver Error/String, declared or
|
|
111
|
-
// promoted from an embedded struct.
|
|
112
|
-
_fmtHasPtrMethod(st, seen = new Set()) {
|
|
113
|
-
if (seen.has(st)) return false;
|
|
114
|
-
seen.add(st);
|
|
115
|
-
if (FMT_METHODS.some((m) => st.methods?.get(m)?._ptrRecv)) return true;
|
|
116
|
-
return (st._embeds ?? []).some((raw) => {
|
|
117
|
-
const inner = (raw.kind === "pointer" ? raw.base : raw).underlying;
|
|
118
|
-
return inner?.kind === "struct" && this._fmtHasPtrMethod(inner, seen);
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
// Error/String promoted from embedded interface fields, as { method: field }.
|
|
123
|
-
_fmtPromoted(st, methodDecls) {
|
|
124
|
-
const out = {};
|
|
125
|
-
for (const f of st._structFields ?? []) {
|
|
126
|
-
if (!f.embedded) continue;
|
|
127
|
-
const t = this.checker?.resolveType?.(f.type) ?? f.type;
|
|
128
|
-
const it = t?.kind === "named" ? t.underlying : t;
|
|
129
|
-
const key = (f.astType?.name ?? t?.name ?? "").split(".").pop();
|
|
130
|
-
if (it?.kind !== "interface" || !key) continue;
|
|
131
|
-
for (const mn of FMT_METHODS) {
|
|
132
|
-
const m = it.methods?.get(mn);
|
|
133
|
-
if (!m || m.params?.length > 0 || out[mn]) continue;
|
|
134
|
-
if (methodDecls.some((d) => d.name === mn)) continue;
|
|
135
|
-
out[mn] = key;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return out;
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
// Per-class fmt metadata of a struct: which of Error/String have a pointer
|
|
142
|
-
// receiver, and the descriptors of the exported fields that hold raw
|
|
143
|
-
// Stringer values.
|
|
144
|
-
_genFmtClassMeta(name, methodDecls) {
|
|
145
|
-
const st = this.checker?.types.get(name)?.underlying;
|
|
146
|
-
if (st?.kind !== "struct") return;
|
|
147
|
-
const ptrRecv = FMT_METHODS.filter((mn) =>
|
|
148
|
-
this._fmtPtrRecv(st, methodDecls, mn),
|
|
149
|
-
);
|
|
150
|
-
if (ptrRecv.length > 0)
|
|
151
|
-
this.line(
|
|
152
|
-
`Object.defineProperty(${name}.prototype, "__pr", { value: ${JSON.stringify(ptrRecv)} });`,
|
|
153
|
-
);
|
|
154
|
-
const promoted = this._fmtPromoted(st, methodDecls);
|
|
155
|
-
if (Object.keys(promoted).length > 0)
|
|
156
|
-
this.line(
|
|
157
|
-
`Object.defineProperty(${name}.prototype, "__pe", { value: ${JSON.stringify(promoted)} });`,
|
|
158
|
-
);
|
|
159
|
-
const fields = [];
|
|
160
|
-
const own = structOwnFields(st);
|
|
161
|
-
// The class also carries a copy of every promoted field (see
|
|
162
|
-
// _promotedPath); fmt lists only the fields the struct declares.
|
|
163
|
-
if (own.length < st.fields.size)
|
|
164
|
-
this.line(
|
|
165
|
-
`Object.defineProperty(${name}.prototype, "__fk", { value: ${JSON.stringify(own.map(([n]) => n))} });`,
|
|
166
|
-
);
|
|
167
|
-
for (const [fname, ftype] of own) {
|
|
168
|
-
const desc = this._fmtDesc(ftype, new Set(), false);
|
|
169
|
-
// Unexported fields get no method dispatch, only the value marker
|
|
170
|
-
// (and the map marker).
|
|
171
|
-
if (
|
|
172
|
-
desc &&
|
|
173
|
-
(isExportedName(fname) ||
|
|
174
|
-
desc === FMT_STRUCT_VALUE ||
|
|
175
|
-
/\bm: 1\b/.test(desc))
|
|
176
|
-
)
|
|
177
|
-
fields.push(`${fname}: ${desc}`);
|
|
178
|
-
}
|
|
179
|
-
// A thunk: the descriptors name classes declared further down.
|
|
180
|
-
if (fields.length > 0)
|
|
181
|
-
this.line(
|
|
182
|
-
`Object.defineProperty(${name}.prototype, "__ff", { value: () => ({ ${fields.join(", ")} }) });`,
|
|
183
|
-
);
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
// Whether method `mn` of struct `st` has a pointer receiver: declared on it,
|
|
187
|
-
// or promoted from an embedded struct (an embedded pointer promotes every
|
|
188
|
-
// method to the value's method set).
|
|
189
|
-
_fmtPtrRecv(st, methodDecls, mn) {
|
|
190
|
-
const decl = methodDecls.find((d) => d.name === mn);
|
|
191
|
-
if (decl) return Boolean(decl.recvPointer);
|
|
192
|
-
for (const raw of st._embeds ?? []) {
|
|
193
|
-
const isPtr = raw.kind === "pointer";
|
|
194
|
-
const m = (isPtr ? raw.base : raw).underlying?.methods?.get(mn);
|
|
195
|
-
if (m) return !isPtr && Boolean(m._ptrRecv);
|
|
196
|
-
}
|
|
197
|
-
return false;
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
// A nil `*T` whose Error/String has a pointer receiver still calls the method
|
|
201
|
-
// (Go does; a panic in it, usually a nil dereference, prints <nil>). The JS
|
|
202
|
-
// source of a stand-in for the nil pointer, or null when `t` is not such a
|
|
203
|
-
// pointer. Only operands whose static type is the pointer are covered.
|
|
204
|
-
_fmtNilPtrOperand(t) {
|
|
205
|
-
t = this.checker?.resolveType?.(t) ?? t;
|
|
206
|
-
if (t?.kind !== "pointer") return null;
|
|
207
|
-
const base = this.checker?.resolveType?.(t.base) ?? t.base;
|
|
208
|
-
const st =
|
|
209
|
-
this.checker?.resolveType?.(base?.underlying) ?? base?.underlying;
|
|
210
|
-
if (base?.kind !== "named" || st?.kind !== "struct" || !base.name)
|
|
211
|
-
return null;
|
|
212
|
-
for (const mn of FMT_METHODS) {
|
|
213
|
-
const m = st.methods?.get(mn) ?? base.methods?.get(mn);
|
|
214
|
-
// Instantiated generic methods are copies without _ptrRecv.
|
|
215
|
-
const generic = base.typeArgs
|
|
216
|
-
? this.checker?.types.get(base.name)?._generic
|
|
217
|
-
: null;
|
|
218
|
-
const ptrRecv = m?._ptrRecv ?? generic?.methods?.get(mn)?._ptrRecv;
|
|
219
|
-
if (!m || !ptrRecv || m.params?.length > 0) continue;
|
|
220
|
-
const cls = this._dequalify(base.name).replace(/\[.*$/, "");
|
|
221
|
-
if (cls.includes(".")) return null;
|
|
222
|
-
return `{ ${mn}() { try { return ${cls}.prototype.${mn}.call(null); } catch (e) { return "<nil>"; } }, __p: true, __nilp: true }`;
|
|
223
|
-
}
|
|
224
|
-
return null;
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
// `typed`: the format string needs operand types (`%T`, `%#v`, EXTRA, see
|
|
228
|
-
// fmtWantsTypes), so the operand travels with its static type as
|
|
229
|
-
// `__ft(value, descriptor)`; operands of interface type carry their dynamic
|
|
230
|
-
// type and stay bare.
|
|
231
|
-
_fmtArgJs(e, typed = false) {
|
|
232
|
-
// `xs...` passes each element as its own operand.
|
|
233
|
-
if (e?._spread) return `...(${this.genExpr(e)} ?? [])`;
|
|
234
|
-
// A multi-value call (`f()` returning a tuple) passes every result.
|
|
235
|
-
if (e?._type?.kind === "tuple") return this._fmtTupleJs(e);
|
|
236
|
-
const nilOperand = this._fmtNilPtrOperand(e?._type);
|
|
237
|
-
if (nilOperand) return `(${this.genExpr(e)} ?? ${nilOperand})`;
|
|
238
|
-
const js = this.genExpr(e);
|
|
239
|
-
// An operand of a type parameter type: the type argument knows how fmt
|
|
240
|
-
// should see it (a Stringer named type is boxed, a slice gets its elements).
|
|
241
|
-
const tpf =
|
|
242
|
-
e?._type?.kind === "typeParam"
|
|
243
|
-
? this._typeParamZeroFactory(e._type.name)
|
|
244
|
-
: null;
|
|
245
|
-
if (tpf) return `(${tpf}.fb ?? ${tpf}.b ?? ((__v) => __v))(${js})`;
|
|
246
|
-
const base =
|
|
247
|
-
e?._type?.kind === "named" ? (e._type.underlying ?? e._type) : e?._type;
|
|
248
|
-
if (e?._type?.name === "time.Duration") {
|
|
249
|
-
this.useHelper("duration");
|
|
250
|
-
this.useHelper("sprintf");
|
|
251
|
-
return `__ft(${js}, { k: "named", n: "time.Duration" })`;
|
|
252
|
-
}
|
|
253
|
-
const desc = fmtTypeDesc(
|
|
254
|
-
e?._type,
|
|
255
|
-
(t) => this.checker?.resolveType?.(t) ?? t,
|
|
256
|
-
);
|
|
257
|
-
if ((typed || fmtDescHasFloat(desc)) && desc && desc.k !== "i") {
|
|
258
|
-
this.useHelper("sprintf");
|
|
259
|
-
return `__ft(${js}, ${JSON.stringify(desc)})`;
|
|
260
|
-
}
|
|
261
|
-
return this._fmtNilValue(base, js, false);
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
// A nil slice or map operand prints as `[]` / `map[]`: coalesce the null
|
|
265
|
-
// to an empty value. Shared by the single-operand and the tuple path.
|
|
266
|
-
// `unboxed`: the map still needs its marker (the caller boxes the result).
|
|
267
|
-
_fmtNilValue(base, js, unboxed = true) {
|
|
268
|
-
if (base?.kind === "slice") return `(${js} ?? [])`;
|
|
269
|
-
if (unboxed && base?.kind === "map") return `(${js} ?? {})`;
|
|
270
|
-
return js;
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
// `js` (a value of static type `t`) boxed as converting it to an `any` does,
|
|
274
|
-
// with the same boxing the single-operand path gets from the checker
|
|
275
|
-
// (_markIfaceBox): named types with methods, pointers, slices, maps, structs
|
|
276
|
-
// and the fmt descriptor of Stringer elements.
|
|
277
|
-
_fmtBoxValue(js, t) {
|
|
278
|
-
const resolve = (x) => this.checker?.resolveType?.(x) ?? x;
|
|
279
|
-
let base = resolve(t);
|
|
280
|
-
if (base?.kind === "named") base = resolve(base.underlying);
|
|
281
|
-
const meta = this.checker?._ifaceBoxMeta?.(t);
|
|
282
|
-
if (meta?.type)
|
|
283
|
-
return this._genNamedIfaceBox(js, meta.type, meta.box === "named_ptr");
|
|
284
|
-
let out = this._fmtNilValue(base, js);
|
|
285
|
-
if (meta) out = this._ifaceBoxWrap(out, meta.box, meta.ptrFields);
|
|
286
|
-
const desc = this._fmtDesc(t);
|
|
287
|
-
return desc ? this._fmtDescWrap(out, desc) : out;
|
|
288
|
-
},
|
|
289
|
-
|
|
290
|
-
// The results of a multi-value call as separate operands. Each result is
|
|
291
|
-
// boxed as if it were assigned to an `any`, so pointers print as `&{...}`
|
|
292
|
-
// and floats keep their width.
|
|
293
|
-
_fmtTupleJs(e) {
|
|
294
|
-
const resolve = (t) => this.checker?.resolveType?.(t) ?? t;
|
|
295
|
-
const parts = e._type.types.map((t, i) => {
|
|
296
|
-
const boxed = this._fmtBoxValue(`__t[${i}]`, t);
|
|
297
|
-
const desc = fmtTypeDesc(t, resolve);
|
|
298
|
-
if (fmtDescHasFloat(desc) && desc.k !== "i") {
|
|
299
|
-
this.useHelper("sprintf");
|
|
300
|
-
return `__ft(${boxed}, ${JSON.stringify(desc)})`;
|
|
301
|
-
}
|
|
302
|
-
return boxed;
|
|
303
|
-
});
|
|
304
|
-
return `...((__t) => [${parts.join(", ")}])(${this.genExpr(e)})`;
|
|
305
|
-
},
|
|
306
|
-
|
|
307
|
-
// The operands of a Printf-style call whose format is args[fmtIdx].
|
|
308
|
-
_fmtFormatArgsJs(args, fmtIdx) {
|
|
309
|
-
const lit = args[fmtIdx];
|
|
310
|
-
const spread = args.some((e) => e?._spread);
|
|
311
|
-
const resolve = (t) => this.checker?.resolveType?.(t) ?? t;
|
|
312
|
-
const seqArgs = args
|
|
313
|
-
.slice(fmtIdx + 1)
|
|
314
|
-
.some((e) => fmtDescIsSeq(fmtTypeDesc(e?._type, resolve)));
|
|
315
|
-
const typed =
|
|
316
|
-
lit?.kind === "BasicLit" &&
|
|
317
|
-
fmtWantsTypes(lit.value, spread ? -1 : args.length - fmtIdx - 1, seqArgs);
|
|
318
|
-
if (typed) this.useHelper("sprintf");
|
|
319
|
-
return args.map((e, idx) =>
|
|
320
|
-
idx < fmtIdx
|
|
321
|
-
? this.genExpr(e)
|
|
322
|
-
: idx === fmtIdx
|
|
323
|
-
? this.genExpr(e)
|
|
324
|
-
: this._fmtArgJs(e, typed),
|
|
325
|
-
);
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
_genFmt(fn, _a, expr) {
|
|
329
|
-
const fmtArgs = ["Sprintf", "Printf", "Errorf"].includes(fn)
|
|
330
|
-
? this._fmtFormatArgsJs(expr.args, 0).join(", ")
|
|
331
|
-
: "";
|
|
332
|
-
switch (fn) {
|
|
333
|
-
case "Sprintf":
|
|
334
|
-
this.useHelper("sprintf");
|
|
335
|
-
return `__sprintf(${fmtArgs})`;
|
|
336
|
-
case "Sprint":
|
|
337
|
-
case "Sprintln":
|
|
338
|
-
this.useHelper("sprint");
|
|
339
|
-
return `__sprint(${fn === "Sprintln"}${expr.args.map((e) => `, ${this._fmtArgJs(e)}`).join("")})`;
|
|
340
|
-
case "Append":
|
|
341
|
-
case "Appendln":
|
|
342
|
-
case "Appendf": {
|
|
343
|
-
this.useHelper("sprint");
|
|
344
|
-
const [dst, ...rest] = expr.args;
|
|
345
|
-
const restJs = (
|
|
346
|
-
fn === "Appendf"
|
|
347
|
-
? this._fmtFormatArgsJs(rest, 0)
|
|
348
|
-
: rest.map((e) => this._fmtArgJs(e))
|
|
349
|
-
).join(", ");
|
|
350
|
-
const str =
|
|
351
|
-
fn === "Appendf"
|
|
352
|
-
? `__sprintf(${restJs})`
|
|
353
|
-
: `__sprint(${fn === "Appendln"}${restJs ? `, ${restJs}` : ""})`;
|
|
354
|
-
// Like append: write in place only when the whole result fits in
|
|
355
|
-
// dst's spare capacity, otherwise copy into one fresh array and
|
|
356
|
-
// leave dst's backing array untouched (never chunk the write).
|
|
357
|
-
this.useHelper("append");
|
|
358
|
-
return `((d, s) => { const e = new TextEncoder().encode(s); if (d == null && e.length === 0) return null; const r = d ?? new Uint8Array(0); const n = r.length + e.length; const c = __tcap.get(r); if (c !== undefined && n <= c) { const v = new Uint8Array(r.buffer, r.byteOffset, n); v.set(e, r.length); if (c > n) __tcap.set(v, c); return v; } const v = new Uint8Array(n); v.set(r); v.set(e, r.length); return v; })(${this.genExpr(dst)}, ${str})`;
|
|
359
|
-
}
|
|
360
|
-
case "Errorf": {
|
|
361
|
-
this.useHelper("sprintf");
|
|
362
|
-
this.useHelper("error");
|
|
363
|
-
const fmtStr = expr.args[0];
|
|
364
|
-
if (fmtStr?.kind === "BasicLit" && fmtStr.value?.includes("%w")) {
|
|
365
|
-
const lastArg = this.genExpr(expr.args[expr.args.length - 1]);
|
|
366
|
-
return `__error(__sprintf(${fmtArgs}), ${lastArg})`;
|
|
367
|
-
}
|
|
368
|
-
return `__error(__sprintf(${fmtArgs}))`;
|
|
369
|
-
}
|
|
370
|
-
case "Printf":
|
|
371
|
-
this.useHelper("sprintf");
|
|
372
|
-
return this._genStdoutWrite(`__sprintf(${fmtArgs})`);
|
|
373
|
-
case "Print":
|
|
374
|
-
this.useHelper("sprintf");
|
|
375
|
-
this.useHelper("sprint");
|
|
376
|
-
return this._genStdoutWrite(
|
|
377
|
-
`__sprint(false${expr.args.map((e) => `, ${this._fmtArgJs(e)}`).join("")})`,
|
|
378
|
-
);
|
|
379
|
-
case "Println":
|
|
380
|
-
this.useHelper("sprintf");
|
|
381
|
-
// console.log supplies the trailing newline.
|
|
382
|
-
return `console.log(${this._genPrintOperands(expr, " ", "")})`;
|
|
383
|
-
case "Fprintf":
|
|
384
|
-
case "Fprintln":
|
|
385
|
-
case "Fprint":
|
|
386
|
-
return this._genFmtFprint(fn, expr);
|
|
387
|
-
case "Sscan": {
|
|
388
|
-
this.useHelper("error");
|
|
389
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
390
|
-
const restArgs = expr.args
|
|
391
|
-
.slice(1)
|
|
392
|
-
.map((e) => (e._spread ? `...${this.genExpr(e)}` : this.genExpr(e)))
|
|
393
|
-
.join(", ");
|
|
394
|
-
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})`;
|
|
395
|
-
}
|
|
396
|
-
case "Sscanln": {
|
|
397
|
-
this.useHelper("error");
|
|
398
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
399
|
-
const restArgs = expr.args
|
|
400
|
-
.slice(1)
|
|
401
|
-
.map((e) => (e._spread ? `...${this.genExpr(e)}` : this.genExpr(e)))
|
|
402
|
-
.join(", ");
|
|
403
|
-
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})`;
|
|
404
|
-
}
|
|
405
|
-
case "Sscanf": {
|
|
406
|
-
this.useHelper("error");
|
|
407
|
-
const strArg = this.genExpr(expr.args[0]);
|
|
408
|
-
const fmtArg = this.genExpr(expr.args[1]);
|
|
409
|
-
const restArgs = expr.args
|
|
410
|
-
.slice(2)
|
|
411
|
-
.map((e) => (e._spread ? `...${this.genExpr(e)}` : this.genExpr(e)))
|
|
412
|
-
.join(", ");
|
|
413
|
-
return (
|
|
414
|
-
`((str, fmt, ...ptrs) => { ` +
|
|
415
|
-
`const s = String(str); const f = String(fmt); ` +
|
|
416
|
-
`let si = 0, fi = 0; const tokens = []; let parseErr = null; ` +
|
|
417
|
-
`while (fi < f.length) { ` +
|
|
418
|
-
`if (/\\s/.test(f[fi])) { ` +
|
|
419
|
-
`while (fi < f.length && /\\s/.test(f[fi])) fi++; ` +
|
|
420
|
-
`while (si < s.length && /\\s/.test(s[si])) si++; ` +
|
|
421
|
-
`continue; ` +
|
|
422
|
-
`} ` +
|
|
423
|
-
`if (f[fi] === "%") { ` +
|
|
424
|
-
`if (fi + 1 < f.length && f[fi + 1] === "%") { ` +
|
|
425
|
-
`if (s[si] !== "%") { parseErr = __error("input does not match format"); break; } ` +
|
|
426
|
-
`si++; fi += 2; continue; ` +
|
|
427
|
-
`} ` +
|
|
428
|
-
`const vm = f.slice(fi).match(/^%[vdsfqtxXbcoeEfFgG]/); ` +
|
|
429
|
-
`if (vm) { ` +
|
|
430
|
-
`const verb = vm[0]; fi += verb.length; ` +
|
|
431
|
-
`if (verb !== "%c") { while (si < s.length && /\\s/.test(s[si])) si++; } ` +
|
|
432
|
-
`if (si >= s.length) break; ` +
|
|
433
|
-
`let tokRe = /^\\S+/; ` +
|
|
434
|
-
`if (verb === "%d" || verb === "%i") tokRe = /^[+-]?\\d+/; ` +
|
|
435
|
-
`else if (verb === "%o") tokRe = /^[+-]?(?:0[oO])?[0-7]+/; ` +
|
|
436
|
-
`else if (verb === "%b") tokRe = /^[+-]?(?:0[bB])?[01]+/; ` +
|
|
437
|
-
`else if (verb === "%f" || verb === "%F" || verb === "%e" || verb === "%E" || verb === "%g" || verb === "%G") tokRe = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?/; ` +
|
|
438
|
-
`else if (verb === "%t") tokRe = /^(?:true|false|1|0|t|f|T|F|TRUE|FALSE)/; ` +
|
|
439
|
-
`else if (verb === "%x" || verb === "%X") tokRe = /^[+-]?(?:0x)?[0-9a-fA-F]+/; ` +
|
|
440
|
-
`else if (verb === "%c") tokRe = /^[\\s\\S]/; ` +
|
|
441
|
-
`const m = s.slice(si).match(tokRe); ` +
|
|
442
|
-
`if (!m) { parseErr = __error("input does not match format"); break; } ` +
|
|
443
|
-
`tokens.push({ t: m[0], verb }); si += m[0].length; continue; ` +
|
|
444
|
-
`} ` +
|
|
445
|
-
`} ` +
|
|
446
|
-
`if (si >= s.length) break; ` +
|
|
447
|
-
`if (s[si] !== f[fi]) { parseErr = __error("input does not match format"); break; } ` +
|
|
448
|
-
`si++; fi++; ` +
|
|
449
|
-
`} ` +
|
|
450
|
-
`${_SSCAN_LOOP} ` +
|
|
451
|
-
`return [n, parseErr || err || (n < ptrs.length ? __error("unexpected EOF") : null)]; ` +
|
|
452
|
-
`})(${strArg}, ${fmtArg}, ${restArgs})`
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
default:
|
|
456
|
-
return undefined;
|
|
457
|
-
}
|
|
458
|
-
},
|
|
459
|
-
|
|
460
|
-
_genFmtFprint(fn, expr) {
|
|
461
|
-
this.useHelper("sprintf");
|
|
462
|
-
const writerArg = expr.args[0];
|
|
463
|
-
const rest = expr.args.slice(1);
|
|
464
|
-
const restJs = (
|
|
465
|
-
fn === "Fprintf"
|
|
466
|
-
? this._fmtFormatArgsJs(rest, 0)
|
|
467
|
-
: rest.map((e) => this._fmtArgJs(e))
|
|
468
|
-
).join(", ");
|
|
469
|
-
const writerType = writerArg._type;
|
|
470
|
-
const targetTypeName =
|
|
471
|
-
writerType?.name ??
|
|
472
|
-
(writerType?.kind === "pointer" ? writerType.base?.name : null);
|
|
473
|
-
const sprintfCall = this._buildFprintSprintfCall(fn, rest.length, restJs);
|
|
474
|
-
if (targetTypeName === "strings.Builder") {
|
|
475
|
-
const w = this.genExpr(writerArg);
|
|
476
|
-
const base = this._unboxWriter(w);
|
|
477
|
-
return `((__b, __s) => { __b._buf += __s; return [__s.length, null]; })(${base}, ${sprintfCall})`;
|
|
478
|
-
}
|
|
479
|
-
if (targetTypeName === "bytes.Buffer") {
|
|
480
|
-
const w = this.genExpr(writerArg);
|
|
481
|
-
const base = this._unboxWriter(w);
|
|
482
|
-
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})`;
|
|
483
|
-
}
|
|
484
|
-
// Generic io.Writer fallback — call .WriteString if available
|
|
485
|
-
const w = this.genExpr(writerArg);
|
|
486
|
-
return `((__w, __s) => typeof __w.WriteString === "function" ? __w.WriteString(__s) : __w.Write(new TextEncoder().encode(__s)))(${w}, ${sprintfCall})`;
|
|
487
|
-
},
|
|
488
|
-
|
|
489
|
-
_genStdoutWrite(strJs) {
|
|
490
|
-
return `((__s) => (typeof process !== "undefined" && process?.stdout?.write ? process.stdout.write(__s) : console.log(__s)))(${strJs})`;
|
|
491
|
-
},
|
|
492
|
-
|
|
493
|
-
// Formats Print/Println operands with %v so the first operand is never
|
|
494
|
-
// mistaken for a format string.
|
|
495
|
-
_genPrintOperands(expr, sep, suffix) {
|
|
496
|
-
const argc = expr.args.length;
|
|
497
|
-
if (argc === 0) return JSON.stringify(suffix);
|
|
498
|
-
if (expr.args.some((e) => e._spread || e._type?.kind === "tuple")) {
|
|
499
|
-
// The operand count is only known at run time: join with Sprint's rules.
|
|
500
|
-
this.useHelper("sprint");
|
|
501
|
-
const joined = `__sprint(${sep === " "}, ${expr.args.map((e) => this._fmtArgJs(e)).join(", ")})`;
|
|
502
|
-
return sep === " " ? `${joined}.slice(0, -1)` : joined;
|
|
503
|
-
}
|
|
504
|
-
const fmt = Array(argc).fill("%v").join(sep) + suffix;
|
|
505
|
-
const args = expr.args.map((e) => this._fmtArgJs(e)).join(", ");
|
|
506
|
-
return `__sprintf(${JSON.stringify(fmt)}, ${args})`;
|
|
507
|
-
},
|
|
508
|
-
|
|
509
|
-
_buildFprintSprintfCall(fn, argc, restJs) {
|
|
510
|
-
if (fn === "Fprintf") return `__sprintf(${restJs})`;
|
|
511
|
-
if (argc === 0) return fn === "Fprintln" ? '"\\n"' : '""';
|
|
512
|
-
const sep = fn === "Fprintln" ? " " : "";
|
|
513
|
-
const suffix = fn === "Fprintln" ? "\\n" : "";
|
|
514
|
-
const fmt = Array(argc).fill("%v").join(sep) + suffix;
|
|
515
|
-
return `__sprintf("${fmt}", ${restJs})`;
|
|
516
|
-
},
|
|
517
|
-
};
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
// CodeGen for the GoFront-built-in `gom` DOM-rendering package.
|
|
2
|
-
|
|
3
|
-
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
|
-
|
|
5
|
-
const GOM_ELEMENT_TAGS = {
|
|
6
|
-
Div: "div",
|
|
7
|
-
Section: "section",
|
|
8
|
-
Article: "article",
|
|
9
|
-
Aside: "aside",
|
|
10
|
-
Header: "header",
|
|
11
|
-
Footer: "footer",
|
|
12
|
-
Main: "main",
|
|
13
|
-
Nav: "nav",
|
|
14
|
-
Figure: "figure",
|
|
15
|
-
H1: "h1",
|
|
16
|
-
H2: "h2",
|
|
17
|
-
H3: "h3",
|
|
18
|
-
H4: "h4",
|
|
19
|
-
H5: "h5",
|
|
20
|
-
H6: "h6",
|
|
21
|
-
Span: "span",
|
|
22
|
-
A: "a",
|
|
23
|
-
Strong: "strong",
|
|
24
|
-
Em: "em",
|
|
25
|
-
Code: "code",
|
|
26
|
-
Pre: "pre",
|
|
27
|
-
Small: "small",
|
|
28
|
-
Mark: "mark",
|
|
29
|
-
P: "p",
|
|
30
|
-
Br: "br",
|
|
31
|
-
Hr: "hr",
|
|
32
|
-
Ul: "ul",
|
|
33
|
-
Ol: "ol",
|
|
34
|
-
Li: "li",
|
|
35
|
-
Dl: "dl",
|
|
36
|
-
Dt: "dt",
|
|
37
|
-
Dd: "dd",
|
|
38
|
-
Form: "form",
|
|
39
|
-
Input: "input",
|
|
40
|
-
Button: "button",
|
|
41
|
-
Textarea: "textarea",
|
|
42
|
-
Select: "select",
|
|
43
|
-
Option: "option",
|
|
44
|
-
Label: "label",
|
|
45
|
-
Fieldset: "fieldset",
|
|
46
|
-
Legend: "legend",
|
|
47
|
-
Img: "img",
|
|
48
|
-
Video: "video",
|
|
49
|
-
Audio: "audio",
|
|
50
|
-
Canvas: "canvas",
|
|
51
|
-
Table: "table",
|
|
52
|
-
Thead: "thead",
|
|
53
|
-
Tbody: "tbody",
|
|
54
|
-
Tfoot: "tfoot",
|
|
55
|
-
Tr: "tr",
|
|
56
|
-
Th: "th",
|
|
57
|
-
Td: "td",
|
|
58
|
-
};
|
|
59
|
-
const GOM_ATTR_HELPERS = {
|
|
60
|
-
For: "for",
|
|
61
|
-
Name: "name",
|
|
62
|
-
Value: "value",
|
|
63
|
-
Target: "target",
|
|
64
|
-
Rel: "rel",
|
|
65
|
-
Alt: "alt",
|
|
66
|
-
Title: "title",
|
|
67
|
-
Lang: "lang",
|
|
68
|
-
Action: "action",
|
|
69
|
-
Method: "method",
|
|
70
|
-
AutoComplete: "autocomplete",
|
|
71
|
-
Draggable: "draggable",
|
|
72
|
-
Role: "role",
|
|
73
|
-
StyleAttr: "style",
|
|
74
|
-
AriaLabel: "aria-label",
|
|
75
|
-
};
|
|
76
|
-
const GOM_BOOL_ATTRS = {
|
|
77
|
-
Disabled: "disabled",
|
|
78
|
-
Checked: "checked",
|
|
79
|
-
Selected: "selected",
|
|
80
|
-
Readonly: "readonly",
|
|
81
|
-
};
|
|
82
|
-
const GOM_PROP_SETTERS = {
|
|
83
|
-
Class: "className",
|
|
84
|
-
Type: "type",
|
|
85
|
-
Href: "href",
|
|
86
|
-
Src: "src",
|
|
87
|
-
Placeholder: "placeholder",
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/** @type {ThisType<CodeGen>} */
|
|
91
|
-
export const gomMethods = {
|
|
92
|
-
_genGom(fn, expr) {
|
|
93
|
-
const a = () =>
|
|
94
|
-
expr.args.map((e) =>
|
|
95
|
-
e._spread ? `...${this.genExpr(e)}` : this.genExpr(e),
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
if (GOM_ELEMENT_TAGS[fn]) {
|
|
99
|
-
const tag = GOM_ELEMENT_TAGS[fn];
|
|
100
|
-
const args = a();
|
|
101
|
-
if (args.length === 0)
|
|
102
|
-
return `(()=>({Mount(p){const e=document.createElement("${tag}");p.appendChild(e);}}))()`;
|
|
103
|
-
return (
|
|
104
|
-
`((...c)=>({Mount(p){const e=document.createElement("${tag}");c.forEach(n=>n?.Mount?.(e));p.appendChild(e);}}))` +
|
|
105
|
-
`(${args.join(",")})`
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (GOM_ATTR_HELPERS[fn]) {
|
|
110
|
-
const [v] = a();
|
|
111
|
-
return `((v)=>({Mount(e){e.setAttribute("${GOM_ATTR_HELPERS[fn]}",v)}}))(${v})`;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (GOM_BOOL_ATTRS[fn])
|
|
115
|
-
return `({Mount(e){e.setAttribute("${GOM_BOOL_ATTRS[fn]}","")}})`;
|
|
116
|
-
|
|
117
|
-
const args = a();
|
|
118
|
-
|
|
119
|
-
if (GOM_PROP_SETTERS[fn])
|
|
120
|
-
return `((v)=>({Mount(e){e.${GOM_PROP_SETTERS[fn]}=v}}))(${args[0]})`;
|
|
121
|
-
|
|
122
|
-
switch (fn) {
|
|
123
|
-
case "El": {
|
|
124
|
-
const [tag, ...children] = args;
|
|
125
|
-
if (children.length === 0)
|
|
126
|
-
return `((t)=>({Mount(p){const e=document.createElement(t);p.appendChild(e);}})) (${tag})`;
|
|
127
|
-
return (
|
|
128
|
-
`((t,...c)=>({Mount(p){const e=document.createElement(t);c.forEach(n=>n?.Mount?.(e));p.appendChild(e);}}))` +
|
|
129
|
-
`(${tag},${children.join(",")})`
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
case "Text": {
|
|
133
|
-
const [s] = args;
|
|
134
|
-
return `((s)=>({Mount(p){p.appendChild(document.createTextNode(s))}}))(${s})`;
|
|
135
|
-
}
|
|
136
|
-
case "Attr": {
|
|
137
|
-
const [name, value] = args;
|
|
138
|
-
return `((n,v)=>({Mount(e){e.setAttribute(n,v)}}))(${name},${value})`;
|
|
139
|
-
}
|
|
140
|
-
case "DataAttr":
|
|
141
|
-
return `((k,v)=>({Mount(e){e.setAttribute("data-"+k,v)}}))(${args[0]},${args[1]})`;
|
|
142
|
-
case "If":
|
|
143
|
-
return `((c,n)=>c?n:{Mount(){}})(${args[0]},${args[1]})`;
|
|
144
|
-
case "Map":
|
|
145
|
-
return `((s,f)=>{const c=s.map(f);return{_items:c,Mount(p){c.forEach(n=>n.Mount(p))}}})(${args[0]},${args[1]})`;
|
|
146
|
-
case "Style":
|
|
147
|
-
return `((s)=>({Mount(p){const e=document.createElement("style");e.textContent=s;p.appendChild(e);}})) (${args[0]})`;
|
|
148
|
-
case "Mount":
|
|
149
|
-
return `((sel,n,r)=>{const e=document.querySelector(sel);e.innerHTML="";n.Mount(e,r)})(${args[0]},${args[1]},${args[2] ?? "undefined"})`;
|
|
150
|
-
case "MountTo":
|
|
151
|
-
return `((sel,n,r)=>{const e=document.querySelector(sel);n.Mount(e,r)})(${args[0]},${args[1]},${args[2] ?? "undefined"})`;
|
|
152
|
-
}
|
|
153
|
-
return undefined;
|
|
154
|
-
},
|
|
155
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
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
|
-
};
|