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
package/src/typechecker/types.js
CHANGED
|
@@ -102,7 +102,7 @@ export const BROWSER_GLOBALS = new Set([
|
|
|
102
102
|
"TextDecoder",
|
|
103
103
|
]);
|
|
104
104
|
|
|
105
|
-
// Stdlib packages the WASM backend can emit. Extend as src/backend/wasm/
|
|
105
|
+
// Stdlib packages the WASM backend can emit. Extend as src/backend/wasm/stdlib/
|
|
106
106
|
// gains support; anything not listed is rejected at import with "not yet available in
|
|
107
107
|
// wasm packages".
|
|
108
108
|
export const WASM_SUPPORTED_STDLIB = new Set([
|
|
@@ -126,17 +126,19 @@ export const WASM_SUPPORTED_STDLIB = new Set([
|
|
|
126
126
|
"time",
|
|
127
127
|
"testing",
|
|
128
128
|
"gofront/shared",
|
|
129
|
+
"gofront/simd",
|
|
129
130
|
"sync",
|
|
130
131
|
"crypto/rand",
|
|
131
132
|
"crypto/sha256",
|
|
132
133
|
"encoding/binary",
|
|
133
134
|
"encoding/hex",
|
|
134
135
|
"encoding/base64",
|
|
136
|
+
"os",
|
|
137
|
+
"encoding/json",
|
|
135
138
|
]);
|
|
136
139
|
|
|
137
140
|
export const STDLIB_PACKAGES = new Set([
|
|
138
141
|
...WASM_SUPPORTED_STDLIB,
|
|
139
|
-
"os",
|
|
140
142
|
"gom",
|
|
141
143
|
"regexp",
|
|
142
144
|
]);
|
|
@@ -145,6 +147,7 @@ export const STDLIB_PACKAGES = new Set([
|
|
|
145
147
|
// member the checker knows about. Members outside the set are rejected in
|
|
146
148
|
// wasm/both packages with "'strings.Split' is not yet available in wasm packages".
|
|
147
149
|
export const WASM_STDLIB_MEMBERS = new Map([
|
|
150
|
+
["os", new Set(["Stdout", "Stderr", "Stdin", "File"])],
|
|
148
151
|
[
|
|
149
152
|
"math",
|
|
150
153
|
new Set([
|
|
@@ -176,8 +179,10 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
176
179
|
"Exp",
|
|
177
180
|
"Exp2",
|
|
178
181
|
"Log",
|
|
182
|
+
"Log1p",
|
|
179
183
|
"Log2",
|
|
180
184
|
"Log10",
|
|
185
|
+
"Expm1",
|
|
181
186
|
"Round",
|
|
182
187
|
"Remainder",
|
|
183
188
|
"Float64bits",
|
|
@@ -223,21 +228,56 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
223
228
|
[
|
|
224
229
|
"bits",
|
|
225
230
|
new Set([
|
|
231
|
+
"Add",
|
|
232
|
+
"Add32",
|
|
233
|
+
"Add64",
|
|
234
|
+
"Sub",
|
|
235
|
+
"Sub32",
|
|
236
|
+
"Sub64",
|
|
237
|
+
"Mul",
|
|
238
|
+
"Mul32",
|
|
239
|
+
"Mul64",
|
|
240
|
+
"Div",
|
|
241
|
+
"Div32",
|
|
242
|
+
"Div64",
|
|
243
|
+
"Rem",
|
|
244
|
+
"Rem32",
|
|
245
|
+
"Rem64",
|
|
246
|
+
"LeadingZeros",
|
|
247
|
+
"LeadingZeros8",
|
|
248
|
+
"LeadingZeros16",
|
|
226
249
|
"LeadingZeros32",
|
|
227
250
|
"LeadingZeros64",
|
|
251
|
+
"TrailingZeros",
|
|
252
|
+
"TrailingZeros8",
|
|
253
|
+
"TrailingZeros16",
|
|
228
254
|
"TrailingZeros32",
|
|
229
255
|
"TrailingZeros64",
|
|
256
|
+
"OnesCount",
|
|
257
|
+
"OnesCount8",
|
|
258
|
+
"OnesCount16",
|
|
230
259
|
"OnesCount32",
|
|
231
260
|
"OnesCount64",
|
|
261
|
+
"RotateLeft",
|
|
262
|
+
"RotateLeft8",
|
|
263
|
+
"RotateLeft16",
|
|
232
264
|
"RotateLeft32",
|
|
233
265
|
"RotateLeft64",
|
|
266
|
+
"Reverse",
|
|
267
|
+
"Reverse8",
|
|
268
|
+
"Reverse16",
|
|
269
|
+
"Reverse32",
|
|
270
|
+
"Reverse64",
|
|
271
|
+
"ReverseBytes",
|
|
234
272
|
"ReverseBytes16",
|
|
235
273
|
"ReverseBytes32",
|
|
236
274
|
"ReverseBytes64",
|
|
275
|
+
"Len",
|
|
276
|
+
"Len8",
|
|
277
|
+
"Len16",
|
|
237
278
|
"Len32",
|
|
238
279
|
"Len64",
|
|
239
|
-
"
|
|
240
|
-
"Reverse64",
|
|
280
|
+
"UintSize",
|
|
241
281
|
]),
|
|
242
282
|
],
|
|
243
283
|
["errors", new Set(["New", "Is", "Unwrap", "As", "Join"])],
|
|
@@ -254,6 +294,15 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
254
294
|
"RuneError",
|
|
255
295
|
"MaxRune",
|
|
256
296
|
"UTFMax",
|
|
297
|
+
"RuneSelf",
|
|
298
|
+
"EncodeRune",
|
|
299
|
+
"AppendRune",
|
|
300
|
+
"DecodeRune",
|
|
301
|
+
"DecodeLastRune",
|
|
302
|
+
"RuneCount",
|
|
303
|
+
"FullRune",
|
|
304
|
+
"Valid",
|
|
305
|
+
"RuneStart",
|
|
257
306
|
]),
|
|
258
307
|
],
|
|
259
308
|
[
|
|
@@ -275,6 +324,11 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
275
324
|
"fmt",
|
|
276
325
|
new Set([
|
|
277
326
|
"Sprintf",
|
|
327
|
+
"Sprint",
|
|
328
|
+
"Sprintln",
|
|
329
|
+
"Append",
|
|
330
|
+
"Appendf",
|
|
331
|
+
"Appendln",
|
|
278
332
|
"Errorf",
|
|
279
333
|
"Printf",
|
|
280
334
|
"Println",
|
|
@@ -285,6 +339,7 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
285
339
|
"Sscan",
|
|
286
340
|
"Sscanln",
|
|
287
341
|
"Sscanf",
|
|
342
|
+
"Stringer",
|
|
288
343
|
]),
|
|
289
344
|
],
|
|
290
345
|
[
|
|
@@ -334,9 +389,11 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
334
389
|
"TrimRightFunc",
|
|
335
390
|
"FieldsFunc",
|
|
336
391
|
"NewReplacer",
|
|
392
|
+
"Replacer",
|
|
337
393
|
"Builder",
|
|
338
394
|
"NewReader",
|
|
339
395
|
"Reader",
|
|
396
|
+
"ToValidUTF8",
|
|
340
397
|
]),
|
|
341
398
|
],
|
|
342
399
|
[
|
|
@@ -360,6 +417,20 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
360
417
|
"AppendBool",
|
|
361
418
|
"ErrSyntax",
|
|
362
419
|
"ErrRange",
|
|
420
|
+
"IntSize",
|
|
421
|
+
"NumError",
|
|
422
|
+
"QuoteRune",
|
|
423
|
+
"QuoteToASCII",
|
|
424
|
+
"QuoteRuneToASCII",
|
|
425
|
+
"AppendQuote",
|
|
426
|
+
"AppendQuoteToASCII",
|
|
427
|
+
"AppendQuoteRune",
|
|
428
|
+
"AppendQuoteRuneToASCII",
|
|
429
|
+
"CanBackquote",
|
|
430
|
+
"UnquoteChar",
|
|
431
|
+
"QuotedPrefix",
|
|
432
|
+
"IsPrint",
|
|
433
|
+
"IsGraphic",
|
|
363
434
|
]),
|
|
364
435
|
],
|
|
365
436
|
[
|
|
@@ -397,16 +468,7 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
397
468
|
],
|
|
398
469
|
[
|
|
399
470
|
"maps",
|
|
400
|
-
new Set([
|
|
401
|
-
"Keys",
|
|
402
|
-
"Values",
|
|
403
|
-
"Clone",
|
|
404
|
-
"Copy",
|
|
405
|
-
"Equal",
|
|
406
|
-
"EqualFunc",
|
|
407
|
-
"Delete",
|
|
408
|
-
"DeleteFunc",
|
|
409
|
-
]),
|
|
471
|
+
new Set(["Clone", "Copy", "Equal", "EqualFunc", "Delete", "DeleteFunc"]),
|
|
410
472
|
],
|
|
411
473
|
[
|
|
412
474
|
"unicode",
|
|
@@ -478,8 +540,11 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
478
540
|
"Map",
|
|
479
541
|
"SplitN",
|
|
480
542
|
"Buffer",
|
|
543
|
+
"NewBuffer",
|
|
544
|
+
"NewBufferString",
|
|
481
545
|
"NewReader",
|
|
482
546
|
"Reader",
|
|
547
|
+
"ToValidUTF8",
|
|
483
548
|
]),
|
|
484
549
|
],
|
|
485
550
|
[
|
|
@@ -519,9 +584,6 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
519
584
|
"ReadWriter",
|
|
520
585
|
"Closer",
|
|
521
586
|
"EOF",
|
|
522
|
-
"ErrUnexpectedEOF",
|
|
523
|
-
"ErrShortWrite",
|
|
524
|
-
"ReadFull",
|
|
525
587
|
"ReadAll",
|
|
526
588
|
"Discard",
|
|
527
589
|
"WriteString",
|
|
@@ -536,10 +598,12 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
536
598
|
"Now",
|
|
537
599
|
"Since",
|
|
538
600
|
"Parse",
|
|
601
|
+
"ParseDuration",
|
|
539
602
|
"Unix",
|
|
540
603
|
"UnixMicro",
|
|
541
604
|
"UnixMilli",
|
|
542
605
|
"Date",
|
|
606
|
+
"FixedZone",
|
|
543
607
|
"Duration",
|
|
544
608
|
"Nanosecond",
|
|
545
609
|
"Microsecond",
|
|
@@ -574,9 +638,12 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
574
638
|
"Friday",
|
|
575
639
|
"Saturday",
|
|
576
640
|
"Time",
|
|
641
|
+
"Month",
|
|
642
|
+
"Weekday",
|
|
643
|
+
"Location",
|
|
577
644
|
]),
|
|
578
645
|
],
|
|
579
|
-
["testing", new Set(["T"])],
|
|
646
|
+
["testing", new Set(["T", "B", "M", "TB", "BenchmarkResult"])],
|
|
580
647
|
["sync", new Set(["Mutex", "RWMutex", "Once", "WaitGroup", "Locker"])],
|
|
581
648
|
["sha256", new Set(["Sum256", "New", "Size", "BlockSize"])],
|
|
582
649
|
[
|
|
@@ -622,6 +689,11 @@ export const WASM_STDLIB_MEMBERS = new Map([
|
|
|
622
689
|
|
|
623
690
|
export const VALID_TARGETS = new Set(["js", "wasm", "both"]);
|
|
624
691
|
|
|
692
|
+
// Backend-provided implementations for body-less Go-source stdlib functions
|
|
693
|
+
// marked `//gofront:intrinsic <name>`: name -> required signature. New
|
|
694
|
+
// intrinsics need a plan change.
|
|
695
|
+
export const INTRINSICS = new Map([]);
|
|
696
|
+
|
|
625
697
|
// ── Static operator sets (module-level for reuse) ────────────
|
|
626
698
|
export const CMP_OPS = new Set(["==", "!=", "<", ">", "<=", ">="]);
|
|
627
699
|
export const LOG_OPS = new Set(["&&", "||"]);
|
|
@@ -666,7 +738,7 @@ export const UNTYPED_BOOL = { kind: "untyped", base: "bool" };
|
|
|
666
738
|
|
|
667
739
|
// ── Complex types ────────────────────────────────────────────
|
|
668
740
|
export const COMPLEX128 = { kind: "basic", name: "complex128" };
|
|
669
|
-
const COMPLEX64 = { kind: "basic", name: "complex64" };
|
|
741
|
+
export const COMPLEX64 = { kind: "basic", name: "complex64" };
|
|
670
742
|
export const UNTYPED_COMPLEX = { kind: "untyped", base: "complex128" };
|
|
671
743
|
|
|
672
744
|
export const BASIC_TYPES = {
|
|
@@ -747,6 +819,32 @@ const TYPED_ARRAY_CONSTRUCTORS = {
|
|
|
747
819
|
rune: "Int32Array",
|
|
748
820
|
};
|
|
749
821
|
|
|
822
|
+
// Element indices of an array or slice literal (Go spec): `i: v` puts v at
|
|
823
|
+
// index i, any other element goes right after the previous one, so
|
|
824
|
+
// `[5]int{1, 3: 4, 5}` fills indices 0, 3 and 4. Array literal keys are
|
|
825
|
+
// resolved by the type checker (`_index`, which handles named constants and
|
|
826
|
+
// constant expressions); otherwise only integer-literal keys are known and
|
|
827
|
+
// another key is treated as a positional element.
|
|
828
|
+
export function compositeLitIndices(elems) {
|
|
829
|
+
const out = [];
|
|
830
|
+
let next = 0;
|
|
831
|
+
for (const e of elems) {
|
|
832
|
+
if (e.kind === "KeyValueExpr" && e._index !== undefined) next = e._index;
|
|
833
|
+
else if (e.kind === "KeyValueExpr" && e.key?.value !== undefined)
|
|
834
|
+
next = Number(e.key.value);
|
|
835
|
+
out.push(next++);
|
|
836
|
+
}
|
|
837
|
+
return out;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Highest element index of an array or slice literal (-1 when empty). A
|
|
841
|
+
// loop, not `Math.max(...)`: spreading a huge literal overflows the stack.
|
|
842
|
+
export function compositeLitMaxIndex(elems) {
|
|
843
|
+
let max = -1;
|
|
844
|
+
for (const i of compositeLitIndices(elems)) if (i > max) max = i;
|
|
845
|
+
return max;
|
|
846
|
+
}
|
|
847
|
+
|
|
750
848
|
export function typedArrayConstructorForElem(elemType) {
|
|
751
849
|
if (!elemType) return null;
|
|
752
850
|
const name = elemType.kind === "basic" ? elemType.name : null;
|
|
@@ -762,12 +860,28 @@ export function isTypedArraySlice(type) {
|
|
|
762
860
|
|
|
763
861
|
export function isComplex(t) {
|
|
764
862
|
if (!t) return false;
|
|
765
|
-
if (
|
|
863
|
+
if (
|
|
864
|
+
(t.kind === "basic" || t.kind === "TypeName" || t.kind === "Ident") &&
|
|
865
|
+
(t.name === "complex128" || t.name === "complex64")
|
|
866
|
+
)
|
|
766
867
|
return true;
|
|
767
868
|
if (t.kind === "untyped" && t.base === "complex128") return true;
|
|
768
869
|
if (t.kind === "named") return isComplex(t.underlying);
|
|
769
870
|
return false;
|
|
770
871
|
}
|
|
872
|
+
export function isComplex64(t) {
|
|
873
|
+
if (!t) return false;
|
|
874
|
+
if (
|
|
875
|
+
(t.kind === "basic" || t.kind === "TypeName" || t.kind === "Ident") &&
|
|
876
|
+
t.name === "complex64"
|
|
877
|
+
)
|
|
878
|
+
return true;
|
|
879
|
+
if (t.kind === "untyped" && t.base === "complex64") return true;
|
|
880
|
+
if (t.kind === "named") return isComplex64(t.underlying);
|
|
881
|
+
if (t.name === "complex64") return true;
|
|
882
|
+
if (t.underlying) return isComplex64(t.underlying);
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
771
885
|
export function isComplexOrNumeric(t) {
|
|
772
886
|
return isNumeric(t) || isComplex(t);
|
|
773
887
|
}
|
|
@@ -839,14 +953,21 @@ export function typeStr(t) {
|
|
|
839
953
|
return t.name || "interface{...}";
|
|
840
954
|
case "namespace":
|
|
841
955
|
return t.name || "namespace{...}";
|
|
842
|
-
case "func":
|
|
843
|
-
|
|
956
|
+
case "func": {
|
|
957
|
+
const retStr =
|
|
958
|
+
t.returns.length > 1
|
|
959
|
+
? `(${t.returns.map(typeStr).join(", ")})`
|
|
960
|
+
: typeStr(t.returns[0] ?? VOID);
|
|
961
|
+
return `func(${t.params.map(typeStr).join(", ")}) ${retStr}`;
|
|
962
|
+
}
|
|
844
963
|
case "tuple":
|
|
845
964
|
return `(${t.types.map(typeStr).join(", ")})`;
|
|
846
|
-
case "named":
|
|
965
|
+
case "named": {
|
|
966
|
+
const name = displayTypeName(t.name);
|
|
847
967
|
return t.typeArgs && t.typeArgs.length > 0
|
|
848
|
-
? `${
|
|
849
|
-
:
|
|
968
|
+
? `${name}[${t.typeArgs.map(typeStr).join(", ")}]`
|
|
969
|
+
: name;
|
|
970
|
+
}
|
|
850
971
|
case "pointer":
|
|
851
972
|
return `*${typeStr(t.base)}`;
|
|
852
973
|
case "typeParam":
|
|
@@ -858,6 +979,17 @@ export function typeStr(t) {
|
|
|
858
979
|
}
|
|
859
980
|
}
|
|
860
981
|
|
|
982
|
+
// Go-source stdlib names are mangled to `Name$$path` (`List$$container$list`);
|
|
983
|
+
// diagnostics show them qualified, as Go does (`list.List`).
|
|
984
|
+
export function displayTypeName(name) {
|
|
985
|
+
const i = typeof name === "string" ? name.indexOf("$$") : -1;
|
|
986
|
+
if (i < 0) return name;
|
|
987
|
+
return `${name
|
|
988
|
+
.slice(i + 2)
|
|
989
|
+
.split("$")
|
|
990
|
+
.at(-1)}.${name.slice(0, i)}`;
|
|
991
|
+
}
|
|
992
|
+
|
|
861
993
|
// ── Iterator function detection (Go 1.23 range-over-func) ───
|
|
862
994
|
|
|
863
995
|
/**
|
|
@@ -887,6 +1019,7 @@ export class Scope {
|
|
|
887
1019
|
this.parent = parent;
|
|
888
1020
|
this.symbols = new Map();
|
|
889
1021
|
this._consts = new Set(); // names declared as const in this scope
|
|
1022
|
+
this._constExprs = new Map(); // name -> AST initializer expr
|
|
890
1023
|
this._locals = new Set(); // names declared as local variables (var / :=)
|
|
891
1024
|
this._used = new Set(); // names referenced in this scope
|
|
892
1025
|
}
|
|
@@ -897,9 +1030,15 @@ export class Scope {
|
|
|
897
1030
|
this.symbols.set(name, type);
|
|
898
1031
|
if (name !== "_") this._locals.add(name);
|
|
899
1032
|
}
|
|
900
|
-
defineConst(name, type) {
|
|
1033
|
+
defineConst(name, type, expr = null) {
|
|
901
1034
|
this.symbols.set(name, type);
|
|
902
1035
|
this._consts.add(name);
|
|
1036
|
+
if (expr) this._constExprs.set(name, expr);
|
|
1037
|
+
}
|
|
1038
|
+
lookupConstExpr(name) {
|
|
1039
|
+
if (this._constExprs.has(name)) return this._constExprs.get(name);
|
|
1040
|
+
if (this.parent) return this.parent.lookupConstExpr(name);
|
|
1041
|
+
return null;
|
|
903
1042
|
}
|
|
904
1043
|
isConst(name) {
|
|
905
1044
|
if (this._consts.has(name)) return true;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Overlay on the emitter-backed bytes package: the sequence members of
|
|
6
|
+
// Go 1.24 are written in Go over iter.Seq and merged into the bytes
|
|
7
|
+
// namespace. Like Go's, the slices they yield alias the input and have their
|
|
8
|
+
// capacity clipped, so appending to one does not write into the original.
|
|
9
|
+
package bytes
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
"iter"
|
|
13
|
+
"unicode"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
const (
|
|
17
|
+
runeError = 0xFFFD
|
|
18
|
+
runeSelf = 0x80
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
// decodeRune unpacks the first UTF-8 encoding in p and returns the rune and
|
|
22
|
+
// its width in bytes, as utf8.DecodeRune does: an invalid or incomplete
|
|
23
|
+
// encoding is (RuneError, 1) and p must not be empty.
|
|
24
|
+
func decodeRune(p []byte) (rune, int) {
|
|
25
|
+
b0 := int(p[0])
|
|
26
|
+
if b0 < runeSelf {
|
|
27
|
+
return rune(b0), 1
|
|
28
|
+
}
|
|
29
|
+
n, lo, mask := 0, 0, 0
|
|
30
|
+
if b0 >= 0xC2 && b0 <= 0xDF {
|
|
31
|
+
n, lo, mask = 2, 0x80, 0x1F
|
|
32
|
+
} else if b0 >= 0xE0 && b0 <= 0xEF {
|
|
33
|
+
n, lo, mask = 3, 0x800, 0x0F
|
|
34
|
+
} else if b0 >= 0xF0 && b0 <= 0xF4 {
|
|
35
|
+
n, lo, mask = 4, 0x10000, 0x07
|
|
36
|
+
} else {
|
|
37
|
+
return runeError, 1
|
|
38
|
+
}
|
|
39
|
+
if len(p) < n {
|
|
40
|
+
return runeError, 1
|
|
41
|
+
}
|
|
42
|
+
r := b0 & mask
|
|
43
|
+
for i := 1; i < n; i++ {
|
|
44
|
+
b := int(p[i])
|
|
45
|
+
if b&0xC0 != 0x80 {
|
|
46
|
+
return runeError, 1
|
|
47
|
+
}
|
|
48
|
+
r = r<<6 | b&0x3F
|
|
49
|
+
}
|
|
50
|
+
if r < lo || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF) {
|
|
51
|
+
return runeError, 1
|
|
52
|
+
}
|
|
53
|
+
return rune(r), n
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// index returns the byte offset of the first instance of sep in s, or -1.
|
|
57
|
+
// It compares bytes: the emitter's bytes.Index goes through a decoded JS
|
|
58
|
+
// string on the JS backend and so counts characters, not bytes, once s holds
|
|
59
|
+
// multi-byte text. sep must not be empty.
|
|
60
|
+
func index(s, sep []byte) int {
|
|
61
|
+
first := sep[0]
|
|
62
|
+
for i := 0; i+len(sep) <= len(s); i++ {
|
|
63
|
+
if s[i] != first {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
j := 1
|
|
67
|
+
for j < len(sep) && s[i+j] == sep[j] {
|
|
68
|
+
j++
|
|
69
|
+
}
|
|
70
|
+
if j == len(sep) {
|
|
71
|
+
return i
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return -1
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// isSpace is unicode.IsSpace as a func(rune) bool (the checker types the
|
|
78
|
+
// unicode predicates over int).
|
|
79
|
+
func isSpace(r rune) bool {
|
|
80
|
+
return unicode.IsSpace(int(r))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Lines returns an iterator over the newline-terminated lines in the byte slice s.
|
|
84
|
+
// The lines yielded by the iterator include their terminating newlines.
|
|
85
|
+
// If s is empty, the iterator yields no lines at all.
|
|
86
|
+
// If s does not end in a newline, the final yielded line will not end in a newline.
|
|
87
|
+
// The iterator yields slices of the original slice s.
|
|
88
|
+
func Lines(s []byte) iter.Seq[[]byte] {
|
|
89
|
+
return func(yield func([]byte) bool) {
|
|
90
|
+
for len(s) > 0 {
|
|
91
|
+
var line []byte
|
|
92
|
+
if i := IndexByte(s, '\n'); i >= 0 {
|
|
93
|
+
line, s = s[:i+1:i+1], s[i+1:]
|
|
94
|
+
} else {
|
|
95
|
+
line, s = s[:len(s):len(s)], nil
|
|
96
|
+
}
|
|
97
|
+
if !yield(line) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// explodeSeq returns an iterator over the UTF-8 encodings of the runes in s.
|
|
105
|
+
func explodeSeq(s []byte) iter.Seq[[]byte] {
|
|
106
|
+
return func(yield func([]byte) bool) {
|
|
107
|
+
for len(s) > 0 {
|
|
108
|
+
_, size := decodeRune(s)
|
|
109
|
+
if !yield(s[:size:size]) {
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
s = s[size:]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// splitSeq is SplitSeq or SplitAfterSeq, configured by how many
|
|
118
|
+
// bytes of sep to include in the results (none or all).
|
|
119
|
+
func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] {
|
|
120
|
+
if len(sep) == 0 {
|
|
121
|
+
return explodeSeq(s)
|
|
122
|
+
}
|
|
123
|
+
return func(yield func([]byte) bool) {
|
|
124
|
+
for {
|
|
125
|
+
i := index(s, sep)
|
|
126
|
+
if i < 0 {
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
frag := s[:i+sepSave]
|
|
130
|
+
if !yield(frag[:len(frag):len(frag)]) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
s = s[i+len(sep):]
|
|
134
|
+
}
|
|
135
|
+
yield(s[:len(s):len(s)])
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// SplitSeq returns an iterator over subslices of s split around sep.
|
|
140
|
+
// The iterator yields the same subslices that would be returned by Split(s, sep),
|
|
141
|
+
// but without constructing the slice.
|
|
142
|
+
// It returns a single-use iterator.
|
|
143
|
+
func SplitSeq(s, sep []byte) iter.Seq[[]byte] {
|
|
144
|
+
return splitSeq(s, sep, 0)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// SplitAfterSeq returns an iterator over subslices of s split after each instance of sep.
|
|
148
|
+
// The iterator yields the same subslices that would be returned by SplitAfter(s, sep),
|
|
149
|
+
// but without constructing the slice.
|
|
150
|
+
// It returns a single-use iterator.
|
|
151
|
+
func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] {
|
|
152
|
+
return splitSeq(s, sep, len(sep))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// FieldsSeq returns an iterator over subslices of s split around runs of
|
|
156
|
+
// whitespace characters, as defined by unicode.IsSpace.
|
|
157
|
+
// The iterator yields the same subslices that would be returned by Fields(s),
|
|
158
|
+
// but without constructing the slice.
|
|
159
|
+
func FieldsSeq(s []byte) iter.Seq[[]byte] {
|
|
160
|
+
return FieldsFuncSeq(s, isSpace)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// FieldsFuncSeq returns an iterator over subslices of s split around runs of
|
|
164
|
+
// Unicode code points satisfying f(c).
|
|
165
|
+
// The iterator yields the same subslices that would be returned by FieldsFunc(s),
|
|
166
|
+
// but without constructing the slice.
|
|
167
|
+
func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
|
|
168
|
+
return func(yield func([]byte) bool) {
|
|
169
|
+
start := -1
|
|
170
|
+
for i := 0; i < len(s); {
|
|
171
|
+
size := 1
|
|
172
|
+
r := rune(s[i])
|
|
173
|
+
if r >= runeSelf {
|
|
174
|
+
r, size = decodeRune(s[i:])
|
|
175
|
+
}
|
|
176
|
+
if f(r) {
|
|
177
|
+
if start >= 0 {
|
|
178
|
+
if !yield(s[start:i:i]) {
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
start = -1
|
|
182
|
+
}
|
|
183
|
+
} else if start < 0 {
|
|
184
|
+
start = i
|
|
185
|
+
}
|
|
186
|
+
i += size
|
|
187
|
+
}
|
|
188
|
+
if start >= 0 {
|
|
189
|
+
yield(s[start:len(s):len(s)])
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|