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.
Files changed (194) hide show
  1. package/README.md +14 -14
  2. package/package.json +10 -38
  3. package/src/backend/js/expressions.js +2060 -389
  4. package/src/backend/js/index.js +586 -174
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +936 -1644
  7. package/src/backend/js/statements.js +1349 -132
  8. package/src/backend/js/stdlib/index.js +51 -94
  9. package/src/backend/js/templ.js +67 -118
  10. package/src/backend/js/type-info.js +436 -0
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +80 -0
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +753 -872
  15. package/src/backend/wasm/emit-builtins.js +914 -237
  16. package/src/backend/wasm/emit-exprs.js +1456 -195
  17. package/src/backend/wasm/emit-maps.js +78 -380
  18. package/src/backend/wasm/emit-stmts.js +1659 -214
  19. package/src/backend/wasm/emit.js +614 -88
  20. package/src/backend/wasm/encode.js +43 -13
  21. package/src/backend/wasm/globals.js +491 -0
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +406 -3195
  24. package/src/backend/wasm/method-expr.js +392 -0
  25. package/src/backend/wasm/module-emitter.js +1615 -0
  26. package/src/backend/wasm/monomorph.js +164 -9
  27. package/src/backend/wasm/natives.js +596 -0
  28. package/src/backend/wasm/prescan.js +249 -0
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -37
  31. package/src/backend/wasm/stdlib/simd.js +293 -28
  32. package/src/backend/wasm/types.js +260 -27
  33. package/src/backend/wasm/variadic.js +93 -0
  34. package/src/backend/wasm/wat.js +47 -20
  35. package/src/{cli-core.js → cli/cli-core.js} +241 -11
  36. package/src/{test-runner.js → cli/test-runner.js} +188 -122
  37. package/src/{vendor.js → cli/vendor.js} +3 -4
  38. package/src/compiler.js +202 -386
  39. package/src/index.js +15 -169
  40. package/src/{lexer.js → lexer/lexer.js} +203 -62
  41. package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
  42. package/src/{tokens.js → lexer/tokens.js} +2 -0
  43. package/src/link/sourcemap.js +97 -0
  44. package/src/link/stdlib.js +737 -0
  45. package/src/link/type-names.js +148 -0
  46. package/src/link/wasm.js +318 -0
  47. package/src/lower/bounds.js +547 -0
  48. package/src/lower/boxing.js +1 -1
  49. package/src/lower/captures.js +267 -64
  50. package/src/lower/embedding.js +32 -3
  51. package/src/lower/errors-as.js +196 -0
  52. package/src/lower/fmt-formatters.js +905 -0
  53. package/src/lower/functions.js +2 -0
  54. package/src/lower/gen-types.js +274 -0
  55. package/src/lower/index.js +33 -19
  56. package/src/lower/json-codecs.js +1379 -0
  57. package/src/lower/ownership.js +47 -8
  58. package/src/lower/range.js +86 -1
  59. package/src/lower/reachability.js +150 -0
  60. package/src/lower/walk.js +12 -0
  61. package/src/parser/declarations.js +83 -15
  62. package/src/parser/expressions.js +110 -18
  63. package/src/parser/index.js +2 -1
  64. package/src/parser/statements.js +38 -22
  65. package/src/{templ-parser.js → parser/templ.js} +179 -17
  66. package/src/parser/types.js +70 -9
  67. package/src/resolver.js +21 -1
  68. package/src/typechecker/assignability.js +291 -19
  69. package/src/typechecker/const-fold.js +399 -0
  70. package/src/typechecker/constants.js +282 -0
  71. package/src/typechecker/expressions.js +1220 -183
  72. package/src/typechecker/index.js +659 -92
  73. package/src/typechecker/init-order.js +426 -0
  74. package/src/typechecker/operand-text.js +40 -0
  75. package/src/typechecker/resolve.js +613 -62
  76. package/src/typechecker/statements.js +212 -20
  77. package/src/typechecker/stdlib/excluded.js +902 -0
  78. package/src/typechecker/stdlib/index.js +38 -0
  79. package/src/typechecker/stdlib/simd.js +65 -15
  80. package/src/typechecker/termination.js +11 -2
  81. package/src/typechecker/types.js +268 -514
  82. package/stdlib/bytes/buffer.go +479 -0
  83. package/stdlib/bytes/bytes.go +1010 -0
  84. package/stdlib/bytes/reader.go +161 -0
  85. package/stdlib/cmp/cmp.go +65 -0
  86. package/stdlib/context/context.go +115 -0
  87. package/stdlib/crypto/rand/rand.go +34 -0
  88. package/stdlib/crypto/sha256/sha256.go +249 -0
  89. package/stdlib/encoding/base64/base64.go +331 -0
  90. package/stdlib/encoding/binary/binary.go +332 -0
  91. package/stdlib/encoding/hex/hex.go +140 -0
  92. package/stdlib/encoding/json/errors.go +31 -0
  93. package/stdlib/encoding/json/indent.go +71 -0
  94. package/stdlib/encoding/json/json.go +62 -0
  95. package/stdlib/encoding/json/number.go +12 -0
  96. package/stdlib/encoding/json/stream.go +173 -0
  97. package/stdlib/errors/errors.go +174 -0
  98. package/stdlib/fmt/errors.go +110 -0
  99. package/stdlib/fmt/format.go +732 -0
  100. package/stdlib/fmt/print.go +1232 -0
  101. package/stdlib/gom/gom.go +293 -0
  102. package/stdlib/hash/hash.go +53 -0
  103. package/stdlib/html/html.go +251 -0
  104. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  105. package/stdlib/internal/jsonrt/dec.go +871 -0
  106. package/stdlib/internal/jsonrt/enc.go +516 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +658 -0
  111. package/stdlib/io/io.go +502 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/maps.go +131 -0
  114. package/stdlib/math/bits/bits.go +507 -0
  115. package/stdlib/math/extra.go +272 -0
  116. package/stdlib/math/math.go +439 -0
  117. package/stdlib/math/rand/rand.go +297 -0
  118. package/stdlib/os/os.go +93 -0
  119. package/stdlib/path/filepath/filepath.go +47 -0
  120. package/stdlib/path/path.go +394 -0
  121. package/stdlib/regexp/regexp.go +231 -0
  122. package/stdlib/slices/slices.go +526 -0
  123. package/stdlib/slices/sort.go +209 -0
  124. package/stdlib/slices/zsort_cmp.go +480 -0
  125. package/stdlib/slices/zsort_ordered.go +482 -0
  126. package/stdlib/sort/sort.go +500 -0
  127. package/stdlib/sort/zsort_func.go +480 -0
  128. package/stdlib/sort/zsort_iface.go +480 -0
  129. package/stdlib/strconv/float.go +1699 -0
  130. package/stdlib/strconv/isprint.go +752 -0
  131. package/stdlib/strconv/quote.go +526 -0
  132. package/stdlib/strconv/strconv.go +616 -0
  133. package/stdlib/strings/builder.go +95 -0
  134. package/stdlib/strings/reader.go +163 -0
  135. package/stdlib/strings/replacer.go +102 -0
  136. package/stdlib/strings/strings.go +807 -0
  137. package/stdlib/sync/sync.go +268 -0
  138. package/stdlib/testing/async_js.go +61 -0
  139. package/stdlib/testing/benchmark.go +297 -0
  140. package/stdlib/testing/testing.go +523 -0
  141. package/stdlib/time/duration.go +233 -0
  142. package/stdlib/time/format.go +745 -0
  143. package/stdlib/time/parse.go +790 -0
  144. package/stdlib/time/sleep_js.go +63 -0
  145. package/stdlib/time/time.go +834 -0
  146. package/stdlib/unicode/unicode.go +250 -0
  147. package/stdlib/unicode/utf8/utf8.go +464 -0
  148. package/src/backend/js/stdlib/base64.js +0 -12
  149. package/src/backend/js/stdlib/binary.js +0 -102
  150. package/src/backend/js/stdlib/bits.js +0 -46
  151. package/src/backend/js/stdlib/builder.js +0 -63
  152. package/src/backend/js/stdlib/bytes.js +0 -122
  153. package/src/backend/js/stdlib/errors.js +0 -44
  154. package/src/backend/js/stdlib/fmt.js +0 -178
  155. package/src/backend/js/stdlib/gom.js +0 -155
  156. package/src/backend/js/stdlib/hex.js +0 -17
  157. package/src/backend/js/stdlib/html.js +0 -20
  158. package/src/backend/js/stdlib/io.js +0 -137
  159. package/src/backend/js/stdlib/json.js +0 -972
  160. package/src/backend/js/stdlib/maps.js +0 -45
  161. package/src/backend/js/stdlib/math.js +0 -69
  162. package/src/backend/js/stdlib/os.js +0 -13
  163. package/src/backend/js/stdlib/path.js +0 -48
  164. package/src/backend/js/stdlib/rand.js +0 -32
  165. package/src/backend/js/stdlib/regexp.js +0 -54
  166. package/src/backend/js/stdlib/sha256.js +0 -12
  167. package/src/backend/js/stdlib/shared.js +0 -17
  168. package/src/backend/js/stdlib/simd.js +0 -24
  169. package/src/backend/js/stdlib/slices.js +0 -77
  170. package/src/backend/js/stdlib/sort.js +0 -30
  171. package/src/backend/js/stdlib/strconv.js +0 -74
  172. package/src/backend/js/stdlib/strings.js +0 -222
  173. package/src/backend/js/stdlib/sync.js +0 -13
  174. package/src/backend/js/stdlib/testing.js +0 -34
  175. package/src/backend/js/stdlib/time.js +0 -128
  176. package/src/backend/js/stdlib/unicode.js +0 -25
  177. package/src/backend/js/stdlib/utf8.js +0 -26
  178. package/src/backend/wasm/const-fold.js +0 -205
  179. package/src/backend/wasm/emit-stdlib.js +0 -13
  180. package/src/backend/wasm/stdlib/bytes.js +0 -5039
  181. package/src/backend/wasm/stdlib/core.js +0 -8903
  182. package/src/backend/wasm/stdlib/io.js +0 -2161
  183. package/src/backend/wasm/stdlib/packages.js +0 -2400
  184. package/src/backend/wasm/stdlib/pure.js +0 -720
  185. package/src/backend/wasm/stdlib/time.js +0 -1200
  186. package/src/typechecker/stdlib/core.js +0 -801
  187. package/src/typechecker/stdlib/extended.js +0 -914
  188. package/src/typechecker/stdlib.js +0 -22
  189. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  190. /package/src/{colors.js → cli/colors.js} +0 -0
  191. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  192. /package/src/{minifier.js → cli/minifier.js} +0 -0
  193. /package/src/{project-config.js → cli/project-config.js} +0 -0
  194. /package/src/{pwa.js → cli/pwa.js} +0 -0
