gofront 1.7.0 → 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.
Files changed (128) hide show
  1. package/README.md +13 -13
  2. package/package.json +8 -37
  3. package/src/backend/js/expressions.js +1341 -148
  4. package/src/backend/js/fmt-runtime.js +573 -0
  5. package/src/backend/js/index.js +375 -57
  6. package/src/backend/js/runtime.js +1460 -133
  7. package/src/backend/js/statements.js +900 -86
  8. package/src/backend/js/stdlib/bits.js +87 -14
  9. package/src/backend/js/stdlib/builder.js +41 -6
  10. package/src/backend/js/stdlib/bytes.js +253 -7
  11. package/src/backend/js/stdlib/errors.js +2 -1
  12. package/src/backend/js/stdlib/fmt.js +349 -10
  13. package/src/backend/js/stdlib/index.js +8 -3
  14. package/src/backend/js/stdlib/json.js +247 -52
  15. package/src/backend/js/stdlib/maps.js +0 -8
  16. package/src/backend/js/stdlib/math.js +17 -1
  17. package/src/backend/js/stdlib/simd.js +10 -0
  18. package/src/backend/js/stdlib/slices.js +36 -6
  19. package/src/backend/js/stdlib/strconv.js +10 -5
  20. package/src/backend/js/stdlib/strings.js +83 -4
  21. package/src/backend/js/stdlib/testing.js +7 -0
  22. package/src/backend/js/stdlib/time.js +79 -55
  23. package/src/backend/js/stdlib/unicode.js +1 -1
  24. package/src/backend/js/stdlib/utf8.js +1 -1
  25. package/src/backend/js/templ.js +38 -76
  26. package/src/backend/js/type-info.js +272 -0
  27. package/src/backend/shared/fmt-types.js +188 -0
  28. package/src/backend/wasm/boundary.js +436 -80
  29. package/src/backend/wasm/emit-builtins.js +303 -13
  30. package/src/backend/wasm/emit-exprs.js +1397 -203
  31. package/src/backend/wasm/emit-maps.js +61 -13
  32. package/src/backend/wasm/emit-stmts.js +1359 -164
  33. package/src/backend/wasm/emit.js +512 -77
  34. package/src/backend/wasm/encode.js +43 -13
  35. package/src/backend/wasm/globals.js +452 -0
  36. package/src/backend/wasm/index.js +194 -2489
  37. package/src/backend/wasm/method-expr.js +381 -0
  38. package/src/backend/wasm/module-emitter.js +2240 -0
  39. package/src/backend/wasm/monomorph.js +62 -4
  40. package/src/backend/wasm/prescan.js +397 -0
  41. package/src/backend/wasm/stdlib/bytes.js +1804 -127
  42. package/src/backend/wasm/stdlib/core.js +1574 -199
  43. package/src/backend/wasm/stdlib/index.js +0 -5
  44. package/src/backend/wasm/stdlib/io.js +1567 -150
  45. package/src/backend/wasm/stdlib/packages.js +2 -0
  46. package/src/backend/wasm/stdlib/simd.js +293 -28
  47. package/src/backend/wasm/stdlib/time.js +1041 -12
  48. package/src/backend/wasm/types.js +200 -15
  49. package/src/backend/wasm/variadic.js +93 -0
  50. package/src/backend/wasm/wat.js +47 -20
  51. package/src/{cli-core.js → cli/cli-core.js} +236 -10
  52. package/src/{test-runner.js → cli/test-runner.js} +332 -39
  53. package/src/{vendor.js → cli/vendor.js} +3 -4
  54. package/src/compiler.js +107 -269
  55. package/src/index.js +15 -169
  56. package/src/{lexer.js → lexer/lexer.js} +102 -55
  57. package/src/{tokens.js → lexer/tokens.js} +1 -0
  58. package/src/link/sourcemap.js +97 -0
  59. package/src/link/stdlib.js +515 -0
  60. package/src/link/wasm.js +294 -0
  61. package/src/lower/bounds.js +394 -0
  62. package/src/lower/boxing.js +1 -1
  63. package/src/lower/captures.js +176 -32
  64. package/src/lower/index.js +26 -18
  65. package/src/lower/json-codecs.js +1398 -0
  66. package/src/lower/ownership.js +22 -1
  67. package/src/lower/range.js +86 -1
  68. package/src/lower/reachability.js +132 -0
  69. package/src/parser/declarations.js +58 -13
  70. package/src/parser/expressions.js +29 -7
  71. package/src/parser/index.js +2 -1
  72. package/src/parser/statements.js +37 -22
  73. package/src/{templ-parser.js → parser/templ.js} +138 -15
  74. package/src/parser/types.js +69 -9
  75. package/src/resolver.js +22 -1
  76. package/src/typechecker/assignability.js +176 -17
  77. package/src/typechecker/const-fold.js +356 -0
  78. package/src/typechecker/constants.js +256 -0
  79. package/src/typechecker/expressions.js +931 -122
  80. package/src/typechecker/index.js +459 -67
  81. package/src/typechecker/init-order.js +330 -0
  82. package/src/typechecker/resolve.js +451 -56
  83. package/src/typechecker/statements.js +90 -9
  84. package/src/typechecker/stdlib/core.js +333 -55
  85. package/src/typechecker/stdlib/excluded.js +898 -0
  86. package/src/typechecker/stdlib/extended.js +322 -26
  87. package/src/typechecker/{stdlib.js → stdlib/index.js} +5 -5
  88. package/src/typechecker/stdlib/simd.js +65 -15
  89. package/src/typechecker/termination.js +1 -1
  90. package/src/typechecker/types.js +149 -25
  91. package/stdlib/bytes/iter.go +192 -0
  92. package/stdlib/bytes/search.go +240 -0
  93. package/stdlib/bytes/split.go +218 -0
  94. package/stdlib/cmp/cmp.go +65 -0
  95. package/stdlib/encoding/json/errors.go +31 -0
  96. package/stdlib/encoding/json/indent.go +71 -0
  97. package/stdlib/encoding/json/number.go +12 -0
  98. package/stdlib/encoding/json/stream.go +173 -0
  99. package/stdlib/errors/overlay.go +12 -0
  100. package/stdlib/hash/hash.go +53 -0
  101. package/stdlib/internal/jsonrt/dec.go +738 -0
  102. package/stdlib/internal/jsonrt/enc.go +366 -0
  103. package/stdlib/internal/jsonrt/indent.go +135 -0
  104. package/stdlib/internal/jsonrt/number.go +27 -0
  105. package/stdlib/internal/jsonrt/reader.go +73 -0
  106. package/stdlib/internal/jsonrt/scanner.go +649 -0
  107. package/stdlib/io/io.go +346 -0
  108. package/stdlib/iter/iter.go +18 -0
  109. package/stdlib/maps/iter.go +65 -0
  110. package/stdlib/math/extra.go +270 -0
  111. package/stdlib/slices/extra.go +73 -0
  112. package/stdlib/slices/iter.go +113 -0
  113. package/stdlib/sort/sort.go +561 -0
  114. package/stdlib/strconv/quote.go +341 -0
  115. package/stdlib/strings/extra.go +35 -0
  116. package/stdlib/strings/iter.go +122 -0
  117. package/stdlib/sync/extra.go +105 -0
  118. package/stdlib/unicode/unicode.go +112 -0
  119. package/stdlib/unicode/utf8/bytes.go +239 -0
  120. package/src/backend/wasm/const-fold.js +0 -205
  121. package/src/backend/wasm/emit-stdlib.js +0 -13
  122. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  123. /package/src/{colors.js → cli/colors.js} +0 -0
  124. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  125. /package/src/{minifier.js → cli/minifier.js} +0 -0
  126. /package/src/{project-config.js → cli/project-config.js} +0 -0
  127. /package/src/{pwa.js → cli/pwa.js} +0 -0
  128. /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
