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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// (e.g. Identity$int, Box$int, Stack$int.Push) and re-typechecks the monomorphised AST.
|
|
8
8
|
|
|
9
9
|
import { TypeChecker } from "../../typechecker/index.js";
|
|
10
|
+
import { goTypeName } from "../shared/fmt-types.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Returns true if the AST contains any generic declarations.
|
|
@@ -33,7 +34,13 @@ export function hasGenerics(programs) {
|
|
|
33
34
|
/**
|
|
34
35
|
* Returns a stable identifier-safe string key for any Go type or AST type node.
|
|
35
36
|
*/
|
|
37
|
+
// A qualified type argument (`time.Duration`) becomes part of a JS and wasm
|
|
38
|
+
// export identifier, so its dot is replaced.
|
|
36
39
|
function typeKey(t) {
|
|
40
|
+
return rawTypeKey(t).replaceAll(".", "_");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function rawTypeKey(t) {
|
|
37
44
|
if (!t) return "any";
|
|
38
45
|
if (typeof t === "string") return t;
|
|
39
46
|
if (t.kind === "basic") return t.name;
|
|
@@ -78,7 +85,7 @@ function typeKey(t) {
|
|
|
78
85
|
/**
|
|
79
86
|
* Converts a Go type representation or AST type node into a concrete AST type node.
|
|
80
87
|
*/
|
|
81
|
-
function typeToTypeNode(t) {
|
|
88
|
+
export function typeToTypeNode(t) {
|
|
82
89
|
if (!t) return { kind: "TypeName", name: "any" };
|
|
83
90
|
if (typeof t === "string") return { kind: "TypeName", name: t };
|
|
84
91
|
if (
|
|
@@ -112,7 +119,11 @@ function typeToTypeNode(t) {
|
|
|
112
119
|
if (t.kind === "array") {
|
|
113
120
|
return {
|
|
114
121
|
kind: "ArrayType",
|
|
115
|
-
|
|
122
|
+
size: {
|
|
123
|
+
kind: "BasicLit",
|
|
124
|
+
litKind: "INT",
|
|
125
|
+
value: String(t.len ?? t.size ?? 0),
|
|
126
|
+
},
|
|
116
127
|
elem: typeToTypeNode(t.elem),
|
|
117
128
|
};
|
|
118
129
|
}
|
|
@@ -127,22 +138,92 @@ function typeToTypeNode(t) {
|
|
|
127
138
|
return { kind: "TypeName", name: t.name ?? "any" };
|
|
128
139
|
}
|
|
129
140
|
|
|
141
|
+
// Replaces the type parameters inside a checker type (`[]E`, `map[K]V`,
|
|
142
|
+
// `Box[E]`) by their type arguments; the result mixes checker types and the
|
|
143
|
+
// AST type nodes of the substitution, which `typeKey` and `typeToTypeNode`
|
|
144
|
+
// both accept.
|
|
145
|
+
function substituteInType(t, map) {
|
|
146
|
+
if (!t || typeof t !== "object") return t;
|
|
147
|
+
const sub = (x) => substituteInType(x, map);
|
|
148
|
+
switch (t.kind) {
|
|
149
|
+
case "typeParam":
|
|
150
|
+
return map.has(t.name) ? map.get(t.name) : t;
|
|
151
|
+
case "slice":
|
|
152
|
+
case "array":
|
|
153
|
+
return { ...t, elem: sub(t.elem) };
|
|
154
|
+
case "pointer":
|
|
155
|
+
return { ...t, base: sub(t.base) };
|
|
156
|
+
case "map":
|
|
157
|
+
return { ...t, key: sub(t.key), value: sub(t.value) };
|
|
158
|
+
case "func":
|
|
159
|
+
return {
|
|
160
|
+
...t,
|
|
161
|
+
params: (t.params ?? []).map(sub),
|
|
162
|
+
returns: (t.returns ?? []).map(sub),
|
|
163
|
+
};
|
|
164
|
+
case "named":
|
|
165
|
+
return t.typeArgs?.length ? { ...t, typeArgs: t.typeArgs.map(sub) } : t;
|
|
166
|
+
default:
|
|
167
|
+
return t;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// A partial instantiation (`Grow[S](nil, n)`) lists only the explicit type
|
|
172
|
+
// arguments; the checker recorded the complete list, which replaces it.
|
|
173
|
+
function completeTypeArgs(node, typeSubstMap) {
|
|
174
|
+
if (node._typeArgs?.length > (node.typeArgs?.length ?? 0))
|
|
175
|
+
return node._typeArgs.map((t) => substituteInType(t, typeSubstMap));
|
|
176
|
+
return node.typeArgs;
|
|
177
|
+
}
|
|
178
|
+
|
|
130
179
|
function getSpecializedName(baseName, typeArgs) {
|
|
131
180
|
if (!typeArgs || typeArgs.length === 0) return baseName;
|
|
132
181
|
const keys = typeArgs.map(typeKey).join("$");
|
|
133
182
|
return `${baseName}$${keys}`;
|
|
134
183
|
}
|
|
135
184
|
|
|
185
|
+
const KEPT_CLONE_KEYS = new Set(["_typeArgs", "_line", "_col", "_spread"]);
|
|
186
|
+
|
|
136
187
|
function cloneAst(node) {
|
|
137
188
|
if (!node || typeof node !== "object") return node;
|
|
138
189
|
if (Array.isArray(node)) return node.map(cloneAst);
|
|
139
190
|
const copy = {};
|
|
140
191
|
for (const [k, v] of Object.entries(node)) {
|
|
192
|
+
// Side tables are dropped, except source positions (for diagnostics in
|
|
193
|
+
// the specialised body) and the inferred type arguments of a generic
|
|
194
|
+
// call inside a generic body: substitution needs them to specialise the
|
|
195
|
+
// callee (`isNaN(x)` inside `Compare[T]`).
|
|
196
|
+
if (k.startsWith("_") && !KEPT_CLONE_KEYS.has(k)) continue;
|
|
141
197
|
copy[k] = cloneAst(v);
|
|
142
198
|
}
|
|
199
|
+
// Named results hang off the return type node and alias its types; keep
|
|
200
|
+
// just the names so `rebindNamedResults` can rebuild them after the types
|
|
201
|
+
// are substituted.
|
|
202
|
+
const named = node.returnType?._namedReturns;
|
|
203
|
+
if (named) copy._resultNames = named.map((r) => r.name);
|
|
143
204
|
return copy;
|
|
144
205
|
}
|
|
145
206
|
|
|
207
|
+
// Re-attaches named results (`(old *T)`) to every function in a cloned and
|
|
208
|
+
// substituted tree, pointing at the substituted type nodes.
|
|
209
|
+
function rebindNamedResults(node) {
|
|
210
|
+
if (!node || typeof node !== "object") return;
|
|
211
|
+
if (Array.isArray(node)) {
|
|
212
|
+
for (const n of node) rebindNamedResults(n);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (node._resultNames && node.returnType) {
|
|
216
|
+
const rt = node.returnType;
|
|
217
|
+
rt._namedReturns = node._resultNames.map((name, i) => ({
|
|
218
|
+
name,
|
|
219
|
+
type: rt.kind === "TupleType" ? rt.types[i] : rt,
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
for (const [k, v] of Object.entries(node)) {
|
|
223
|
+
if (!k.startsWith("_")) rebindNamedResults(v);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
146
227
|
/**
|
|
147
228
|
* Replaces references to type parameters in AST nodes with concrete types.
|
|
148
229
|
*/
|
|
@@ -214,6 +295,7 @@ function substituteTypesInAst(
|
|
|
214
295
|
}
|
|
215
296
|
const baseName = node.expr?.name;
|
|
216
297
|
if (baseName) {
|
|
298
|
+
node.typeArgs = completeTypeArgs(node, typeSubstMap);
|
|
217
299
|
const sName = getSpecializedName(baseName, node.typeArgs);
|
|
218
300
|
const isType = genericTypes ? genericTypes.has(baseName) : false;
|
|
219
301
|
if (onGenericUsage) {
|
|
@@ -233,6 +315,13 @@ function substituteTypesInAst(
|
|
|
233
315
|
// 3b. CompositeLit
|
|
234
316
|
if (node.kind === "CompositeLit") {
|
|
235
317
|
const targetProp = node.typeExpr ? "typeExpr" : node.type ? "type" : null;
|
|
318
|
+
// `S{a, b}` with S a type parameter: the type is a bare identifier.
|
|
319
|
+
if (
|
|
320
|
+
targetProp &&
|
|
321
|
+
node[targetProp]?.kind === "Ident" &&
|
|
322
|
+
typeSubstMap.has(node[targetProp].name)
|
|
323
|
+
)
|
|
324
|
+
node[targetProp] = cloneAst(typeSubstMap.get(node[targetProp].name));
|
|
236
325
|
if (targetProp && node[targetProp]) {
|
|
237
326
|
node[targetProp] = substituteTypesInAst(
|
|
238
327
|
node[targetProp],
|
|
@@ -246,6 +335,35 @@ function substituteTypesInAst(
|
|
|
246
335
|
|
|
247
336
|
// 4. CallExpr
|
|
248
337
|
if (node.kind === "CallExpr") {
|
|
338
|
+
// `T(x)` with T a type parameter becomes the conversion `int8(x)`.
|
|
339
|
+
const conv =
|
|
340
|
+
node.func?.kind === "Ident" ? typeSubstMap.get(node.func.name) : null;
|
|
341
|
+
if (conv && node.args?.length === 1) {
|
|
342
|
+
return {
|
|
343
|
+
kind: "TypeConversion",
|
|
344
|
+
targetType: cloneAst(conv),
|
|
345
|
+
expr: substituteTypesInAst(
|
|
346
|
+
node.args[0],
|
|
347
|
+
typeSubstMap,
|
|
348
|
+
onGenericUsage,
|
|
349
|
+
genericTypes,
|
|
350
|
+
genericFuncs,
|
|
351
|
+
),
|
|
352
|
+
_line: node._line,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
// `make(S, n)` / `new(S)`: the type argument is a bare identifier.
|
|
356
|
+
if (
|
|
357
|
+
node.func?.kind === "Ident" &&
|
|
358
|
+
(node.func.name === "make" || node.func.name === "new") &&
|
|
359
|
+
node.args?.[0]?.kind === "Ident" &&
|
|
360
|
+
typeSubstMap.has(node.args[0].name)
|
|
361
|
+
) {
|
|
362
|
+
node.args[0] = {
|
|
363
|
+
kind: "TypeExpr",
|
|
364
|
+
type: cloneAst(typeSubstMap.get(node.args[0].name)),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
249
367
|
if (node.func?.kind === "Ident") {
|
|
250
368
|
let typeArgs = node._typeArgs ?? node.func._typeArgs;
|
|
251
369
|
if (typeArgs) {
|
|
@@ -254,7 +372,7 @@ function substituteTypesInAst(
|
|
|
254
372
|
if (name && typeSubstMap.has(name)) {
|
|
255
373
|
return typeSubstMap.get(name);
|
|
256
374
|
}
|
|
257
|
-
return t;
|
|
375
|
+
return substituteInType(t, typeSubstMap);
|
|
258
376
|
});
|
|
259
377
|
const baseName = node.func.name;
|
|
260
378
|
const sName = getSpecializedName(baseName, typeArgs);
|
|
@@ -504,9 +622,14 @@ export function monomorphise(programs, checker) {
|
|
|
504
622
|
const genericFuncs = new Map();
|
|
505
623
|
const genericTypes = new Map();
|
|
506
624
|
const genericMethods = new Map(); // recvBaseName -> Array<MethodDecl>
|
|
625
|
+
// Template declaration -> its program; a specialization joins the program
|
|
626
|
+
// of its template, so a wasm package's instances stay wasm-package
|
|
627
|
+
// declarations even when a Go-source stdlib package is linked first.
|
|
628
|
+
const homeOf = new Map();
|
|
507
629
|
|
|
508
630
|
for (const p of progs) {
|
|
509
631
|
for (const d of p?.decls ?? []) {
|
|
632
|
+
homeOf.set(d, p);
|
|
510
633
|
if (d.kind === "FuncDecl" && d.typeParams && d.typeParams.length > 0) {
|
|
511
634
|
genericFuncs.set(d.name, d);
|
|
512
635
|
} else if (
|
|
@@ -556,6 +679,7 @@ export function monomorphise(programs, checker) {
|
|
|
556
679
|
}
|
|
557
680
|
}
|
|
558
681
|
|
|
682
|
+
const typeInstances = new Map();
|
|
559
683
|
const specializedFuncs = new Map();
|
|
560
684
|
const specializedTypes = new Map();
|
|
561
685
|
const specializedMethods = new Map();
|
|
@@ -583,6 +707,7 @@ export function monomorphise(programs, checker) {
|
|
|
583
707
|
typeSubstMap.set(tp.name, typeToTypeNode(concrete));
|
|
584
708
|
}
|
|
585
709
|
|
|
710
|
+
typeInstances.set(item.specializedName, item);
|
|
586
711
|
const monoTypeDecl = cloneAst(genDecl);
|
|
587
712
|
monoTypeDecl.name = item.specializedName;
|
|
588
713
|
monoTypeDecl.typeParams = null;
|
|
@@ -593,7 +718,9 @@ export function monomorphise(programs, checker) {
|
|
|
593
718
|
genericTypes,
|
|
594
719
|
genericFuncs,
|
|
595
720
|
);
|
|
721
|
+
rebindNamedResults(monoTypeDecl);
|
|
596
722
|
specializedTypes.set(item.specializedName, monoTypeDecl);
|
|
723
|
+
homeOf.set(monoTypeDecl, homeOf.get(genDecl));
|
|
597
724
|
|
|
598
725
|
// Specialize all methods declared on this generic type
|
|
599
726
|
const methods = genericMethods.get(item.genericName) ?? [];
|
|
@@ -610,8 +737,10 @@ export function monomorphise(programs, checker) {
|
|
|
610
737
|
genericTypes,
|
|
611
738
|
genericFuncs,
|
|
612
739
|
);
|
|
740
|
+
rebindNamedResults(monoMethod);
|
|
613
741
|
const mKey = `${item.specializedName}.${monoMethod.name}`;
|
|
614
742
|
specializedMethods.set(mKey, monoMethod);
|
|
743
|
+
homeOf.set(monoMethod, homeOf.get(m));
|
|
615
744
|
}
|
|
616
745
|
} else if (item.kind === "func") {
|
|
617
746
|
const genDecl = genericFuncs.get(item.genericName);
|
|
@@ -634,7 +763,9 @@ export function monomorphise(programs, checker) {
|
|
|
634
763
|
genericTypes,
|
|
635
764
|
genericFuncs,
|
|
636
765
|
);
|
|
766
|
+
rebindNamedResults(monoFuncDecl);
|
|
637
767
|
specializedFuncs.set(item.specializedName, monoFuncDecl);
|
|
768
|
+
homeOf.set(monoFuncDecl, homeOf.get(genDecl));
|
|
638
769
|
}
|
|
639
770
|
}
|
|
640
771
|
|
|
@@ -686,15 +817,22 @@ export function monomorphise(programs, checker) {
|
|
|
686
817
|
|
|
687
818
|
const targetProg = progs[0];
|
|
688
819
|
if (targetProg) {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
820
|
+
for (const group of [
|
|
821
|
+
specializedTypes,
|
|
822
|
+
specializedMethods,
|
|
823
|
+
specializedFuncs,
|
|
824
|
+
])
|
|
825
|
+
for (const d of group.values())
|
|
826
|
+
(homeOf.get(d) ?? targetProg).decls.push(d);
|
|
692
827
|
}
|
|
693
828
|
|
|
694
829
|
// 6. Typecheck the monomorphised program to annotate all concrete types
|
|
695
830
|
const monoChecker = new TypeChecker();
|
|
696
831
|
monoChecker.target = "wasm";
|
|
697
832
|
monoChecker.pkgName = targetProg?.pkg?.name ?? "main";
|
|
833
|
+
// The programs were checked once already, where `//gofront:native` is
|
|
834
|
+
// limited to the standard library; this pass only re-annotates them.
|
|
835
|
+
monoChecker.nativesChecked = true;
|
|
698
836
|
if (checker?.types) {
|
|
699
837
|
for (const [name, type] of checker.types.entries()) {
|
|
700
838
|
if (!monoChecker.types.has(name)) {
|
|
@@ -703,9 +841,26 @@ export function monomorphise(programs, checker) {
|
|
|
703
841
|
}
|
|
704
842
|
}
|
|
705
843
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
844
|
+
// One pass over all programs: declarations of every linked package are
|
|
845
|
+
// visible to the others (cross-package references are dequalified).
|
|
846
|
+
monoChecker.checkAll(progs);
|
|
847
|
+
nameInstances(monoChecker, typeInstances);
|
|
709
848
|
|
|
710
849
|
return { programs: progs, checker: monoChecker };
|
|
711
850
|
}
|
|
851
|
+
|
|
852
|
+
// Records Go's spelling of each generic instance (`Box[int]`) on its
|
|
853
|
+
// monomorphised type, which is named `Box$int`; `%T` prints the spelling.
|
|
854
|
+
function nameInstances(checker, instances) {
|
|
855
|
+
const spelling = {
|
|
856
|
+
has: (name) => instances.has(name),
|
|
857
|
+
get: (name) => {
|
|
858
|
+
const { genericName, typeArgs } = instances.get(name);
|
|
859
|
+
return `${genericName}[${typeArgs.map((a) => goTypeName(a, spelling)).join(",")}]`;
|
|
860
|
+
},
|
|
861
|
+
};
|
|
862
|
+
for (const name of instances.keys()) {
|
|
863
|
+
const type = checker.types.get(name);
|
|
864
|
+
if (type) type._goName = spelling.get(name);
|
|
865
|
+
}
|
|
866
|
+
}
|