@@ -0,0 +1,249 @@
1
+ // src/backend/wasm/prescan.js
2
+ // Pre-scan helpers: walk the lowered AST to decide which imports, runtime helpers
3
+ // and interface dispatchers a module needs before emission starts.
4
+
5
+ import { prepareWasmNative } from "./natives.js";
6
+ import {
7
+ anonIfaceName,
8
+ getInterfaceMethodList,
9
+ getReceiverTypeName,
10
+ isInterfaceType,
11
+ isNonEmptyInterface,
12
+ printOperandKind,
13
+ toWasmType,
14
+ } from "./types.js";
15
+
16
+ export function hasErrorUsage(programs) {
17
+ return (programs ?? []).some((p) => {
18
+ let found = false;
19
+ const scan = (n) => {
20
+ if (!n || found || typeof n !== "object") return;
21
+ if (Array.isArray(n)) {
22
+ for (const x of n) scan(x);
23
+ return;
24
+ }
25
+ if (
26
+ (n.kind === "Ident" ||
27
+ n.kind === "TypeName" ||
28
+ n.kind === "basic" ||
29
+ n.kind === "interface") &&
30
+ n.name === "error"
31
+ ) {
32
+ found = true;
33
+ return;
34
+ }
35
+ for (const k of Object.keys(n)) {
36
+ if (!k.startsWith("_")) scan(n[k]);
37
+ }
38
+ };
39
+ scan(p);
40
+ return found;
41
+ });
42
+ }
43
+
44
+ // Depth-first search over AST nodes (skipping `_`-prefixed annotations).
45
+ export function _someNode(node, pred) {
46
+ if (!node || typeof node !== "object") return false;
47
+ if (Array.isArray(node)) return node.some((n) => _someNode(n, pred));
48
+ if (pred(node)) return true;
49
+ for (const key of Object.keys(node)) {
50
+ if (key.startsWith("_")) continue;
51
+ if (_someNode(node[key], pred)) return true;
52
+ }
53
+ return false;
54
+ }
55
+
56
+ // `__any_eq` is only needed when some `==`/`!=` (or switch case) compares
57
+ // anyref operands, a struct with an anyref field is compared, or the error
58
+ // runtime (`errors.Is`) is present. `_emitAnyEq` throws if this misses a
59
+ // site, so a gap surfaces as a compile error rather than a bad module.
60
+ export function _usesAnyEq(funcDecls, mod) {
61
+ if (mod.hasErrorType) return true;
62
+ for (const info of mod.mapTypes.values()) {
63
+ if (isInterfaceType(info.keyGoType, mod.checker)) return true;
64
+ }
65
+ for (const info of mod.structTypes.values()) {
66
+ if (info.fields?.some((f) => f.wType === "anyref")) return true;
67
+ }
68
+ const isAnyRef = (n) =>
69
+ Boolean(n?._type) && toWasmType(n._type, mod.checker, mod) === "anyref";
70
+ return funcDecls.some((fn) =>
71
+ _someNode(fn.body, (n) => {
72
+ if (n.kind === "BinaryExpr" && (n.op === "==" || n.op === "!="))
73
+ return isAnyRef(n.left) || isAnyRef(n.right);
74
+ if (n.kind === "SwitchStmt" && n.tag) return isAnyRef(n.tag);
75
+ return false;
76
+ }),
77
+ );
78
+ }
79
+
80
+ export function _scanImportsInBody(node, mod) {
81
+ if (!node || typeof node !== "object") return;
82
+
83
+ if (node.kind === "CallExpr") {
84
+ const { func, args } = node;
85
+ prepareWasmNative(mod, node);
86
+ if (
87
+ func.kind === "Ident" &&
88
+ (func.name === "print" || func.name === "println")
89
+ ) {
90
+ const isPrintln = func.name === "println";
91
+ if (args.length === 0 && isPrintln) {
92
+ mod.getPrintlnEmptyIndex();
93
+ }
94
+ for (let i = 0; i < args.length; i++) {
95
+ const isLast = i === args.length - 1 && isPrintln;
96
+ const { wType, isBool } = printOperandKind(args[i], mod.checker);
97
+ mod.getLogImportIndex(wType, isLast, isBool);
98
+ if (!isPrintln) mod.getPrintResetIndex();
99
+ }
100
+ }
101
+ }
102
+
103
+ if (node.kind === "BasicLit" && node.litKind === "STRING") {
104
+ mod.getStringImportIndex();
105
+ const strVal = String(node.value ?? "");
106
+ mod.internString(strVal);
107
+ }
108
+
109
+ // Recurse child properties
110
+ for (const key of Object.keys(node)) {
111
+ if (key.startsWith("_")) continue;
112
+ const child = node[key];
113
+ if (Array.isArray(child)) {
114
+ for (const item of child) _scanImportsInBody(item, mod);
115
+ } else if (child && typeof child === "object") {
116
+ _scanImportsInBody(child, mod);
117
+ }
118
+ }
119
+ }
120
+
121
+ export function _scanInterfaceCallNodes(node, interfaceCalls, checker) {
122
+ if (!node || typeof node !== "object") return;
123
+ if (Array.isArray(node)) {
124
+ for (const item of node)
125
+ _scanInterfaceCallNodes(item, interfaceCalls, checker);
126
+ return;
127
+ }
128
+ if (node.kind === "CallExpr" && node.func?.kind === "SelectorExpr") {
129
+ const recvType = node.func.expr?._type;
130
+ if (isNonEmptyInterface(recvType, checker)) {
131
+ const ifaceName =
132
+ getReceiverTypeName(recvType, node.func.expr) ||
133
+ anonIfaceName(recvType);
134
+ const methodName = node.func.field;
135
+ const key = `${ifaceName}.${methodName}`;
136
+ if (!interfaceCalls.has(key)) {
137
+ interfaceCalls.set(key, {
138
+ ifaceName,
139
+ ifaceType: recvType,
140
+ methodName,
141
+ callNode: node,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ for (const key of Object.keys(node)) {
147
+ if (!key.startsWith("_"))
148
+ _scanInterfaceCallNodes(node[key], interfaceCalls, checker);
149
+ }
150
+ }
151
+
152
+ export function _scanInterfaceTypeDecls(progs, interfaceCalls, checker) {
153
+ for (const p of progs) {
154
+ for (const d of p.decls ?? []) {
155
+ if (d.kind !== "TypeDecl") continue;
156
+ const resolved = checker?.types?.get(d.name) ?? d.type;
157
+ const underlying =
158
+ resolved?.kind === "named"
159
+ ? resolved.underlying
160
+ : d.type?.kind === "InterfaceType"
161
+ ? d.type
162
+ : resolved;
163
+ if (!isNonEmptyInterface(underlying, checker)) continue;
164
+ const methods =
165
+ underlying.methods instanceof Map
166
+ ? Array.from(underlying.methods.entries())
167
+ : Array.isArray(underlying.methods)
168
+ ? underlying.methods.map((m) => [m.name ?? m, m])
169
+ : [];
170
+ for (const [mName, mSig] of methods) {
171
+ const key = `${d.name}.${mName}`;
172
+ if (!interfaceCalls.has(key)) {
173
+ interfaceCalls.set(key, {
174
+ ifaceName: d.name,
175
+ ifaceType: resolved,
176
+ methodName: mName,
177
+ methodSig: mSig,
178
+ });
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ // A qualified interface (`fmt.Stringer`) in a signature is a boundary type
186
+ // when the function is exported, so its dispatchers must exist. Returns true
187
+ // when `t` names such a type.
188
+ function _registerQualifiedIface(t, interfaceCalls, checker) {
189
+ if (t.kind !== "TypeName" || !t.name?.includes(".")) return false;
190
+ const resolved = checker?.types?.get(t.name);
191
+ const iface = resolved?.underlying ?? resolved;
192
+ if (!resolved || !isNonEmptyInterface(iface, checker)) return true;
193
+ for (const m of getInterfaceMethodList(iface)) {
194
+ const key = `${t.name}.${m.name}`;
195
+ if (interfaceCalls.has(key)) continue;
196
+ interfaceCalls.set(key, {
197
+ ifaceName: t.name,
198
+ ifaceType: resolved,
199
+ methodName: m.name,
200
+ methodSig: { kind: "func", params: m.params, returns: m.returns },
201
+ });
202
+ }
203
+ return true;
204
+ }
205
+
206
+ export function _scanFuncSigInterfaces(
207
+ progs,
208
+ funcDecls,
209
+ interfaceCalls,
210
+ checker,
211
+ mod,
212
+ ) {
213
+ const scanType = (t) => {
214
+ if (!t) return;
215
+ if (_registerQualifiedIface(t, interfaceCalls, checker)) return;
216
+ if (t.kind === "InterfaceType" || (t.kind === "interface" && !t.name)) {
217
+ const mList = getInterfaceMethodList(t);
218
+ if (mList.length === 0) return;
219
+ const ifaceName = anonIfaceName(t, checker, mod);
220
+ for (const m of mList) {
221
+ const key = `${ifaceName}.${m.name}`;
222
+ if (!interfaceCalls.has(key)) {
223
+ interfaceCalls.set(key, {
224
+ ifaceName,
225
+ ifaceType: t,
226
+ methodName: m.name,
227
+ methodSig: {
228
+ kind: "func",
229
+ params: m.params,
230
+ returns: m.returns,
231
+ },
232
+ });
233
+ }
234
+ }
235
+ }
236
+ };
237
+ for (const fn of funcDecls) {
238
+ for (const p of fn.params ?? []) scanType(p.type);
239
+ scanType(fn.returnType);
240
+ }
241
+ for (const p of progs) {
242
+ for (const d of p.decls ?? []) {
243
+ if (d.kind === "FuncDecl") {
244
+ for (const param of d.params ?? []) scanType(param.type);
245
+ scanType(d.returnType);
246
+ }
247
+ }
248
+ }
249
+ }
@@ -0,0 +1,89 @@
1
+ // src/backend/was./prune-funcs.js
2
+ // Drops function imports and defined functions that no export, element
3
+ // segment, global initialiser or start function reaches, and renumbers the function index space to match. Imports
4
+ // are registered eagerly because the table is locked before bodies are
5
+ // emitted, so most modules declare far more than they call.
6
+
7
+ const FUNC_REF_OPS = new Set(["call", "return_call", "ref.func"]);
8
+
9
+ const funcRef = (inst) => inst.funcIndex ?? inst.index ?? 0;
10
+
11
+ function funcRefsOf(insts, visit) {
12
+ for (const inst of insts ?? []) {
13
+ if (FUNC_REF_OPS.has(inst.op)) visit(funcRef(inst));
14
+ }
15
+ }
16
+
17
+ // Calls `visit` for every function the module reaches without a body: exports,
18
+ // element segments, global initialisers and the start function.
19
+ function forEachRoot(moduleIR, visit) {
20
+ for (const g of moduleIR.globals ?? []) funcRefsOf(g.init, visit);
21
+ for (const idx of moduleIR.elements ?? []) visit(idx);
22
+ for (const exp of moduleIR.exports ?? []) {
23
+ if (exp.kind === "func") visit(exp.index);
24
+ }
25
+ if (typeof moduleIR.start === "number") visit(moduleIR.start);
26
+ }
27
+
28
+ function remapInst(inst, remap) {
29
+ if (!FUNC_REF_OPS.has(inst.op)) return inst;
30
+ const next = remap[funcRef(inst)];
31
+ return "funcIndex" in inst
32
+ ? { ...inst, funcIndex: next }
33
+ : { ...inst, index: next };
34
+ }
35
+
36
+ // Marks every function index reachable from the roots through call bodies.
37
+ function reachableFuncs(moduleIR, count, total) {
38
+ const used = new Array(total).fill(false);
39
+ const work = [];
40
+ const mark = (idx) => {
41
+ if (idx < total && !used[idx]) {
42
+ used[idx] = true;
43
+ work.push(idx);
44
+ }
45
+ };
46
+ forEachRoot(moduleIR, mark);
47
+ while (work.length > 0) {
48
+ const idx = work.pop();
49
+ if (idx >= count) funcRefsOf(moduleIR.funcs[idx - count].body, mark);
50
+ }
51
+ return used;
52
+ }
53
+
54
+ function applyRemap(moduleIR, remap) {
55
+ for (const fn of moduleIR.funcs) {
56
+ fn.body = fn.body.map((inst) => remapInst(inst, remap));
57
+ }
58
+ for (const g of moduleIR.globals ?? []) {
59
+ if (g.init) g.init = g.init.map((inst) => remapInst(inst, remap));
60
+ }
61
+ if (moduleIR.elements) {
62
+ moduleIR.elements = moduleIR.elements.map((idx) => remap[idx]);
63
+ }
64
+ for (const exp of moduleIR.exports ?? []) {
65
+ if (exp.kind === "func") exp.index = remap[exp.index];
66
+ }
67
+ if (typeof moduleIR.start === "number") {
68
+ moduleIR.start = remap[moduleIR.start];
69
+ }
70
+ }
71
+
72
+ export function pruneUnusedFuncs(moduleIR) {
73
+ const imports = moduleIR.imports ?? [];
74
+ const funcImports = imports.filter((imp) => imp.kind === "func");
75
+ const count = funcImports.length;
76
+ const total = count + moduleIR.funcs.length;
77
+
78
+ const used = reachableFuncs(moduleIR, count, total);
79
+ if (used.every(Boolean)) return;
80
+
81
+ const remap = new Array(total);
82
+ let next = 0;
83
+ for (let i = 0; i < total; i++) if (used[i]) remap[i] = next++;
84
+
85
+ const dropped = new Set(funcImports.filter((_, i) => !used[i]));
86
+ moduleIR.imports = imports.filter((imp) => !dropped.has(imp));
87
+ moduleIR.funcs = moduleIR.funcs.filter((_, i) => used[count + i]);
88
+ applyRemap(moduleIR, remap);
89
+ }
@@ -1,43 +1,8 @@
1
1
  // src/backend/wasm/stdlib/index.js
2
2
  // Standard library emitters for the WebAssembly backend.
3
- //
4
- // Organized by domain:
5
- // - core.js: math, math/bits, maps, slices, strings, strconv, fmt, errors, sort, unicode/utf8, testing
6
- // - bytes.js: bytes package functions and bytes.Buffer methods
7
- // - pure.js: stateless utilities (unicode, math/rand, html, path/filepath)
8
- // - io.js: io constants/functions, readers/writers, fmt Fprint/Sscan, synthetic IO methods
9
- // - time.js: time package (Duration, Time struct, components, Format/Parse, clock)
10
3
 
11
- import { BytesEmitter } from "./bytes.js";
12
- import { BINARY_MATH_IMPORTS, StdlibCoreEmitter } from "./core.js";
13
- import { IoEmitter } from "./io.js";
14
- import { ExtendedPackagesEmitter } from "./packages.js";
15
- import { PurePackagesEmitter } from "./pure.js";
16
4
  import { SimdEmitter } from "./simd.js";
17
- import { TimeEmitter } from "./time.js";
18
5
 
19
- // Aliases for backwards compatibility
20
- export {
21
- BINARY_MATH_IMPORTS,
22
- BytesEmitter,
23
- ExtendedPackagesEmitter,
24
- IoEmitter,
25
- IoEmitter as Phase7Emitter,
26
- PurePackagesEmitter,
27
- PurePackagesEmitter as Phase6Emitter,
28
- SimdEmitter,
29
- StdlibCoreEmitter,
30
- StdlibCoreEmitter as StdlibEmitter,
31
- TimeEmitter,
32
- TimeEmitter as Phase8Emitter,
33
- };
6
+ export { SimdEmitter };
34
7
 
35
- export const stdlibEmitters = [
36
- StdlibCoreEmitter,
37
- BytesEmitter,
38
- PurePackagesEmitter,
39
- IoEmitter,
40
- TimeEmitter,
41
- ExtendedPackagesEmitter,
42
- SimdEmitter,
43
- ];
8
+ export const stdlibEmitters = [SimdEmitter];