@@ -0,0 +1,341 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package strconv
6
+
7
+ import (
8
+ "unicode"
9
+ "unicode/utf8"
10
+ )
11
+
12
+ // IntSize is the size in bits of an int or uint value.
13
+ const IntSize = 64
14
+
15
+ const lowerhex = "0123456789abcdef"
16
+
17
+ // A NumError records a failed conversion.
18
+ type NumError struct {
19
+ Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat, ParseComplex)
20
+ Num string // the input
21
+ Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
22
+ }
23
+
24
+ func (e *NumError) Error() string {
25
+ return "strconv." + e.Func + ": parsing " + Quote(e.Num) + ": " + e.Err.Error()
26
+ }
27
+
28
+ func (e *NumError) Unwrap() error { return e.Err }
29
+
30
+ // IsPrint reports whether the rune is defined as printable by Go, with
31
+ // the same definition as unicode.IsPrint: letters, numbers, punctuation,
32
+ // symbols and ASCII space.
33
+ func IsPrint(r rune) bool {
34
+ if 0x20 <= r && r <= 0x7E {
35
+ return true
36
+ }
37
+ return unicode.IsPrint(r)
38
+ }
39
+
40
+ // IsGraphic reports whether the rune is defined as a Graphic by Unicode.
41
+ func IsGraphic(r rune) bool {
42
+ if 0x20 <= r && r <= 0x7E {
43
+ return true
44
+ }
45
+ return unicode.IsGraphic(r)
46
+ }
47
+
48
+ func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string {
49
+ return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly))
50
+ }
51
+
52
+ func quoteRuneWith(r rune, quote byte, ASCIIonly, graphicOnly bool) string {
53
+ return string(appendQuotedRuneWith(nil, r, quote, ASCIIonly, graphicOnly))
54
+ }
55
+
56
+ func hexDigit(v int) byte {
57
+ return byte(lowerhex[v&0xF])
58
+ }
59
+
60
+ func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte {
61
+ buf = append(buf, quote)
62
+ for len(s) > 0 {
63
+ r, width := utf8.DecodeRuneInString(s)
64
+ if width == 1 && r == utf8.RuneError {
65
+ b0 := int(byte(s[0]))
66
+ buf = append(buf, byte('\\'), byte('x'), hexDigit(b0>>4), hexDigit(b0))
67
+ s = s[1:]
68
+ continue
69
+ }
70
+ buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly)
71
+ s = s[width:]
72
+ }
73
+ buf = append(buf, quote)
74
+ return buf
75
+ }
76
+
77
+ func appendQuotedRuneWith(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte {
78
+ buf = append(buf, quote)
79
+ if !utf8.ValidRune(r) {
80
+ r = utf8.RuneError
81
+ }
82
+ buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly)
83
+ buf = append(buf, quote)
84
+ return buf
85
+ }
86
+
87
+ func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte {
88
+ if r == rune(quote) || r == '\\' {
89
+ buf = append(buf, byte('\\'), byte(r))
90
+ return buf
91
+ }
92
+ if ASCIIonly {
93
+ if r < utf8.RuneSelf && IsPrint(r) {
94
+ buf = append(buf, byte(r))
95
+ return buf
96
+ }
97
+ } else if IsPrint(r) || (graphicOnly && IsGraphic(r)) {
98
+ return utf8.AppendRune(buf, r)
99
+ }
100
+ switch r {
101
+ case '\a':
102
+ buf = append(buf, byte('\\'), byte('a'))
103
+ case '\b':
104
+ buf = append(buf, byte('\\'), byte('b'))
105
+ case '\f':
106
+ buf = append(buf, byte('\\'), byte('f'))
107
+ case '\n':
108
+ buf = append(buf, byte('\\'), byte('n'))
109
+ case '\r':
110
+ buf = append(buf, byte('\\'), byte('r'))
111
+ case '\t':
112
+ buf = append(buf, byte('\\'), byte('t'))
113
+ case '\v':
114
+ buf = append(buf, byte('\\'), byte('v'))
115
+ default:
116
+ switch {
117
+ case r < ' ' || r == 0x7f:
118
+ br := int(r)
119
+ buf = append(buf, byte('\\'), byte('x'), hexDigit(br>>4), hexDigit(br))
120
+ case !utf8.ValidRune(r):
121
+ r = 0xFFFD
122
+ buf = append(buf, byte('\\'), byte('u'))
123
+ for s := 12; s >= 0; s -= 4 {
124
+ buf = append(buf, hexDigit(int(r>>uint(s))))
125
+ }
126
+ case r < 0x10000:
127
+ buf = append(buf, byte('\\'), byte('u'))
128
+ for s := 12; s >= 0; s -= 4 {
129
+ buf = append(buf, hexDigit(int(r>>uint(s))))
130
+ }
131
+ default:
132
+ buf = append(buf, byte('\\'), byte('U'))
133
+ for s := 28; s >= 0; s -= 4 {
134
+ buf = append(buf, hexDigit(int(r>>uint(s))))
135
+ }
136
+ }
137
+ }
138
+ return buf
139
+ }
140
+
141
+ // QuoteRune returns a single-quoted Go character literal representing the rune.
142
+ func QuoteRune(r rune) string {
143
+ return quoteRuneWith(r, byte('\''), false, false)
144
+ }
145
+
146
+ // QuoteToASCII returns a double-quoted Go string literal representing s using ASCII escapes.
147
+ func QuoteToASCII(s string) string {
148
+ return quoteWith(s, byte('"'), true, false)
149
+ }
150
+
151
+ // QuoteRuneToASCII returns a single-quoted Go character literal representing the rune using ASCII escapes.
152
+ func QuoteRuneToASCII(r rune) string {
153
+ return quoteRuneWith(r, byte('\''), true, false)
154
+ }
155
+
156
+ // AppendQuote appends a double-quoted Go string literal representing s to dst.
157
+ func AppendQuote(dst []byte, s string) []byte {
158
+ return appendQuotedWith(dst, s, byte('"'), false, false)
159
+ }
160
+
161
+ // AppendQuoteToASCII appends a double-quoted Go string literal representing s using ASCII escapes to dst.
162
+ func AppendQuoteToASCII(dst []byte, s string) []byte {
163
+ return appendQuotedWith(dst, s, byte('"'), true, false)
164
+ }
165
+
166
+ // AppendQuoteRune appends a single-quoted Go character literal representing the rune to dst.
167
+ func AppendQuoteRune(dst []byte, r rune) []byte {
168
+ return appendQuotedRuneWith(dst, r, byte('\''), false, false)
169
+ }
170
+
171
+ // AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune using ASCII escapes to dst.
172
+ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
173
+ return appendQuotedRuneWith(dst, r, byte('\''), true, false)
174
+ }
175
+
176
+ // CanBackquote reports whether the string s can be represented unchanged as a single-line backquoted string.
177
+ func CanBackquote(s string) bool {
178
+ for len(s) > 0 {
179
+ r, wid := utf8.DecodeRuneInString(s)
180
+ s = s[wid:]
181
+ if wid > 1 {
182
+ if r == '\ufeff' {
183
+ return false
184
+ }
185
+ continue
186
+ }
187
+ if r == utf8.RuneError {
188
+ return false
189
+ }
190
+ if (r < ' ' && r != '\t') || r == '`' || r == '\u007F' {
191
+ return false
192
+ }
193
+ }
194
+ return true
195
+ }
196
+
197
+ func unhex(b byte) (rune, bool) {
198
+ switch {
199
+ case byte('0') <= b && b <= byte('9'):
200
+ return rune(b - byte('0')), true
201
+ case byte('a') <= b && b <= byte('f'):
202
+ return rune(b - byte('a') + 10), true
203
+ case byte('A') <= b && b <= byte('F'):
204
+ return rune(b - byte('A') + 10), true
205
+ }
206
+ return 0, false
207
+ }
208
+
209
+ func unquoteHex(c byte, s string) (rune, bool, string, error) {
210
+ n := 0
211
+ switch c {
212
+ case byte('x'):
213
+ n = 2
214
+ case byte('u'):
215
+ n = 4
216
+ case byte('U'):
217
+ n = 8
218
+ }
219
+ if len(s) < n {
220
+ return 0, false, "", ErrSyntax
221
+ }
222
+ var v rune
223
+ for j := 0; j < n; j++ {
224
+ x, ok := unhex(byte(s[j]))
225
+ if !ok {
226
+ return 0, false, "", ErrSyntax
227
+ }
228
+ v = v<<4 | x
229
+ }
230
+ s = s[n:]
231
+ if c == byte('x') {
232
+ return v, false, s, nil
233
+ }
234
+ if !utf8.ValidRune(v) {
235
+ return 0, false, "", ErrSyntax
236
+ }
237
+ return v, true, s, nil
238
+ }
239
+
240
+ func unquoteOctal(c byte, s string) (rune, string, error) {
241
+ v := rune(c - byte('0'))
242
+ if len(s) < 2 {
243
+ return 0, "", ErrSyntax
244
+ }
245
+ for j := 0; j < 2; j++ {
246
+ b := byte(s[j])
247
+ if b < byte('0') || b > byte('7') {
248
+ return 0, "", ErrSyntax
249
+ }
250
+ v = (v << 3) | rune(b-byte('0'))
251
+ }
252
+ if v > 255 {
253
+ return 0, "", ErrSyntax
254
+ }
255
+ return v, s[2:], nil
256
+ }
257
+
258
+ // UnquoteChar decodes the first character or byte in the escaped string or character literal represented by s.
259
+ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
260
+ if len(s) == 0 {
261
+ return 0, false, "", ErrSyntax
262
+ }
263
+ c := byte(s[0])
264
+ if c == quote && (quote == byte('\'') || quote == byte('"')) {
265
+ return 0, false, "", ErrSyntax
266
+ }
267
+ if rune(c) >= utf8.RuneSelf {
268
+ r, size := utf8.DecodeRuneInString(s)
269
+ return r, true, s[size:], nil
270
+ }
271
+ if c != byte('\\') {
272
+ return rune(c), false, s[1:], nil
273
+ }
274
+ if len(s) <= 1 {
275
+ return 0, false, "", ErrSyntax
276
+ }
277
+ esc := byte(s[1])
278
+ s = s[2:]
279
+ switch esc {
280
+ case byte('a'):
281
+ return '\a', false, s, nil
282
+ case byte('b'):
283
+ return '\b', false, s, nil
284
+ case byte('f'):
285
+ return '\f', false, s, nil
286
+ case byte('n'):
287
+ return '\n', false, s, nil
288
+ case byte('r'):
289
+ return '\r', false, s, nil
290
+ case byte('t'):
291
+ return '\t', false, s, nil
292
+ case byte('v'):
293
+ return '\v', false, s, nil
294
+ case byte('x'), byte('u'), byte('U'):
295
+ v, mb, rem, err := unquoteHex(esc, s)
296
+ return v, mb, rem, err
297
+ case byte('0'), byte('1'), byte('2'), byte('3'), byte('4'), byte('5'), byte('6'), byte('7'):
298
+ v, rem, err := unquoteOctal(esc, s)
299
+ return v, false, rem, err
300
+ case byte('\\'):
301
+ return '\\', false, s, nil
302
+ case byte('\''), byte('"'):
303
+ if esc != quote {
304
+ return 0, false, "", ErrSyntax
305
+ }
306
+ return rune(esc), false, s, nil
307
+ default:
308
+ return 0, false, "", ErrSyntax
309
+ }
310
+ }
311
+
312
+ // QuotedPrefix returns the quoted string at the prefix of s.
313
+ func QuotedPrefix(s string) (string, error) {
314
+ if len(s) < 2 {
315
+ return "", ErrSyntax
316
+ }
317
+ quote := byte(s[0])
318
+ if quote != byte('"') && quote != byte('\'') && quote != byte('`') {
319
+ return "", ErrSyntax
320
+ }
321
+ if quote == byte('`') {
322
+ for i := 1; i < len(s); i++ {
323
+ if byte(s[i]) == byte('`') {
324
+ return s[:i+1], nil
325
+ }
326
+ }
327
+ return "", ErrSyntax
328
+ }
329
+ rem := s[1:]
330
+ for len(rem) > 0 {
331
+ if byte(rem[0]) == quote {
332
+ return s[:len(s)-len(rem)+1], nil
333
+ }
334
+ _, _, next, err := UnquoteChar(rem, quote)
335
+ if err != nil {
336
+ return "", err
337
+ }
338
+ rem = next
339
+ }
340
+ return "", ErrSyntax
341
+ }
@@ -0,0 +1,35 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed strings package: small members written in Go
6
+ // and merged into the strings namespace.
7
+ package strings
8
+
9
+ // Clone returns a fresh copy of s. Strings are immutable values here, so
10
+ // the copy is s itself.
11
+ func Clone(s string) string {
12
+ return s
13
+ }
14
+
15
+ // Compare returns an integer comparing two strings lexicographically.
16
+ // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
17
+ func Compare(a, b string) int {
18
+ if a == b {
19
+ return 0
20
+ }
21
+ if a < b {
22
+ return -1
23
+ }
24
+ return +1
25
+ }
26
+
27
+ // ContainsFunc reports whether any Unicode code points in s satisfy f(c).
28
+ func ContainsFunc(s string, f func(rune) bool) bool {
29
+ for _, r := range s {
30
+ if f(r) {
31
+ return true
32
+ }
33
+ }
34
+ return false
35
+ }
@@ -0,0 +1,122 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed strings package: the sequence members of
6
+ // Go 1.24 are written in Go over iter.Seq and merged into the strings
7
+ // namespace. Strings are JavaScript strings, so Index and slicing count the
8
+ // same units and splitting at a substring is always consistent; the places
9
+ // that need code points (an empty separator, Fields) go through []rune.
10
+ package strings
11
+
12
+ import (
13
+ "iter"
14
+ "unicode"
15
+ )
16
+
17
+ // Lines returns an iterator over the newline-terminated lines in the string s.
18
+ // The lines yielded by the iterator include their terminating newlines.
19
+ // If s is empty, the iterator yields no lines at all.
20
+ // If s does not end in a newline, the final yielded line will not end in a newline.
21
+ func Lines(s string) iter.Seq[string] {
22
+ return func(yield func(string) bool) {
23
+ for len(s) > 0 {
24
+ var line string
25
+ if i := IndexByte(s, '\n'); i >= 0 {
26
+ line, s = s[:i+1], s[i+1:]
27
+ } else {
28
+ line, s = s, ""
29
+ }
30
+ if !yield(line) {
31
+ return
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ // explodeSeq returns an iterator over the runes in s.
38
+ func explodeSeq(s string) iter.Seq[string] {
39
+ return func(yield func(string) bool) {
40
+ for _, r := range []rune(s) {
41
+ if !yield(string(r)) {
42
+ return
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ // splitSeq is SplitSeq or SplitAfterSeq, configured by how many
49
+ // bytes of sep to include in the results (none or all).
50
+ func splitSeq(s, sep string, sepSave int) iter.Seq[string] {
51
+ if len(sep) == 0 {
52
+ return explodeSeq(s)
53
+ }
54
+ return func(yield func(string) bool) {
55
+ for {
56
+ i := Index(s, sep)
57
+ if i < 0 {
58
+ break
59
+ }
60
+ frag := s[:i+sepSave]
61
+ if !yield(frag) {
62
+ return
63
+ }
64
+ s = s[i+len(sep):]
65
+ }
66
+ yield(s)
67
+ }
68
+ }
69
+
70
+ // SplitSeq returns an iterator over substrings of s split by sep.
71
+ // The iterator yields the same strings that would be returned by Split(s, sep),
72
+ // but without constructing the slice.
73
+ func SplitSeq(s, sep string) iter.Seq[string] {
74
+ return splitSeq(s, sep, 0)
75
+ }
76
+
77
+ // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
78
+ // The iterator yields the same strings that would be returned by SplitAfter(s, sep),
79
+ // but without constructing the slice.
80
+ func SplitAfterSeq(s, sep string) iter.Seq[string] {
81
+ return splitSeq(s, sep, len(sep))
82
+ }
83
+
84
+ // isSpace is unicode.IsSpace as a func(rune) bool (the checker types the
85
+ // unicode predicates over int).
86
+ func isSpace(r rune) bool {
87
+ return unicode.IsSpace(int(r))
88
+ }
89
+
90
+ // FieldsSeq returns an iterator over substrings of s split around runs of
91
+ // whitespace characters, as defined by unicode.IsSpace.
92
+ // The iterator yields the same strings that would be returned by Fields(s),
93
+ // but without constructing the slice.
94
+ func FieldsSeq(s string) iter.Seq[string] {
95
+ return FieldsFuncSeq(s, isSpace)
96
+ }
97
+
98
+ // FieldsFuncSeq returns an iterator over substrings of s split around runs of
99
+ // Unicode code points satisfying f(c).
100
+ // The iterator yields the same strings that would be returned by FieldsFunc(s),
101
+ // but without constructing the slice.
102
+ func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string] {
103
+ return func(yield func(string) bool) {
104
+ runes := []rune(s)
105
+ start := -1
106
+ for i, r := range runes {
107
+ if f(r) {
108
+ if start >= 0 {
109
+ if !yield(string(runes[start:i])) {
110
+ return
111
+ }
112
+ start = -1
113
+ }
114
+ } else if start < 0 {
115
+ start = i
116
+ }
117
+ }
118
+ if start >= 0 {
119
+ yield(string(runes[start:]))
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,105 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed sync package: OnceFunc/OnceValue/OnceValues
6
+ // and RWMutex.RLocker.
7
+ package sync
8
+
9
+ // OnceFunc returns a function that invokes f only once. The returned function
10
+ // may be called concurrently.
11
+ //
12
+ // If f panics, the returned function will panic with the same value on every call.
13
+ func OnceFunc(f func()) func() {
14
+ var (
15
+ once Once
16
+ valid bool
17
+ p any
18
+ )
19
+ return func() {
20
+ once.Do(func() {
21
+ defer func() {
22
+ p = recover()
23
+ if !valid {
24
+ panic(p)
25
+ }
26
+ }()
27
+ f()
28
+ valid = true
29
+ })
30
+ if !valid {
31
+ panic(p)
32
+ }
33
+ }
34
+ }
35
+
36
+ // OnceValue returns a function that invokes f only once and returns the value
37
+ // returned by f. The returned function may be called concurrently.
38
+ //
39
+ // If f panics, the returned function will panic with the same value on every call.
40
+ func OnceValue[T any](f func() T) func() T {
41
+ var (
42
+ once Once
43
+ valid bool
44
+ p any
45
+ result T
46
+ )
47
+ return func() T {
48
+ once.Do(func() {
49
+ defer func() {
50
+ p = recover()
51
+ if !valid {
52
+ panic(p)
53
+ }
54
+ }()
55
+ result = f()
56
+ valid = true
57
+ })
58
+ if !valid {
59
+ panic(p)
60
+ }
61
+ return result
62
+ }
63
+ }
64
+
65
+ // OnceValues returns a function that invokes f only once and returns the values
66
+ // returned by f. The returned function may be called concurrently.
67
+ //
68
+ // If f panics, the returned function will panic with the same value on every call.
69
+ func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
70
+ var (
71
+ once Once
72
+ valid bool
73
+ p any
74
+ r1 T1
75
+ r2 T2
76
+ )
77
+ return func() (T1, T2) {
78
+ once.Do(func() {
79
+ defer func() {
80
+ p = recover()
81
+ if !valid {
82
+ panic(p)
83
+ }
84
+ }()
85
+ r1, r2 = f()
86
+ valid = true
87
+ })
88
+ if !valid {
89
+ panic(p)
90
+ }
91
+ return r1, r2
92
+ }
93
+ }
94
+
95
+ type rlocker struct {
96
+ rw *RWMutex
97
+ }
98
+
99
+ func (r *rlocker) Lock() {}
100
+
101
+ func (r *rlocker) Unlock() {}
102
+
103
+ func (rw *RWMutex) RLocker() Locker {
104
+ return &rlocker{rw: rw}
105
+ }
@@ -0,0 +1,112 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package unicode
6
+
7
+ const (
8
+ MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
9
+ ReplacementChar = '\uFFFD' // Represents invalid code points.
10
+ MaxASCII = '\u007F' // maximum ASCII value.
11
+ MaxLatin1 = '\u00FF' // maximum Latin-1 value.
12
+ UpperLower = MaxRune + 1
13
+ Version = "15.0.0"
14
+ )
15
+
16
+ // ToTitle maps the rune to title case.
17
+ func ToTitle(r rune) rune {
18
+ if r <= MaxASCII {
19
+ if 'a' <= r && r <= 'z' {
20
+ return r - ('a' - 'A')
21
+ }
22
+ return r
23
+ }
24
+ switch r {
25
+ case 0x1C4, 0x1C5, 0x1C6:
26
+ return 0x1C5
27
+ case 0x1C7, 0x1C8, 0x1C9:
28
+ return 0x1C8
29
+ case 0x1CA, 0x1CB, 0x1CC:
30
+ return 0x1CB
31
+ case 0x1F1, 0x1F2, 0x1F3:
32
+ return 0x1F2
33
+ }
34
+ if 0x10D0 <= r && r <= 0x10FF {
35
+ return r
36
+ }
37
+ return rune(ToUpper(int(r)))
38
+ }
39
+
40
+ type foldPair struct {
41
+ From uint16
42
+ To uint16
43
+ }
44
+
45
+ var caseOrbit = []foldPair{
46
+ {0x004B, 0x006B}, {0x0053, 0x0073}, {0x006B, 0x212A}, {0x0073, 0x017F},
47
+ {0x00B5, 0x039C}, {0x00C5, 0x00E5}, {0x00DF, 0x1E9E}, {0x00E5, 0x212B},
48
+ {0x0130, 0x0130}, {0x0131, 0x0131}, {0x017F, 0x0053}, {0x01C4, 0x01C5},
49
+ {0x01C5, 0x01C6}, {0x01C6, 0x01C4}, {0x01C7, 0x01C8}, {0x01C8, 0x01C9},
50
+ {0x01C9, 0x01C7}, {0x01CA, 0x01CB}, {0x01CB, 0x01CC}, {0x01CC, 0x01CA},
51
+ {0x01F1, 0x01F2}, {0x01F2, 0x01F3}, {0x01F3, 0x01F1}, {0x0345, 0x0399},
52
+ {0x0392, 0x03B2}, {0x0395, 0x03B5}, {0x0398, 0x03B8}, {0x0399, 0x03B9},
53
+ {0x039A, 0x03BA}, {0x039C, 0x03BC}, {0x03A0, 0x03C0}, {0x03A1, 0x03C1},
54
+ {0x03A3, 0x03C2}, {0x03A6, 0x03C6}, {0x03A9, 0x03C9}, {0x03B2, 0x03D0},
55
+ {0x03B5, 0x03F5}, {0x03B8, 0x03D1}, {0x03B9, 0x1FBE}, {0x03BA, 0x03F0},
56
+ {0x03BC, 0x00B5}, {0x03C0, 0x03D6}, {0x03C1, 0x03F1}, {0x03C2, 0x03C3},
57
+ {0x03C3, 0x03A3}, {0x03C6, 0x03D5}, {0x03C9, 0x2126}, {0x03D0, 0x0392},
58
+ {0x03D1, 0x03F4}, {0x03D5, 0x03A6}, {0x03D6, 0x03A0}, {0x03F0, 0x039A},
59
+ {0x03F1, 0x03A1}, {0x03F4, 0x0398}, {0x03F5, 0x0395}, {0x0412, 0x0432},
60
+ {0x0414, 0x0434}, {0x041E, 0x043E}, {0x0421, 0x0441}, {0x0422, 0x0442},
61
+ {0x042A, 0x044A}, {0x0432, 0x1C80}, {0x0434, 0x1C81}, {0x043E, 0x1C82},
62
+ {0x0441, 0x1C83}, {0x0442, 0x1C84}, {0x044A, 0x1C86}, {0x0462, 0x0463},
63
+ {0x0463, 0x1C87}, {0x1C80, 0x0412}, {0x1C81, 0x0414}, {0x1C82, 0x041E},
64
+ {0x1C83, 0x0421}, {0x1C84, 0x1C85}, {0x1C85, 0x0422}, {0x1C86, 0x042A},
65
+ {0x1C87, 0x0462}, {0x1C88, 0xA64A}, {0x1E60, 0x1E61}, {0x1E61, 0x1E9B},
66
+ {0x1E9B, 0x1E60}, {0x1E9E, 0x00DF}, {0x1FBE, 0x0345}, {0x2126, 0x03A9},
67
+ {0x212A, 0x004B}, {0x212B, 0x00C5}, {0xA64A, 0xA64B}, {0xA64B, 0x1C88},
68
+ }
69
+
70
+ func foldASCII(r rune) (rune, bool) {
71
+ if 'a' <= r && r <= 'z' {
72
+ if r != 'k' && r != 's' {
73
+ return r - ('a' - 'A'), true
74
+ }
75
+ } else if 'A' <= r && r <= 'Z' {
76
+ if r != 'K' && r != 'S' {
77
+ return r + ('a' - 'A'), true
78
+ }
79
+ } else {
80
+ return r, true
81
+ }
82
+ return r, false
83
+ }
84
+
85
+ // SimpleFold iterates over Unicode code points equivalent under simple case folding.
86
+ func SimpleFold(r rune) rune {
87
+ if r < 0 || r > MaxRune {
88
+ return r
89
+ }
90
+ if r < 128 {
91
+ if folded, ok := foldASCII(r); ok {
92
+ return folded
93
+ }
94
+ }
95
+ lo := 0
96
+ hi := len(caseOrbit)
97
+ for lo < hi {
98
+ m := int(uint(lo+hi) >> 1)
99
+ if rune(caseOrbit[m].From) < r {
100
+ lo = m + 1
101
+ } else {
102
+ hi = m
103
+ }
104
+ }
105
+ if lo < len(caseOrbit) && rune(caseOrbit[lo].From) == r {
106
+ return rune(caseOrbit[lo].To)
107
+ }
108
+ if l := rune(ToLower(int(r))); l != r {
109
+ return l
110
+ }
111
+ return rune(ToUpper(int(r)))
112
+ }