gofront 1.6.1 → 1.8.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 +45 -49
- package/package.json +12 -8
- package/src/backend/js/expressions.js +1627 -148
- package/src/backend/js/fmt-runtime.js +573 -0
- package/src/backend/js/index.js +508 -102
- package/src/backend/js/runtime.js +1997 -106
- package/src/backend/js/statements.js +931 -87
- package/src/backend/js/stdlib/bits.js +87 -14
- package/src/backend/js/stdlib/builder.js +41 -6
- package/src/backend/js/stdlib/bytes.js +253 -7
- package/src/backend/js/stdlib/errors.js +7 -1
- package/src/backend/js/stdlib/fmt.js +349 -10
- package/src/backend/js/stdlib/index.js +19 -2
- package/src/backend/js/stdlib/json.js +1167 -0
- package/src/backend/js/stdlib/maps.js +0 -8
- package/src/backend/js/stdlib/math.js +17 -1
- package/src/backend/js/stdlib/simd.js +34 -0
- package/src/backend/js/stdlib/slices.js +36 -6
- package/src/backend/js/stdlib/strconv.js +10 -5
- package/src/backend/js/stdlib/strings.js +83 -4
- package/src/backend/js/stdlib/testing.js +7 -0
- package/src/backend/js/stdlib/time.js +79 -55
- package/src/backend/js/stdlib/unicode.js +1 -1
- package/src/backend/js/stdlib/utf8.js +1 -1
- package/src/backend/js/templ.js +38 -76
- package/src/backend/js/type-info.js +272 -0
- package/src/backend/shared/fmt-types.js +188 -0
- package/src/backend/wasm/boundary.js +446 -72
- package/src/backend/wasm/emit-builtins.js +320 -13
- package/src/backend/wasm/emit-exprs.js +1404 -199
- package/src/backend/wasm/emit-maps.js +61 -13
- package/src/backend/wasm/emit-stmts.js +1359 -164
- package/src/backend/wasm/emit.js +518 -74
- package/src/backend/wasm/encode.js +128 -13
- package/src/backend/wasm/globals.js +452 -0
- package/src/backend/wasm/index.js +194 -2489
- package/src/backend/wasm/method-expr.js +381 -0
- package/src/backend/wasm/module-emitter.js +2240 -0
- package/src/backend/wasm/monomorph.js +62 -4
- package/src/backend/wasm/optimize.js +4 -2
- package/src/backend/wasm/prescan.js +397 -0
- package/src/backend/wasm/stdlib/bytes.js +1804 -127
- package/src/backend/wasm/stdlib/core.js +1574 -199
- package/src/backend/wasm/stdlib/index.js +3 -5
- package/src/backend/wasm/stdlib/io.js +1567 -150
- package/src/backend/wasm/stdlib/packages.js +2 -0
- package/src/backend/wasm/stdlib/simd.js +499 -0
- package/src/backend/wasm/stdlib/time.js +1041 -12
- package/src/backend/wasm/types.js +221 -15
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +84 -20
- package/src/{cli-core.js → cli/cli-core.js} +236 -10
- package/src/{test-runner.js → cli/test-runner.js} +332 -39
- package/src/{vendor.js → cli/vendor.js} +89 -15
- package/src/compiler.js +107 -269
- package/src/dts-parser.js +71 -14
- package/src/index.js +15 -169
- package/src/{lexer.js → lexer/lexer.js} +102 -55
- package/src/{tokens.js → lexer/tokens.js} +1 -0
- package/src/link/sourcemap.js +97 -0
- package/src/link/stdlib.js +515 -0
- package/src/link/wasm.js +294 -0
- package/src/lower/bounds.js +394 -0
- package/src/lower/boxing.js +1 -6
- package/src/lower/captures.js +176 -32
- package/src/lower/embedding.js +2 -1
- package/src/lower/index.js +26 -18
- package/src/lower/json-codecs.js +1398 -0
- package/src/lower/ownership.js +22 -1
- package/src/lower/range.js +86 -1
- package/src/lower/reachability.js +132 -0
- package/src/parser/declarations.js +58 -13
- package/src/parser/expressions.js +29 -7
- package/src/parser/index.js +2 -1
- package/src/parser/statements.js +37 -22
- package/src/parser/struct-tag.js +144 -0
- package/src/{templ-parser.js → parser/templ.js} +138 -15
- package/src/parser/types.js +130 -13
- package/src/resolver.js +22 -1
- package/src/typechecker/assignability.js +215 -11
- package/src/typechecker/const-fold.js +356 -0
- package/src/typechecker/constants.js +256 -0
- package/src/typechecker/expressions.js +960 -99
- package/src/typechecker/index.js +491 -72
- package/src/typechecker/init-order.js +330 -0
- package/src/typechecker/resolve.js +596 -52
- package/src/typechecker/statements.js +157 -17
- package/src/typechecker/stdlib/core.js +333 -55
- package/src/typechecker/stdlib/excluded.js +898 -0
- package/src/typechecker/stdlib/extended.js +359 -26
- package/src/typechecker/{stdlib.js → stdlib/index.js} +6 -4
- package/src/typechecker/stdlib/simd.js +123 -0
- package/src/typechecker/termination.js +1 -1
- package/src/typechecker/types.js +165 -26
- package/stdlib/bytes/iter.go +192 -0
- package/stdlib/bytes/search.go +240 -0
- package/stdlib/bytes/split.go +218 -0
- package/stdlib/cmp/cmp.go +65 -0
- package/stdlib/encoding/json/errors.go +31 -0
- package/stdlib/encoding/json/indent.go +71 -0
- package/stdlib/encoding/json/number.go +12 -0
- package/stdlib/encoding/json/stream.go +173 -0
- package/stdlib/errors/overlay.go +12 -0
- package/stdlib/hash/hash.go +53 -0
- package/stdlib/internal/jsonrt/dec.go +738 -0
- package/stdlib/internal/jsonrt/enc.go +366 -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 +649 -0
- package/stdlib/io/io.go +346 -0
- package/stdlib/iter/iter.go +18 -0
- package/stdlib/maps/iter.go +65 -0
- package/stdlib/math/extra.go +270 -0
- package/stdlib/slices/extra.go +73 -0
- package/stdlib/slices/iter.go +113 -0
- package/stdlib/sort/sort.go +561 -0
- package/stdlib/strconv/quote.go +341 -0
- package/stdlib/strings/extra.go +35 -0
- package/stdlib/strings/iter.go +122 -0
- package/stdlib/sync/extra.go +105 -0
- package/stdlib/unicode/unicode.go +112 -0
- package/stdlib/unicode/utf8/bytes.go +239 -0
- package/src/backend/wasm/const-fold.js +0 -205
- package/src/backend/wasm/emit-stdlib.js +0 -13
- /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
- /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
|
@@ -79,10 +79,40 @@ export const statementCheckMethods = {
|
|
|
79
79
|
const name = stmt.lhs[i].name ?? stmt.lhs[i];
|
|
80
80
|
if (name === "_") continue;
|
|
81
81
|
if (scope.symbols.has(name)) stmt.lhs[i]._redecl = true;
|
|
82
|
+
if (stmt.rhs.length === stmt.lhs.length)
|
|
83
|
+
this._checkConstDefault(
|
|
84
|
+
rhsFlat[i],
|
|
85
|
+
stmt.rhs[i],
|
|
86
|
+
"variable declaration",
|
|
87
|
+
);
|
|
82
88
|
scope.defineLocal(name, defaultType(rhsFlat[i]) ?? ANY);
|
|
83
89
|
}
|
|
84
90
|
},
|
|
85
91
|
|
|
92
|
+
_checkDefineCommaOkMap(stmt, scope) {
|
|
93
|
+
if (
|
|
94
|
+
stmt.lhs.length !== 2 ||
|
|
95
|
+
stmt.rhs.length !== 1 ||
|
|
96
|
+
stmt.rhs[0].kind !== "IndexExpr"
|
|
97
|
+
)
|
|
98
|
+
return false;
|
|
99
|
+
const mapBaseType = this.checkExpr(stmt.rhs[0].expr, scope);
|
|
100
|
+
const resolvedBase =
|
|
101
|
+
mapBaseType?.kind === "named" ? mapBaseType.underlying : mapBaseType;
|
|
102
|
+
if (resolvedBase?.kind !== "map") return false;
|
|
103
|
+
const keyType = this.checkExpr(stmt.rhs[0].index, scope);
|
|
104
|
+
this._markIfaceKey(resolvedBase, stmt.rhs[0].index, keyType);
|
|
105
|
+
stmt._commaOkMap = true;
|
|
106
|
+
stmt.rhs[0]._mapValueType = resolvedBase.value;
|
|
107
|
+
this._declareDefineVars(stmt, [resolvedBase.value, BOOL], scope);
|
|
108
|
+
const allRedecl = stmt.lhs.every((e) => e._redecl || (e.name ?? e) === "_");
|
|
109
|
+
if (allRedecl && stmt.lhs.length > 0) {
|
|
110
|
+
this.err("no new variables on left side of :=", stmt.lhs[0]);
|
|
111
|
+
}
|
|
112
|
+
stmt._rhsTypes = [resolvedBase.value, BOOL];
|
|
113
|
+
return true;
|
|
114
|
+
},
|
|
115
|
+
|
|
86
116
|
_checkDefineStmt(stmt, scope) {
|
|
87
117
|
// comma-ok type assertion: n, ok := x.(T)
|
|
88
118
|
if (
|
|
@@ -92,10 +122,24 @@ export const statementCheckMethods = {
|
|
|
92
122
|
) {
|
|
93
123
|
stmt.rhs[0]._commaOk = true;
|
|
94
124
|
}
|
|
125
|
+
if (this._checkDefineCommaOkMap(stmt, scope)) return;
|
|
95
126
|
const rhs = stmt.rhs.map((e) => this.checkExpr(e, scope));
|
|
96
|
-
const
|
|
97
|
-
|
|
127
|
+
const isTuple = rhs.length === 1 && rhs[0]?.kind === "tuple";
|
|
128
|
+
const rhsFlat = isTuple ? rhs[0].types : rhs;
|
|
98
129
|
if (this._checkDefineCommaOkAssert(stmt, rhs, scope)) return;
|
|
130
|
+
if (
|
|
131
|
+
stmt.rhs[0]?.kind !== "RangeExpr" &&
|
|
132
|
+
stmt.lhs.length !== rhsFlat.length
|
|
133
|
+
) {
|
|
134
|
+
const vars =
|
|
135
|
+
stmt.lhs.length === 1 ? "1 variable" : `${stmt.lhs.length} variables`;
|
|
136
|
+
const vals = isTuple
|
|
137
|
+
? `returns ${rhsFlat.length} values`
|
|
138
|
+
: rhsFlat.length === 1
|
|
139
|
+
? "1 value"
|
|
140
|
+
: `${rhsFlat.length} values`;
|
|
141
|
+
this.err(`assignment mismatch: ${vars} but ${vals}`, stmt);
|
|
142
|
+
}
|
|
99
143
|
this._declareDefineVars(stmt, rhsFlat, scope);
|
|
100
144
|
const allRedecl = stmt.lhs.every((e) => e._redecl || (e.name ?? e) === "_");
|
|
101
145
|
if (allRedecl && stmt.lhs.length > 0) {
|
|
@@ -110,15 +154,16 @@ export const statementCheckMethods = {
|
|
|
110
154
|
stmt.rhs.length !== 1 ||
|
|
111
155
|
stmt.rhs[0].kind !== "IndexExpr"
|
|
112
156
|
)
|
|
113
|
-
return
|
|
157
|
+
return null;
|
|
114
158
|
const mapBaseType = this.checkExpr(stmt.rhs[0].expr, scope);
|
|
115
159
|
const resolvedBase =
|
|
116
160
|
mapBaseType?.kind === "named" ? mapBaseType.underlying : mapBaseType;
|
|
117
|
-
if (resolvedBase?.kind !== "map") return
|
|
118
|
-
this.checkExpr(stmt.rhs[0].index, scope);
|
|
161
|
+
if (resolvedBase?.kind !== "map") return null;
|
|
162
|
+
const keyType = this.checkExpr(stmt.rhs[0].index, scope);
|
|
163
|
+
this._markIfaceKey(resolvedBase, stmt.rhs[0].index, keyType);
|
|
119
164
|
stmt._commaOkMap = true;
|
|
120
165
|
stmt.rhs[0]._mapValueType = resolvedBase.value;
|
|
121
|
-
return
|
|
166
|
+
return [resolvedBase.value, BOOL];
|
|
122
167
|
},
|
|
123
168
|
|
|
124
169
|
_checkConstAssignment(stmt, scope) {
|
|
@@ -154,6 +199,16 @@ export const statementCheckMethods = {
|
|
|
154
199
|
this.resolveType(r),
|
|
155
200
|
stmt.rhs[i],
|
|
156
201
|
);
|
|
202
|
+
// A shift count is not converted to the left operand's type.
|
|
203
|
+
if (stmt.op === "<<=" || stmt.op === ">>=") {
|
|
204
|
+
if (r && !isAny(r)) this.checkShiftCount(r, stmt.rhs[i]);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (
|
|
208
|
+
stmt.rhs.length === lhsTypes.length &&
|
|
209
|
+
this._checkConstOverflow(lhsTypes[i], r, stmt.rhs[i], "assignment")
|
|
210
|
+
)
|
|
211
|
+
continue;
|
|
157
212
|
if (!isAny(lhsTypes[i]) && !isAny(r)) {
|
|
158
213
|
this._skipIfaceMark = true;
|
|
159
214
|
this.assertAssignable(lhsTypes[i], r, stmt.lhs[i]);
|
|
@@ -163,12 +218,34 @@ export const statementCheckMethods = {
|
|
|
163
218
|
},
|
|
164
219
|
|
|
165
220
|
_checkAssignStmt(stmt, scope) {
|
|
166
|
-
|
|
221
|
+
const commaOkMapTypes = this._checkAssignCommaOkMap(stmt, scope);
|
|
167
222
|
if (this._isCommaOkTypeAssertAssign(stmt)) stmt.rhs[0]._commaOk = true;
|
|
168
223
|
this._checkConstAssignment(stmt, scope);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
224
|
+
let rhsFlat;
|
|
225
|
+
if (commaOkMapTypes) {
|
|
226
|
+
rhsFlat = commaOkMapTypes;
|
|
227
|
+
} else {
|
|
228
|
+
const rhs = stmt.rhs.map((e) => this.checkExpr(e, scope));
|
|
229
|
+
const isTuple = rhs.length === 1 && rhs[0]?.kind === "tuple";
|
|
230
|
+
rhsFlat = isTuple ? rhs[0].types : rhs;
|
|
231
|
+
if (
|
|
232
|
+
!stmt.rhs[0]?._commaOk &&
|
|
233
|
+
stmt.rhs[0]?.kind !== "RangeExpr" &&
|
|
234
|
+
stmt.lhs.length !== rhsFlat.length
|
|
235
|
+
) {
|
|
236
|
+
const vars =
|
|
237
|
+
stmt.lhs.length === 1 ? "1 variable" : `${stmt.lhs.length} variables`;
|
|
238
|
+
const vals = isTuple
|
|
239
|
+
? `returns ${rhsFlat.length} values`
|
|
240
|
+
: rhsFlat.length === 1
|
|
241
|
+
? "1 value"
|
|
242
|
+
: `${rhsFlat.length} values`;
|
|
243
|
+
this.err(`assignment mismatch: ${vars} but ${vals}`, stmt);
|
|
244
|
+
}
|
|
245
|
+
if (stmt.rhs[0]?._commaOk) {
|
|
246
|
+
rhsFlat = [rhs[0], BOOL];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
172
249
|
const lhsTypes = stmt.lhs.map((e) => this._checkAssignLhsType(e, scope));
|
|
173
250
|
this._checkAssignTypes(stmt, rhsFlat, lhsTypes);
|
|
174
251
|
},
|
|
@@ -187,9 +264,34 @@ export const statementCheckMethods = {
|
|
|
187
264
|
if (!isVoid(returnType) && types.length > 0) {
|
|
188
265
|
const expected =
|
|
189
266
|
returnType.kind === "tuple" ? returnType.types : [returnType];
|
|
267
|
+
// `return f()` forwards every result of a multi-value call.
|
|
268
|
+
if (types.length === 1 && types[0]?.kind === "tuple") {
|
|
269
|
+
const forwarded = types[0].types;
|
|
270
|
+
if (forwarded.length !== expected.length) {
|
|
271
|
+
this.err(
|
|
272
|
+
`return count mismatch: have ${forwarded.length} values, want ${expected.length}`,
|
|
273
|
+
stmt,
|
|
274
|
+
);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
for (let i = 0; i < expected.length; i++) {
|
|
278
|
+
this.assertAssignable(
|
|
279
|
+
expected[i],
|
|
280
|
+
forwarded[i],
|
|
281
|
+
stmt.values[0],
|
|
282
|
+
"return statement",
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
190
287
|
for (let i = 0; i < expected.length; i++) {
|
|
191
288
|
if (types[i])
|
|
192
|
-
this.assertAssignable(
|
|
289
|
+
this.assertAssignable(
|
|
290
|
+
expected[i],
|
|
291
|
+
types[i],
|
|
292
|
+
stmt.values[i] ?? stmt,
|
|
293
|
+
"return statement",
|
|
294
|
+
);
|
|
193
295
|
}
|
|
194
296
|
}
|
|
195
297
|
},
|
|
@@ -229,7 +331,14 @@ export const statementCheckMethods = {
|
|
|
229
331
|
}
|
|
230
332
|
},
|
|
231
333
|
|
|
232
|
-
|
|
334
|
+
// `checkBody(bodyScope)` checks the loop body; templ `for` loops pass one
|
|
335
|
+
// that checks their HTML nodes in place of the header's empty block.
|
|
336
|
+
_checkForStmt(
|
|
337
|
+
stmt,
|
|
338
|
+
scope,
|
|
339
|
+
returnType,
|
|
340
|
+
checkBody = (s) => this.checkBlock(stmt.body, s, returnType),
|
|
341
|
+
) {
|
|
233
342
|
const inner = new Scope(scope);
|
|
234
343
|
let iterInfo = null;
|
|
235
344
|
if (stmt.init?.rhs?.[0]?.kind === "RangeExpr") {
|
|
@@ -240,7 +349,7 @@ export const statementCheckMethods = {
|
|
|
240
349
|
if (stmt.post) this.checkStmt(stmt.post, inner, returnType);
|
|
241
350
|
this._loopDepth++;
|
|
242
351
|
const bodyScope = new Scope(inner);
|
|
243
|
-
|
|
352
|
+
checkBody(bodyScope);
|
|
244
353
|
this._reportUnused(bodyScope, stmt);
|
|
245
354
|
this._loopDepth--;
|
|
246
355
|
this._reportUnused(inner, stmt);
|
|
@@ -261,6 +370,19 @@ export const statementCheckMethods = {
|
|
|
261
370
|
this._reportUnused(inner, stmt);
|
|
262
371
|
},
|
|
263
372
|
|
|
373
|
+
// A case naming an interface (literal or declared) records the resolved
|
|
374
|
+
// type so backends test its method set.
|
|
375
|
+
_markInterfaceCaseType(t, scope) {
|
|
376
|
+
if (!t || (t.kind !== "InterfaceType" && t.kind !== "TypeName")) return;
|
|
377
|
+
if (t.kind === "TypeName" && (t.name === "nil" || t.name === "error"))
|
|
378
|
+
return;
|
|
379
|
+
const resolved = this.resolveTypeNode(t, scope);
|
|
380
|
+
const u = this.resolveType(
|
|
381
|
+
resolved?.kind === "named" ? resolved.underlying : resolved,
|
|
382
|
+
);
|
|
383
|
+
if (u?.kind === "interface") t._type = resolved;
|
|
384
|
+
},
|
|
385
|
+
|
|
264
386
|
_checkTypeSwitchStmt(stmt, scope, returnType) {
|
|
265
387
|
const inner = new Scope(scope);
|
|
266
388
|
this.checkExpr(stmt.expr, inner);
|
|
@@ -268,10 +390,23 @@ export const statementCheckMethods = {
|
|
|
268
390
|
this._typeSwitchDepth++;
|
|
269
391
|
for (const c of stmt.cases) {
|
|
270
392
|
const caseScope = new Scope(inner);
|
|
393
|
+
// Resolve instantiated generic case types so backends can tell
|
|
394
|
+
// `*Stack[int]` from `*Stack[string]`.
|
|
395
|
+
for (const t of c.types ?? []) {
|
|
396
|
+
const base = t?.kind === "PointerType" ? t.base : t;
|
|
397
|
+
if (base?.kind === "GenericTypeName") this.resolveTypeNode(t, inner);
|
|
398
|
+
this._markInterfaceCaseType(t, inner);
|
|
399
|
+
}
|
|
271
400
|
if (stmt.assign) {
|
|
272
|
-
// Bind the variable to the single case type, or any for multi/default
|
|
273
|
-
|
|
274
|
-
|
|
401
|
+
// Bind the variable to the single case type, or any for multi/default.
|
|
402
|
+
// `case nil` binds the switch expression's own type, as in Go.
|
|
403
|
+
const only = c.types?.length === 1 ? c.types[0] : null;
|
|
404
|
+
const isNilCase = only?.kind === "TypeName" && only.name === "nil";
|
|
405
|
+
const bindType = isNilCase
|
|
406
|
+
? (stmt.expr._type ?? ANY)
|
|
407
|
+
: only
|
|
408
|
+
? this.resolveTypeNode(only, inner)
|
|
409
|
+
: ANY;
|
|
275
410
|
caseScope.defineLocal(stmt.assign, bindType);
|
|
276
411
|
// The capture variable is always considered used — it's the whole
|
|
277
412
|
// point of the switch-with-assign form. Each case body uses its own
|
|
@@ -287,7 +422,12 @@ export const statementCheckMethods = {
|
|
|
287
422
|
|
|
288
423
|
_checkBranchStmt(stmt) {
|
|
289
424
|
const kw = stmt.keyword;
|
|
290
|
-
if (kw === "
|
|
425
|
+
if (kw === "goto")
|
|
426
|
+
this.err(
|
|
427
|
+
"goto is not supported; restructure with labeled break/continue",
|
|
428
|
+
stmt,
|
|
429
|
+
);
|
|
430
|
+
else if (kw === "continue" && this._loopDepth === 0)
|
|
291
431
|
this.err("continue statement outside for loop", stmt);
|
|
292
432
|
else if (kw === "break" && this._loopDepth === 0 && this._switchDepth === 0)
|
|
293
433
|
this.err("break statement outside for loop or switch", stmt);
|