gofront 1.3.5 → 1.3.7
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 +7 -6
- package/package.json +1 -1
- package/src/cli-core.js +118 -13
- package/src/codegen/expressions.js +408 -89
- package/src/codegen/index.js +216 -25
- package/src/codegen/runtime.js +22 -1
- package/src/codegen/statements.js +170 -45
- package/src/codegen/stdlib/builder.js +7 -2
- package/src/codegen/stdlib/fmt.js +2 -2
- package/src/codegen/stdlib/io.js +1 -1
- package/src/dev-server.js +22 -10
- package/src/index.js +8 -2
- package/src/parser/declarations.js +2 -1
- package/src/pwa.js +3 -1
- package/src/typechecker/assignability.js +50 -4
- package/src/typechecker/expressions.js +13 -1
- package/src/typechecker/index.js +50 -3
- package/src/typechecker/resolve.js +2 -0
- package/src/typechecker/statements.js +10 -1
- package/src/typechecker/stdlib/web.js +54 -26
- package/src/typechecker/types.js +3 -2
- package/src/vendor.js +12 -7
package/src/typechecker/index.js
CHANGED
|
@@ -185,12 +185,55 @@ export class TypeChecker {
|
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
+
const all = [];
|
|
188
189
|
for (const p of programs) {
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
for (const d of p.decls) if (d.kind === "TypeDecl") all.push({ p, d });
|
|
191
|
+
}
|
|
192
|
+
// Collect in dependency order so aliases, generics, embedded and by-value
|
|
193
|
+
// field types declared later (or in other files) are ready when needed.
|
|
194
|
+
let pending = all;
|
|
195
|
+
while (pending.length > 0) {
|
|
196
|
+
const pendingNames = new Map(pending.map((x) => [x.d.name, x.d]));
|
|
197
|
+
const ready = pending.filter(
|
|
198
|
+
(x) => !this._typeDeclBlocked(x.d, pendingNames),
|
|
199
|
+
);
|
|
200
|
+
const batch = ready.length > 0 ? ready : pending;
|
|
201
|
+
for (const { p, d } of batch) {
|
|
202
|
+
this._setCurrentFile(p);
|
|
203
|
+
this.collectType(d);
|
|
204
|
+
}
|
|
205
|
+
pending =
|
|
206
|
+
ready.length > 0 ? pending.filter((x) => !ready.includes(x)) : [];
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
209
|
|
|
210
|
+
_typeDeclBlocked(decl, pendingNames) {
|
|
211
|
+
const visit = (node, indirect) => {
|
|
212
|
+
if (!node || typeof node !== "object") return false;
|
|
213
|
+
if (Array.isArray(node)) return node.some((n) => visit(n, indirect));
|
|
214
|
+
if (
|
|
215
|
+
(node.kind === "TypeName" || node.kind === "GenericTypeName") &&
|
|
216
|
+
node.name !== decl.name
|
|
217
|
+
) {
|
|
218
|
+
const dep = pendingNames.get(node.name);
|
|
219
|
+
if (dep && (!indirect || dep.isAlias || dep.typeParams)) return true;
|
|
220
|
+
}
|
|
221
|
+
const nextIndirect =
|
|
222
|
+
indirect ||
|
|
223
|
+
[
|
|
224
|
+
"PointerType",
|
|
225
|
+
"SliceType",
|
|
226
|
+
"MapType",
|
|
227
|
+
"FuncType",
|
|
228
|
+
"ChanType",
|
|
229
|
+
].includes(node.kind);
|
|
230
|
+
return Object.keys(node).some(
|
|
231
|
+
(k) => !k.startsWith("_") && visit(node[k], nextIndirect),
|
|
232
|
+
);
|
|
233
|
+
};
|
|
234
|
+
return visit(decl.type, false);
|
|
235
|
+
}
|
|
236
|
+
|
|
194
237
|
_collectFuncsPass(programs) {
|
|
195
238
|
for (const p of programs) {
|
|
196
239
|
this._setCurrentFile(p);
|
|
@@ -390,6 +433,7 @@ export class TypeChecker {
|
|
|
390
433
|
}
|
|
391
434
|
|
|
392
435
|
_attachMethod(decl, funcType) {
|
|
436
|
+
funcType._ptrRecv = Boolean(decl.recvPointer);
|
|
393
437
|
const recvNamedType = this.types.get(decl.recvType.name);
|
|
394
438
|
if (recvNamedType?._generic)
|
|
395
439
|
this._attachGenericMethod(recvNamedType, decl, funcType);
|
|
@@ -461,7 +505,10 @@ export class TypeChecker {
|
|
|
461
505
|
const recvNamedType = this.types.get(recvTypeName);
|
|
462
506
|
this._injectGenericReceiverTypeParams(inner, recvNamedType);
|
|
463
507
|
const recvType = this.resolveTypeNodeName(decl.recvType, outer);
|
|
464
|
-
inner.define(
|
|
508
|
+
inner.define(
|
|
509
|
+
decl.recvName,
|
|
510
|
+
decl.recvPointer ? { kind: "pointer", base: recvType } : recvType,
|
|
511
|
+
);
|
|
465
512
|
for (const p of decl.params) {
|
|
466
513
|
inner.define(p.name, this.resolveTypeNode(p.type, inner));
|
|
467
514
|
}
|
|
@@ -411,6 +411,8 @@ export const resolveMethods = {
|
|
|
411
411
|
_fieldTypeInterface(base, baseType, field, node) {
|
|
412
412
|
if (base.methods?.has(field)) return base.methods.get(field);
|
|
413
413
|
if (base.fields?.has(field)) return base.fields.get(field);
|
|
414
|
+
if (base._excluded?.has(field))
|
|
415
|
+
return this.err(`No member '${field}' on ${typeStr(baseType)}`, node);
|
|
414
416
|
if (base._isOpen) return ANY;
|
|
415
417
|
return this.err(`No method '${field}' on ${typeStr(baseType)}`, node);
|
|
416
418
|
},
|
|
@@ -148,8 +148,17 @@ export const statementCheckMethods = {
|
|
|
148
148
|
for (let i = 0; i < lhsTypes.length; i++) {
|
|
149
149
|
if (stmt.lhs[i]?.kind === "Ident" && stmt.lhs[i]?.name === "_") continue;
|
|
150
150
|
const r = rhsFlat[i] ?? ANY;
|
|
151
|
-
if (
|
|
151
|
+
if (stmt.rhs.length === lhsTypes.length && lhsTypes[i] && r)
|
|
152
|
+
this._markIfaceBox(
|
|
153
|
+
this.resolveType(lhsTypes[i]),
|
|
154
|
+
this.resolveType(r),
|
|
155
|
+
stmt.rhs[i],
|
|
156
|
+
);
|
|
157
|
+
if (!isAny(lhsTypes[i]) && !isAny(r)) {
|
|
158
|
+
this._skipIfaceMark = true;
|
|
152
159
|
this.assertAssignable(lhsTypes[i], r, stmt.lhs[i]);
|
|
160
|
+
this._skipIfaceMark = false;
|
|
161
|
+
}
|
|
153
162
|
}
|
|
154
163
|
},
|
|
155
164
|
|
|
@@ -23,6 +23,25 @@ const func = (params, returns = [VOID], variadic = false) => ({
|
|
|
23
23
|
variadic,
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
// Last parameter is optional (modelled as variadic).
|
|
27
|
+
const optLast = (params, returns = [VOID]) => func(params, returns, true);
|
|
28
|
+
|
|
29
|
+
const WEBGL2_ONLY_CONSTANTS = new Set([
|
|
30
|
+
"UNIFORM_BUFFER",
|
|
31
|
+
"HALF_FLOAT",
|
|
32
|
+
"RGBA8",
|
|
33
|
+
"RGBA32F",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const WEBGL2_ONLY_METHODS = new Set([
|
|
37
|
+
"VertexAttribIPointer",
|
|
38
|
+
"DrawArraysInstanced",
|
|
39
|
+
"DrawElementsInstanced",
|
|
40
|
+
"CreateVertexArray",
|
|
41
|
+
"BindVertexArray",
|
|
42
|
+
"DeleteVertexArray",
|
|
43
|
+
]);
|
|
44
|
+
|
|
26
45
|
const WEBGL_CONSTANTS_LIST = {
|
|
27
46
|
ARRAY_BUFFER: 0x8892,
|
|
28
47
|
ELEMENT_ARRAY_BUFFER: 0x8893,
|
|
@@ -113,7 +132,7 @@ function buildArrayBufferType() {
|
|
|
113
132
|
methods,
|
|
114
133
|
};
|
|
115
134
|
named.underlying = iface;
|
|
116
|
-
methods.set("slice",
|
|
135
|
+
methods.set("slice", optLast([INT, INT], [named]));
|
|
117
136
|
return named;
|
|
118
137
|
}
|
|
119
138
|
|
|
@@ -126,20 +145,20 @@ function buildDataViewType(arrayBufferType) {
|
|
|
126
145
|
const methods = new Map([
|
|
127
146
|
["getInt8", func([INT], [INT8])],
|
|
128
147
|
["getUint8", func([INT], [UINT8])],
|
|
129
|
-
["getInt16",
|
|
130
|
-
["getUint16",
|
|
131
|
-
["getInt32",
|
|
132
|
-
["getUint32",
|
|
133
|
-
["getFloat32",
|
|
134
|
-
["getFloat64",
|
|
148
|
+
["getInt16", optLast([INT, BOOL], [INT16])],
|
|
149
|
+
["getUint16", optLast([INT, BOOL], [UINT16])],
|
|
150
|
+
["getInt32", optLast([INT, BOOL], [INT32])],
|
|
151
|
+
["getUint32", optLast([INT, BOOL], [UINT32])],
|
|
152
|
+
["getFloat32", optLast([INT, BOOL], [FLOAT32])],
|
|
153
|
+
["getFloat64", optLast([INT, BOOL], [FLOAT64])],
|
|
135
154
|
["setInt8", func([INT, INT8])],
|
|
136
155
|
["setUint8", func([INT, UINT8])],
|
|
137
|
-
["setInt16",
|
|
138
|
-
["setUint16",
|
|
139
|
-
["setInt32",
|
|
140
|
-
["setUint32",
|
|
141
|
-
["setFloat32",
|
|
142
|
-
["setFloat64",
|
|
156
|
+
["setInt16", optLast([INT, INT16, BOOL])],
|
|
157
|
+
["setUint16", optLast([INT, UINT16, BOOL])],
|
|
158
|
+
["setInt32", optLast([INT, INT32, BOOL])],
|
|
159
|
+
["setUint32", optLast([INT, UINT32, BOOL])],
|
|
160
|
+
["setFloat32", optLast([INT, FLOAT32, BOOL])],
|
|
161
|
+
["setFloat64", optLast([INT, FLOAT64, BOOL])],
|
|
143
162
|
]);
|
|
144
163
|
const named = { kind: "named", name: "DataView", underlying: null };
|
|
145
164
|
named.underlying = { kind: "interface", name: "DataView", fields, methods };
|
|
@@ -164,15 +183,16 @@ function buildTypedArrayType(name, elemType, arrayBufferType) {
|
|
|
164
183
|
_isTypedArray: true,
|
|
165
184
|
};
|
|
166
185
|
named.underlying = iface;
|
|
167
|
-
methods.set("subarray",
|
|
168
|
-
methods.set("slice",
|
|
169
|
-
methods.set("set",
|
|
186
|
+
methods.set("subarray", optLast([INT, INT], [named]));
|
|
187
|
+
methods.set("slice", optLast([INT, INT], [named]));
|
|
188
|
+
methods.set("set", optLast([ANY, INT], [VOID]));
|
|
170
189
|
return named;
|
|
171
190
|
}
|
|
172
191
|
|
|
173
|
-
function createWebGLMethods() {
|
|
192
|
+
function createWebGLMethods(isWebGL2) {
|
|
174
193
|
const methods = new Map();
|
|
175
194
|
const add = (name, fn) => {
|
|
195
|
+
if (!isWebGL2 && WEBGL2_ONLY_METHODS.has(name)) return;
|
|
176
196
|
methods.set(name, fn);
|
|
177
197
|
const camel = name[0].toLowerCase() + name.slice(1);
|
|
178
198
|
if (camel !== name) methods.set(camel, fn);
|
|
@@ -296,7 +316,7 @@ function createWebGPUMethods() {
|
|
|
296
316
|
addDev("CreateShaderModule", func([ANY], [ANY]));
|
|
297
317
|
addDev("CreateRenderPipeline", func([ANY], [ANY]));
|
|
298
318
|
addDev("CreateComputePipeline", func([ANY], [ANY]));
|
|
299
|
-
addDev("CreateCommandEncoder",
|
|
319
|
+
addDev("CreateCommandEncoder", optLast([ANY], [ANY]));
|
|
300
320
|
addDev("CreateBindGroup", func([ANY], [ANY]));
|
|
301
321
|
addDev("CreateBindGroupLayout", func([ANY], [ANY]));
|
|
302
322
|
addDev("CreatePipelineLayout", func([ANY], [ANY]));
|
|
@@ -307,7 +327,7 @@ function createWebGPUMethods() {
|
|
|
307
327
|
const camel = name[0].toLowerCase() + name.slice(1);
|
|
308
328
|
if (camel !== name) adapterMethods.set(camel, fn);
|
|
309
329
|
};
|
|
310
|
-
addAdapt("RequestDevice",
|
|
330
|
+
addAdapt("RequestDevice", optLast([ANY], [ANY]));
|
|
311
331
|
|
|
312
332
|
return { queueMethods, deviceMethods, adapterMethods };
|
|
313
333
|
}
|
|
@@ -339,21 +359,29 @@ export function setupWebGlobals(globals, types) {
|
|
|
339
359
|
}
|
|
340
360
|
|
|
341
361
|
// WebGL constants map
|
|
342
|
-
const
|
|
362
|
+
const constFields2 = new Map();
|
|
343
363
|
for (const [k] of Object.entries(WEBGL_CONSTANTS_LIST)) {
|
|
344
|
-
|
|
364
|
+
constFields2.set(k, INT);
|
|
365
|
+
}
|
|
366
|
+
const constFields1 = new Map(
|
|
367
|
+
[...constFields2].filter(([k]) => !WEBGL2_ONLY_CONSTANTS.has(k)),
|
|
368
|
+
);
|
|
369
|
+
const webgl2Only = new Set(WEBGL2_ONLY_CONSTANTS);
|
|
370
|
+
for (const m of WEBGL2_ONLY_METHODS) {
|
|
371
|
+
webgl2Only.add(m);
|
|
372
|
+
webgl2Only.add(m[0].toLowerCase() + m.slice(1));
|
|
345
373
|
}
|
|
346
374
|
|
|
347
|
-
const webglMethods = createWebGLMethods();
|
|
348
375
|
const webglContext = {
|
|
349
376
|
kind: "named",
|
|
350
377
|
name: "WebGLRenderingContext",
|
|
351
378
|
underlying: {
|
|
352
379
|
kind: "interface",
|
|
353
380
|
name: "WebGLRenderingContext",
|
|
354
|
-
fields:
|
|
355
|
-
methods:
|
|
381
|
+
fields: constFields1,
|
|
382
|
+
methods: createWebGLMethods(false),
|
|
356
383
|
_isOpen: true,
|
|
384
|
+
_excluded: webgl2Only,
|
|
357
385
|
},
|
|
358
386
|
};
|
|
359
387
|
const webgl2Context = {
|
|
@@ -362,8 +390,8 @@ export function setupWebGlobals(globals, types) {
|
|
|
362
390
|
underlying: {
|
|
363
391
|
kind: "interface",
|
|
364
392
|
name: "WebGL2RenderingContext",
|
|
365
|
-
fields:
|
|
366
|
-
methods:
|
|
393
|
+
fields: constFields2,
|
|
394
|
+
methods: createWebGLMethods(true),
|
|
367
395
|
_isOpen: true,
|
|
368
396
|
},
|
|
369
397
|
};
|
package/src/typechecker/types.js
CHANGED
|
@@ -55,7 +55,7 @@ export const UINT16 = { kind: "basic", name: "uint16" };
|
|
|
55
55
|
export const UINT32 = { kind: "basic", name: "uint32" };
|
|
56
56
|
export const UINT64 = { kind: "basic", name: "uint64" };
|
|
57
57
|
export const UINTPTR = { kind: "basic", name: "uintptr" };
|
|
58
|
-
export const RUNE =
|
|
58
|
+
export const RUNE = INT32;
|
|
59
59
|
export const FLOAT32 = { kind: "basic", name: "float32" };
|
|
60
60
|
export const FLOAT64 = { kind: "basic", name: "float64" };
|
|
61
61
|
export const STRING = { kind: "basic", name: "string" };
|
|
@@ -149,9 +149,9 @@ export const isString = makeBasicPredicate("string");
|
|
|
149
149
|
export const isBool = makeBasicPredicate("bool");
|
|
150
150
|
|
|
151
151
|
// ── TypedArray mappings ──────────────────────────────────────
|
|
152
|
+
// []float64 deliberately stays a plain Array for JSON / JS-library interop.
|
|
152
153
|
export const TYPED_ARRAY_CONSTRUCTORS = {
|
|
153
154
|
float32: "Float32Array",
|
|
154
|
-
float64: "Float64Array",
|
|
155
155
|
uint8: "Uint8Array",
|
|
156
156
|
byte: "Uint8Array",
|
|
157
157
|
int8: "Int8Array",
|
|
@@ -159,6 +159,7 @@ export const TYPED_ARRAY_CONSTRUCTORS = {
|
|
|
159
159
|
int16: "Int16Array",
|
|
160
160
|
uint32: "Uint32Array",
|
|
161
161
|
int32: "Int32Array",
|
|
162
|
+
rune: "Int32Array",
|
|
162
163
|
};
|
|
163
164
|
|
|
164
165
|
export function typedArrayConstructorForElem(elemType) {
|
package/src/vendor.js
CHANGED
|
@@ -227,9 +227,12 @@ export async function loadNodePolyfillsPlugin(projectRoot, customPlugin) {
|
|
|
227
227
|
if (!info) return null;
|
|
228
228
|
try {
|
|
229
229
|
const mod = await import(pathToFileURL(info.path).href);
|
|
230
|
-
const fn =
|
|
231
|
-
mod.nodePolyfills
|
|
232
|
-
|
|
230
|
+
const fn = [
|
|
231
|
+
mod.nodePolyfills,
|
|
232
|
+
mod.default?.nodePolyfills,
|
|
233
|
+
mod.default,
|
|
234
|
+
].find((f) => typeof f === "function");
|
|
235
|
+
return fn ? fn() : null;
|
|
233
236
|
} catch {
|
|
234
237
|
return null;
|
|
235
238
|
}
|
|
@@ -339,10 +342,12 @@ export async function bundleVendor(projectDir = ".", options = {}) {
|
|
|
339
342
|
options.nodePolyfillsPlugin ??
|
|
340
343
|
bundlerInfo.nodePolyfillsPlugin ??
|
|
341
344
|
(options.nodePolyfills === false ? null : undefined);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
345
|
+
// The polyfill plugin is a Rolldown plugin; esbuild cannot use it.
|
|
346
|
+
const supportsPlugins =
|
|
347
|
+
typeof bundlerInfo.bundle === "function" || bundlerInfo.name === "rolldown";
|
|
348
|
+
const polyfillPlugin = supportsPlugins
|
|
349
|
+
? await loadNodePolyfillsPlugin(projectRoot, customPlugin)
|
|
350
|
+
: null;
|
|
346
351
|
|
|
347
352
|
if (typeof bundlerInfo.bundle === "function") {
|
|
348
353
|
try {
|