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
package/src/lower/embedding.js
CHANGED
|
@@ -1,26 +1,83 @@
|
|
|
1
1
|
// src/lower/embedding.js
|
|
2
2
|
// Computes promoted methods and delegation stubs for embedded structs.
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
ambiguousPromotions,
|
|
6
|
+
embeddedFieldName,
|
|
7
|
+
} from "../typechecker/types.js";
|
|
8
|
+
|
|
9
|
+
// A method promoted from an embedded struct value but declared on its
|
|
10
|
+
// pointer receiver is outside the method set of the outer struct's value.
|
|
11
|
+
function isPtrOnlyPromotion(rawEmbed, embed, mName, mType) {
|
|
12
|
+
if (rawEmbed.kind === "pointer") return false;
|
|
13
|
+
return Boolean((mType ?? embed.methods?.get(mName))?._ptrRecv);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// A pointer-receiver method reached through an embedded pointer, which may
|
|
17
|
+
// be nil.
|
|
18
|
+
function isNilablePtrRecv(rawEmbed, mType) {
|
|
19
|
+
return rawEmbed.kind === "pointer" && Boolean(mType?._ptrRecv);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// An embedded interface (named, literal or `error`) forwards each method of
|
|
23
|
+
// its method set to the interface value in the field.
|
|
24
|
+
function pushInterfaceStubs(stubs, declared, iface, fieldName) {
|
|
25
|
+
for (const mName of iface.methods?.keys() ?? []) {
|
|
26
|
+
if (declared.has(mName)) continue;
|
|
27
|
+
stubs.push({ methodName: mName, fieldName, ifaceEmbed: true });
|
|
28
|
+
declared.add(mName);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function pushValueEmbedStubs(stubs, declared, embed, embedName, fieldName) {
|
|
33
|
+
for (const [mName, mType] of embed.methods?.entries() ?? []) {
|
|
34
|
+
if (declared.has(mName) || mType?._ptrRecv) continue;
|
|
35
|
+
stubs.push({ methodName: mName, embedName, fieldName, valueEmbed: true });
|
|
36
|
+
declared.add(mName);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
4
40
|
export function computeEmbeddedStubs(name, methodDecls, checker) {
|
|
5
41
|
if (!checker) return [];
|
|
6
42
|
const resolvedType = checker.types.get(name)?.underlying;
|
|
7
43
|
if (resolvedType?.kind !== "struct" || !resolvedType._embeds) return [];
|
|
8
44
|
|
|
9
|
-
|
|
45
|
+
// A method two embeds declare at the same depth is in neither method set:
|
|
46
|
+
// no stub, so the value does not satisfy an interface that needs it.
|
|
47
|
+
const declared = new Set([
|
|
48
|
+
...methodDecls.map((m) => m.name),
|
|
49
|
+
...ambiguousPromotions(resolvedType),
|
|
50
|
+
]);
|
|
10
51
|
const stubs = [];
|
|
11
52
|
|
|
12
|
-
|
|
53
|
+
const embedded = (resolvedType._structFields ?? []).filter((f) => f.embedded);
|
|
54
|
+
for (const [i, rawEmbed] of resolvedType._embeds.entries()) {
|
|
55
|
+
const fieldName = embedded[i] ? embeddedFieldName(embedded[i]) : null;
|
|
13
56
|
const embed = rawEmbed.kind === "pointer" ? rawEmbed.base : rawEmbed;
|
|
57
|
+
const embedBase = embed.kind === "named" ? embed.underlying : embed;
|
|
58
|
+
if (embedBase?.kind === "interface") {
|
|
59
|
+
if (rawEmbed.kind !== "pointer" && fieldName)
|
|
60
|
+
pushInterfaceStubs(stubs, declared, embedBase, fieldName);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
14
63
|
const embedName = embed.kind === "named" ? embed.name : null;
|
|
15
64
|
if (!embedName) continue;
|
|
16
|
-
|
|
17
|
-
|
|
65
|
+
if (embedBase?.kind !== "struct" || !embedBase.methods) {
|
|
66
|
+
// A named non-struct type (`time.Duration`) promotes its value
|
|
67
|
+
// methods; the stub passes the embedded value as the receiver.
|
|
68
|
+
if (rawEmbed.kind !== "pointer")
|
|
69
|
+
pushValueEmbedStubs(stubs, declared, embed, embedName, fieldName);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
18
72
|
|
|
19
|
-
for (const [mName] of embedBase.methods.entries()) {
|
|
73
|
+
for (const [mName, mType] of embedBase.methods.entries()) {
|
|
20
74
|
if (!declared.has(mName)) {
|
|
21
75
|
stubs.push({
|
|
22
76
|
methodName: mName,
|
|
23
77
|
embedName,
|
|
78
|
+
fieldName,
|
|
79
|
+
ptrOnly: isPtrOnlyPromotion(rawEmbed, embed, mName, mType),
|
|
80
|
+
nilPtrRecv: isNilablePtrRecv(rawEmbed, mType),
|
|
24
81
|
});
|
|
25
82
|
declared.add(mName); // Prevent duplicate stubs for diamond embeds
|
|
26
83
|
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// src/lower/errors-as.js
|
|
2
|
+
// errors.As as generated Go source.
|
|
3
|
+
//
|
|
4
|
+
// `errors.As(err, &x)` stores through a pointer whose type only the checker
|
|
5
|
+
// knows. Each call site gets a function generated for its static target
|
|
6
|
+
// type; it walks the error tree like the real package and honours custom
|
|
7
|
+
// `As(any) bool` methods. The functions are ordinary Go, parsed and checked
|
|
8
|
+
// as part of the package's generated file (src/link/stdlib.js), so both
|
|
9
|
+
// backends compile the same code.
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
importsFor,
|
|
13
|
+
mentionsTypeParam,
|
|
14
|
+
TypeSpeller,
|
|
15
|
+
walkNodes,
|
|
16
|
+
} from "./gen-types.js";
|
|
17
|
+
|
|
18
|
+
const ERRORS_PATH = "errors";
|
|
19
|
+
const NOT_POINTER =
|
|
20
|
+
"errors.As: second argument must be a non-nil pointer to a type that implements error or to any interface type";
|
|
21
|
+
|
|
22
|
+
// The names the file imports `errors` as.
|
|
23
|
+
function errorsAliases(program) {
|
|
24
|
+
const aliases = new Set();
|
|
25
|
+
for (const imp of program.imports ?? [])
|
|
26
|
+
for (const spec of imp.imports)
|
|
27
|
+
if (spec.path === ERRORS_PATH && spec.alias !== "_")
|
|
28
|
+
aliases.add(spec.alias ?? "errors");
|
|
29
|
+
return aliases;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const isAsRef = (node, aliases) =>
|
|
33
|
+
node.kind === "SelectorExpr" &&
|
|
34
|
+
node.expr?.kind === "Ident" &&
|
|
35
|
+
node.expr._type?.kind === "namespace" &&
|
|
36
|
+
aliases.has(node.expr.name) &&
|
|
37
|
+
node.field === "As";
|
|
38
|
+
|
|
39
|
+
const isAsCall = (node, aliases) =>
|
|
40
|
+
node.kind === "CallExpr" && isAsRef(node.func, aliases);
|
|
41
|
+
|
|
42
|
+
// Marks `call` to call the generated function `name`. The function takes the
|
|
43
|
+
// typed pointer: the target is not boxed into an interface the way
|
|
44
|
+
// errors.As's `any` parameter asked.
|
|
45
|
+
function markCall(call, name) {
|
|
46
|
+
call.func._genEntry = name;
|
|
47
|
+
const arg = call.args[1];
|
|
48
|
+
arg._ifaceBox = undefined;
|
|
49
|
+
arg._ifaceSrc = undefined;
|
|
50
|
+
arg._ifaceNamedType = undefined;
|
|
51
|
+
arg._ifacePtrFields = undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// One function per distinct target type; `tparams` ("[T any]") makes it the
|
|
55
|
+
// shared function for targets that are a type parameter.
|
|
56
|
+
function asFunction(name, target, tparams = "") {
|
|
57
|
+
return `func ${name}${tparams}(err error, target *${target}) bool {
|
|
58
|
+
if target == nil {
|
|
59
|
+
panic("errors: target must be a non-nil pointer")
|
|
60
|
+
}
|
|
61
|
+
for err != nil {
|
|
62
|
+
if v, ok := err.(${target}); ok {
|
|
63
|
+
*target = v
|
|
64
|
+
return true
|
|
65
|
+
}
|
|
66
|
+
if a, ok := err.(interface{ As(any) bool }); ok && a.As(target) {
|
|
67
|
+
return true
|
|
68
|
+
}
|
|
69
|
+
switch u := err.(type) {
|
|
70
|
+
case interface{ Unwrap() error }:
|
|
71
|
+
err = u.Unwrap()
|
|
72
|
+
case interface{ Unwrap() []error }:
|
|
73
|
+
for _, e := range u.Unwrap() {
|
|
74
|
+
if e != nil && ${name}${tparams ? "[T]" : ""}(e, target) {
|
|
75
|
+
return true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false
|
|
79
|
+
default:
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false
|
|
84
|
+
}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// The `errors.As` calls of the programs, and a diagnostic for each use of
|
|
88
|
+
// errors.As that is not a call.
|
|
89
|
+
function findSites(programs) {
|
|
90
|
+
const sites = [];
|
|
91
|
+
const diagnostics = [];
|
|
92
|
+
for (const program of programs) {
|
|
93
|
+
const aliases = errorsAliases(program);
|
|
94
|
+
if (aliases.size === 0) continue;
|
|
95
|
+
const callees = new Set();
|
|
96
|
+
const refs = [];
|
|
97
|
+
walkNodes(program.decls, (node) => {
|
|
98
|
+
if (isAsCall(node, aliases)) {
|
|
99
|
+
sites.push({ call: node, program });
|
|
100
|
+
callees.add(node.func);
|
|
101
|
+
} else if (isAsRef(node, aliases)) {
|
|
102
|
+
refs.push(node);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
for (const node of refs)
|
|
106
|
+
if (!callees.has(node))
|
|
107
|
+
diagnostics.push({
|
|
108
|
+
program,
|
|
109
|
+
node: node.expr,
|
|
110
|
+
message: "errors.As cannot be used as a value",
|
|
111
|
+
hint: "call errors.As directly",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return { sites, diagnostics };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// What a call's target type allows: { base } for a target to generate for, or
|
|
118
|
+
// { message, hint } for one the generator rejects.
|
|
119
|
+
function classifyTarget(call) {
|
|
120
|
+
const argType = call.args[1]?._type;
|
|
121
|
+
if (argType?.kind !== "pointer") return { message: NOT_POINTER };
|
|
122
|
+
const base = argType.base;
|
|
123
|
+
if (base?.kind === "interface" && !base.name && base.methods?.size > 0)
|
|
124
|
+
return {
|
|
125
|
+
message:
|
|
126
|
+
"errors.As with a target of an anonymous interface type is not yet available",
|
|
127
|
+
hint: "declare a named interface type for the target",
|
|
128
|
+
};
|
|
129
|
+
if (base?.kind !== "typeParam" && mentionsTypeParam(base))
|
|
130
|
+
return {
|
|
131
|
+
message:
|
|
132
|
+
"errors.As with a target that mentions a type parameter is not yet available",
|
|
133
|
+
hint: "use a target that is a type parameter itself, or a concrete type",
|
|
134
|
+
};
|
|
135
|
+
return { base };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Generates the `errors.As` functions for a package's call sites. Returns
|
|
139
|
+
// null when it has none; otherwise { body, imports, diagnostics, link } and
|
|
140
|
+
// marks each call's SelectorExpr with `_genEntry`.
|
|
141
|
+
export function generateErrorsAs(programs, _checker, pkgName) {
|
|
142
|
+
const { sites, diagnostics } = findSites(programs);
|
|
143
|
+
if (sites.length + diagnostics.length === 0) return null;
|
|
144
|
+
const qualifiers = new Map();
|
|
145
|
+
const speller = new TypeSpeller(pkgName, qualifiers, programs);
|
|
146
|
+
const prefix = `gfe_${String(pkgName).replace(/[^A-Za-z0-9_]/g, "_")}_as_`;
|
|
147
|
+
const names = new Map(); // spelled target -> function name
|
|
148
|
+
const out = [];
|
|
149
|
+
const sharedSites = []; // targets that are a type parameter
|
|
150
|
+
for (const { call, program } of sites) {
|
|
151
|
+
const { base, message, hint } = classifyTarget(call);
|
|
152
|
+
let target;
|
|
153
|
+
try {
|
|
154
|
+
if (base?.kind === "typeParam") sharedSites.push(call);
|
|
155
|
+
else if (base) target = speller.spell(base);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
diagnostics.push({
|
|
158
|
+
program,
|
|
159
|
+
node: call.func.expr,
|
|
160
|
+
message: `errors.As: ${e.message}`,
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (!base) {
|
|
165
|
+
diagnostics.push({ program, node: call.func.expr, message, hint });
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (target === undefined) continue;
|
|
169
|
+
if (!names.has(target)) {
|
|
170
|
+
names.set(target, `${prefix}${names.size}`);
|
|
171
|
+
out.push(asFunction(names.get(target), target));
|
|
172
|
+
}
|
|
173
|
+
markCall(call, names.get(target));
|
|
174
|
+
}
|
|
175
|
+
const sharedName = `${prefix}t`;
|
|
176
|
+
if (sharedSites.length > 0) out.push(asFunction(sharedName, "T", "[T any]"));
|
|
177
|
+
for (const call of sharedSites) markCall(call, sharedName);
|
|
178
|
+
// The shared function is generic: once it is checked, its call sites take
|
|
179
|
+
// the type arguments the checker would have inferred.
|
|
180
|
+
const link = (chk) => {
|
|
181
|
+
const generic = chk.globals.symbols.get(sharedName);
|
|
182
|
+
for (const call of sharedSites) {
|
|
183
|
+
const typeArgs = [call.args[1]._type.base];
|
|
184
|
+
for (const n of [call, call.func]) {
|
|
185
|
+
n._typeArgs = typeArgs;
|
|
186
|
+
n._genericFnType = generic;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
return {
|
|
191
|
+
body: out.join("\n\n"),
|
|
192
|
+
imports: importsFor(qualifiers),
|
|
193
|
+
diagnostics,
|
|
194
|
+
link,
|
|
195
|
+
};
|
|
196
|
+
}
|