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.
Files changed (178) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -5
  3. package/src/backend/js/expressions.js +1157 -408
  4. package/src/backend/js/index.js +327 -153
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +559 -2552
  7. package/src/backend/js/statements.js +670 -158
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +298 -19
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +91 -170
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +884 -256
  16. package/src/backend/wasm/emit-exprs.js +185 -77
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-shared.js +4 -1
  19. package/src/backend/wasm/emit-stmts.js +524 -240
  20. package/src/backend/wasm/emit.js +176 -38
  21. package/src/backend/wasm/globals.js +48 -8
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +44 -530
  24. package/src/backend/wasm/method-expr.js +12 -1
  25. package/src/backend/wasm/module-emitter.js +299 -770
  26. package/src/backend/wasm/monomorph.js +139 -8
  27. package/src/backend/wasm/natives.js +600 -0
  28. package/src/backend/wasm/prescan.js +5 -153
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -32
  31. package/src/backend/wasm/types.js +97 -20
  32. package/src/backend/wasm/variadic.js +9 -4
  33. package/src/cli/cli-core.js +5 -1
  34. package/src/cli/test-runner.js +115 -342
  35. package/src/compiler.js +113 -130
  36. package/src/lexer/lexer.js +106 -11
  37. package/src/lexer/templ-lexer.js +61 -18
  38. package/src/lexer/tokens.js +1 -0
  39. package/src/link/stdlib.js +355 -132
  40. package/src/link/type-names.js +204 -0
  41. package/src/link/wasm.js +30 -6
  42. package/src/lower/bounds.js +153 -0
  43. package/src/lower/captures.js +92 -33
  44. package/src/lower/embedding.js +62 -5
  45. package/src/lower/errors-as.js +196 -0
  46. package/src/lower/fmt-formatters.js +929 -0
  47. package/src/lower/functions.js +225 -7
  48. package/src/lower/gen-types.js +293 -0
  49. package/src/lower/index.js +14 -2
  50. package/src/lower/json-codecs.js +334 -245
  51. package/src/lower/ownership.js +25 -7
  52. package/src/lower/reachability.js +69 -51
  53. package/src/lower/walk.js +12 -0
  54. package/src/parser/declarations.js +30 -5
  55. package/src/parser/expressions.js +111 -57
  56. package/src/parser/statements.js +108 -0
  57. package/src/parser/templ.js +44 -5
  58. package/src/parser/types.js +12 -0
  59. package/src/resolver.js +1 -2
  60. package/src/typechecker/assignability.js +214 -19
  61. package/src/typechecker/const-fold.js +70 -27
  62. package/src/typechecker/constants.js +156 -8
  63. package/src/typechecker/expressions.js +490 -108
  64. package/src/typechecker/index.js +346 -42
  65. package/src/typechecker/init-order.js +136 -40
  66. package/src/typechecker/operand-text.js +41 -0
  67. package/src/typechecker/resolve.js +490 -65
  68. package/src/typechecker/statements.js +288 -27
  69. package/src/typechecker/stdlib/excluded.js +9 -5
  70. package/src/typechecker/stdlib/index.js +25 -9
  71. package/src/typechecker/termination.js +10 -1
  72. package/src/typechecker/types.js +287 -575
  73. package/stdlib/bytes/buffer.go +479 -0
  74. package/stdlib/bytes/bytes.go +1010 -0
  75. package/stdlib/bytes/reader.go +161 -0
  76. package/stdlib/context/context.go +115 -0
  77. package/stdlib/crypto/rand/rand.go +34 -0
  78. package/stdlib/crypto/sha256/sha256.go +249 -0
  79. package/stdlib/encoding/base64/base64.go +331 -0
  80. package/stdlib/encoding/binary/binary.go +332 -0
  81. package/stdlib/encoding/hex/hex.go +140 -0
  82. package/stdlib/encoding/json/json.go +62 -0
  83. package/stdlib/errors/errors.go +174 -0
  84. package/stdlib/fmt/errors.go +110 -0
  85. package/stdlib/fmt/format.go +732 -0
  86. package/stdlib/fmt/print.go +1232 -0
  87. package/stdlib/gom/gom.go +293 -0
  88. package/stdlib/html/html.go +251 -0
  89. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  90. package/stdlib/internal/jsonrt/dec.go +171 -38
  91. package/stdlib/internal/jsonrt/enc.go +186 -36
  92. package/stdlib/internal/jsonrt/scanner.go +17 -8
  93. package/stdlib/io/io.go +157 -1
  94. package/stdlib/maps/maps.go +131 -0
  95. package/stdlib/math/bits/bits.go +507 -0
  96. package/stdlib/math/extra.go +16 -14
  97. package/stdlib/math/math.go +439 -0
  98. package/stdlib/math/rand/rand.go +297 -0
  99. package/stdlib/os/os.go +93 -0
  100. package/stdlib/path/filepath/filepath.go +47 -0
  101. package/stdlib/path/path.go +394 -0
  102. package/stdlib/regexp/regexp.go +231 -0
  103. package/stdlib/slices/slices.go +526 -0
  104. package/stdlib/slices/sort.go +209 -0
  105. package/stdlib/slices/zsort_cmp.go +480 -0
  106. package/stdlib/slices/zsort_ordered.go +482 -0
  107. package/stdlib/sort/sort.go +391 -452
  108. package/stdlib/sort/zsort_func.go +480 -0
  109. package/stdlib/sort/zsort_iface.go +480 -0
  110. package/stdlib/strconv/float.go +1699 -0
  111. package/stdlib/strconv/isprint.go +752 -0
  112. package/stdlib/strconv/quote.go +235 -50
  113. package/stdlib/strconv/strconv.go +616 -0
  114. package/stdlib/strings/builder.go +95 -0
  115. package/stdlib/strings/reader.go +163 -0
  116. package/stdlib/strings/replacer.go +102 -0
  117. package/stdlib/strings/strings.go +807 -0
  118. package/stdlib/sync/sync.go +268 -0
  119. package/stdlib/testing/async_js.go +61 -0
  120. package/stdlib/testing/benchmark.go +297 -0
  121. package/stdlib/testing/testing.go +523 -0
  122. package/stdlib/time/duration.go +233 -0
  123. package/stdlib/time/format.go +745 -0
  124. package/stdlib/time/parse.go +790 -0
  125. package/stdlib/time/sleep_js.go +63 -0
  126. package/stdlib/time/time.go +834 -0
  127. package/stdlib/unicode/unicode.go +141 -3
  128. package/stdlib/unicode/utf8/utf8.go +464 -0
  129. package/src/backend/js/fmt-runtime.js +0 -573
  130. package/src/backend/js/stdlib/base64.js +0 -12
  131. package/src/backend/js/stdlib/binary.js +0 -102
  132. package/src/backend/js/stdlib/bits.js +0 -119
  133. package/src/backend/js/stdlib/builder.js +0 -98
  134. package/src/backend/js/stdlib/bytes.js +0 -368
  135. package/src/backend/js/stdlib/errors.js +0 -45
  136. package/src/backend/js/stdlib/fmt.js +0 -517
  137. package/src/backend/js/stdlib/gom.js +0 -155
  138. package/src/backend/js/stdlib/hex.js +0 -17
  139. package/src/backend/js/stdlib/html.js +0 -20
  140. package/src/backend/js/stdlib/io.js +0 -137
  141. package/src/backend/js/stdlib/json.js +0 -1167
  142. package/src/backend/js/stdlib/maps.js +0 -37
  143. package/src/backend/js/stdlib/math.js +0 -85
  144. package/src/backend/js/stdlib/os.js +0 -13
  145. package/src/backend/js/stdlib/path.js +0 -48
  146. package/src/backend/js/stdlib/rand.js +0 -32
  147. package/src/backend/js/stdlib/regexp.js +0 -54
  148. package/src/backend/js/stdlib/sha256.js +0 -12
  149. package/src/backend/js/stdlib/shared.js +0 -17
  150. package/src/backend/js/stdlib/simd.js +0 -34
  151. package/src/backend/js/stdlib/slices.js +0 -107
  152. package/src/backend/js/stdlib/sort.js +0 -30
  153. package/src/backend/js/stdlib/strconv.js +0 -79
  154. package/src/backend/js/stdlib/strings.js +0 -301
  155. package/src/backend/js/stdlib/sync.js +0 -13
  156. package/src/backend/js/stdlib/testing.js +0 -41
  157. package/src/backend/js/stdlib/time.js +0 -152
  158. package/src/backend/js/stdlib/unicode.js +0 -25
  159. package/src/backend/js/stdlib/utf8.js +0 -26
  160. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  161. package/src/backend/wasm/stdlib/core.js +0 -10278
  162. package/src/backend/wasm/stdlib/io.js +0 -3578
  163. package/src/backend/wasm/stdlib/packages.js +0 -2402
  164. package/src/backend/wasm/stdlib/pure.js +0 -720
  165. package/src/backend/wasm/stdlib/time.js +0 -2229
  166. package/src/typechecker/stdlib/core.js +0 -1079
  167. package/src/typechecker/stdlib/extended.js +0 -1210
  168. package/stdlib/bytes/iter.go +0 -192
  169. package/stdlib/bytes/search.go +0 -240
  170. package/stdlib/bytes/split.go +0 -218
  171. package/stdlib/errors/overlay.go +0 -12
  172. package/stdlib/maps/iter.go +0 -65
  173. package/stdlib/slices/extra.go +0 -73
  174. package/stdlib/slices/iter.go +0 -113
  175. package/stdlib/strings/extra.go +0 -35
  176. package/stdlib/strings/iter.go +0 -122
  177. package/stdlib/sync/extra.go +0 -105
  178. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -0,0 +1,526 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Copyright 2021 The Go Authors. All rights reserved.
6
+ // Use of this source code is governed by a BSD-style
7
+ // license that can be found in the LICENSE file.
8
+
9
+ // Package slices defines various functions useful with slices of any type.
10
+ package slices
11
+
12
+ import (
13
+ "cmp"
14
+ "iter"
15
+ )
16
+
17
+ // Equal reports whether two slices are equal: the same length and all
18
+ // elements equal. If the lengths are different, Equal returns false.
19
+ // Otherwise, the elements are compared in increasing index order, and the
20
+ // comparison stops at the first unequal pair.
21
+ // Empty and nil slices are considered equal.
22
+ // Floating point NaNs are not considered equal.
23
+ func Equal[S ~[]E, E comparable](s1, s2 S) bool {
24
+ if len(s1) != len(s2) {
25
+ return false
26
+ }
27
+ for i := range s1 {
28
+ if s1[i] != s2[i] {
29
+ return false
30
+ }
31
+ }
32
+ return true
33
+ }
34
+
35
+ // EqualFunc reports whether two slices are equal using an equality
36
+ // function on each pair of elements. If the lengths are different,
37
+ // EqualFunc returns false. Otherwise, the elements are compared in
38
+ // increasing index order, and the comparison stops at the first index
39
+ // for which eq returns false.
40
+ func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
41
+ if len(s1) != len(s2) {
42
+ return false
43
+ }
44
+ for i, v1 := range s1 {
45
+ v2 := s2[i]
46
+ if !eq(v1, v2) {
47
+ return false
48
+ }
49
+ }
50
+ return true
51
+ }
52
+
53
+ // Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
54
+ // of elements. The elements are compared sequentially, starting at index 0,
55
+ // until one element is not equal to the other.
56
+ // The result of comparing the first non-matching elements is returned.
57
+ // If both slices are equal until one of them ends, the shorter slice is
58
+ // considered less than the longer one.
59
+ // The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
60
+ func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
61
+ for i, v1 := range s1 {
62
+ if i >= len(s2) {
63
+ return +1
64
+ }
65
+ v2 := s2[i]
66
+ if c := cmp.Compare(v1, v2); c != 0 {
67
+ return c
68
+ }
69
+ }
70
+ if len(s1) < len(s2) {
71
+ return -1
72
+ }
73
+ return 0
74
+ }
75
+
76
+ // CompareFunc is like [Compare] but uses a custom comparison function on each
77
+ // pair of elements.
78
+ // The result is the first non-zero result of cmp; if cmp always
79
+ // returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
80
+ // and +1 if len(s1) > len(s2).
81
+ func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
82
+ for i, v1 := range s1 {
83
+ if i >= len(s2) {
84
+ return +1
85
+ }
86
+ v2 := s2[i]
87
+ if c := cmp(v1, v2); c != 0 {
88
+ return c
89
+ }
90
+ }
91
+ if len(s1) < len(s2) {
92
+ return -1
93
+ }
94
+ return 0
95
+ }
96
+
97
+ // Index returns the index of the first occurrence of v in s,
98
+ // or -1 if not present.
99
+ //gofront:native slices.Index
100
+ func Index[S ~[]E, E comparable](s S, v E) int {
101
+ for i := range s {
102
+ if v == s[i] {
103
+ return i
104
+ }
105
+ }
106
+ return -1
107
+ }
108
+
109
+ // IndexFunc returns the first index i satisfying f(s[i]),
110
+ // or -1 if none do.
111
+ func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
112
+ for i := range s {
113
+ if f(s[i]) {
114
+ return i
115
+ }
116
+ }
117
+ return -1
118
+ }
119
+
120
+ // Contains reports whether v is present in s.
121
+ //gofront:native slices.Contains
122
+ func Contains[S ~[]E, E comparable](s S, v E) bool {
123
+ return Index(s, v) >= 0
124
+ }
125
+
126
+ // ContainsFunc reports whether at least one
127
+ // element e of s satisfies f(e).
128
+ func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
129
+ return IndexFunc(s, f) >= 0
130
+ }
131
+
132
+ // Insert inserts the values v... into s at index i,
133
+ // returning the modified slice.
134
+ // The elements at s[i:] are shifted up to make room.
135
+ // In the returned slice r, r[i] == v[0],
136
+ // and, if i < len(s), r[i+len(v)] == value originally at s[i].
137
+ // Insert panics if i > len(s).
138
+ // This function is O(len(s) + len(v)).
139
+ // If the result is empty, it has the same nilness as s.
140
+ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
141
+ _ = s[i:] // bounds check
142
+
143
+ m := len(v)
144
+ if m == 0 {
145
+ return s
146
+ }
147
+ n := len(s)
148
+ if i == n {
149
+ return append(s, v...)
150
+ }
151
+ if n+m > cap(s) {
152
+ // Use append rather than make so that we bump the size of
153
+ // the slice up to the next storage class.
154
+ // This is what Grow does but we don't call Grow because
155
+ // that might copy the values twice.
156
+ s2 := append(s[:i], make(S, n+m-i)...)
157
+ copy(s2[i:], v)
158
+ copy(s2[i+m:], s[i:])
159
+ return s2
160
+ }
161
+ s = s[:n+m]
162
+
163
+ // before:
164
+ // s: aaaaaaaabbbbccccccccdddd
165
+ // ^ ^ ^ ^
166
+ // i i+m n n+m
167
+ // after:
168
+ // s: aaaaaaaavvvvbbbbcccccccc
169
+ // ^ ^ ^ ^
170
+ // i i+m n n+m
171
+ //
172
+ // a are the values that don't move in s.
173
+ // v are the values copied in from v.
174
+ // b and c are the values from s that are shifted up in index.
175
+ // d are the values that get overwritten, never to be seen again.
176
+
177
+ // v may alias s (for example Insert(s, 0, s[2:]...)): take a copy, which
178
+ // is then free of the regions that are shifted and overwritten. Go
179
+ // detects the overlap with pointer arithmetic and rotates instead.
180
+ v = append([]E(nil), v...)
181
+ copy(s[i+m:], s[i:])
182
+ copy(s[i:], v)
183
+ return s
184
+ }
185
+
186
+ // Delete removes the elements s[i:j] from s, returning the modified slice.
187
+ // Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
188
+ // Delete is O(len(s)-i), so if many items must be deleted, it is better to
189
+ // make a single call deleting them all together than to delete one at a time.
190
+ // Delete zeroes the elements s[len(s)-(j-i):len(s)].
191
+ // If the result is empty, it has the same nilness as s.
192
+ func Delete[S ~[]E, E any](s S, i, j int) S {
193
+ _ = s[i:j:len(s)] // bounds check
194
+
195
+ if i == j {
196
+ return s
197
+ }
198
+
199
+ oldlen := len(s)
200
+ s = append(s[:i], s[j:]...)
201
+ clear(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
202
+ return s
203
+ }
204
+
205
+ // DeleteFunc removes any elements from s for which del returns true,
206
+ // returning the modified slice.
207
+ // DeleteFunc zeroes the elements between the new length and the original length.
208
+ // If the result is empty, it has the same nilness as s.
209
+ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
210
+ i := IndexFunc(s, del)
211
+ if i == -1 {
212
+ return s
213
+ }
214
+ // Don't start copying elements until we find one to delete.
215
+ for j := i + 1; j < len(s); j++ {
216
+ if v := s[j]; !del(v) {
217
+ s[i] = v
218
+ i++
219
+ }
220
+ }
221
+ clear(s[i:]) // zero/nil out the obsolete elements, for GC
222
+ return s[:i]
223
+ }
224
+
225
+ // Replace replaces the elements s[i:j] by the given v, and returns the
226
+ // modified slice.
227
+ // Replace panics if j > len(s) or s[i:j] is not a valid slice of s.
228
+ // When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
229
+ // If the result is empty, it has the same nilness as s.
230
+ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
231
+ _ = s[i:j] // bounds check
232
+
233
+ if i == j {
234
+ return Insert(s, i, v...)
235
+ }
236
+ if j == len(s) {
237
+ s2 := append(s[:i], v...)
238
+ if len(s2) < len(s) {
239
+ clear(s[len(s2):]) // zero/nil out the obsolete elements, for GC
240
+ }
241
+ return s2
242
+ }
243
+
244
+ tot := len(s[:i]) + len(v) + len(s[j:])
245
+ if tot > cap(s) {
246
+ // Too big to fit, allocate and copy over.
247
+ s2 := append(s[:i], make(S, tot-i)...) // See Insert
248
+ copy(s2[i:], v)
249
+ copy(s2[i+len(v):], s[j:])
250
+ return s2
251
+ }
252
+
253
+ r := s[:tot]
254
+
255
+ if i+len(v) <= j {
256
+ // Easy, as v fits in the deleted portion.
257
+ copy(r[i:], v)
258
+ copy(r[i+len(v):], s[j:])
259
+ clear(s[tot:]) // zero/nil out the obsolete elements, for GC
260
+ return r
261
+ }
262
+
263
+ // We are expanding (v is bigger than j-i).
264
+ // The situation is something like this:
265
+ // (example has i=4,j=8,len(s)=16,len(v)=6)
266
+ // s: aaaaxxxxbbbbbbbbyy
267
+ // ^ ^ ^ ^
268
+ // i j len(s) tot
269
+ // a: prefix of s
270
+ // x: deleted range
271
+ // b: more of s
272
+ // y: area to expand into
273
+
274
+ // v may alias s: copy it before the first move can clobber it (Go
275
+ // detects the overlap with pointer arithmetic and rotates instead).
276
+ v = append([]E(nil), v...)
277
+ copy(r[i+len(v):], s[j:])
278
+ copy(r[i:], v)
279
+ return r
280
+ }
281
+
282
+ // Clone returns a copy of the slice.
283
+ // The elements are copied using assignment, so this is a shallow clone.
284
+ // The result may have additional unused capacity.
285
+ // The result preserves the nilness of s.
286
+ //gofront:native slices.Clone
287
+ func Clone[S ~[]E, E any](s S) S {
288
+ // Preserve nilness in case it matters.
289
+ if s == nil {
290
+ return nil
291
+ }
292
+ // Avoid s[:0:0] as it leads to unwanted liveness when cloning a
293
+ // zero-length slice of a large array; see https://go.dev/issue/68488.
294
+ return append(S{}, s...)
295
+ }
296
+
297
+ // Compact replaces consecutive runs of equal elements with a single copy.
298
+ // This is like the uniq command found on Unix.
299
+ // Compact modifies the contents of the slice s and returns the modified slice,
300
+ // which may have a smaller length.
301
+ // Compact zeroes the elements between the new length and the original length.
302
+ // The result preserves the nilness of s.
303
+ func Compact[S ~[]E, E comparable](s S) S {
304
+ if len(s) < 2 {
305
+ return s
306
+ }
307
+ for k := 1; k < len(s); k++ {
308
+ if s[k] == s[k-1] {
309
+ s2 := s[k:]
310
+ for k2 := 1; k2 < len(s2); k2++ {
311
+ if s2[k2] != s2[k2-1] {
312
+ s[k] = s2[k2]
313
+ k++
314
+ }
315
+ }
316
+
317
+ clear(s[k:]) // zero/nil out the obsolete elements, for GC
318
+ return s[:k]
319
+ }
320
+ }
321
+ return s
322
+ }
323
+
324
+ // CompactFunc is like [Compact] but uses an equality function to compare elements.
325
+ // For runs of elements that compare equal, CompactFunc keeps the first one.
326
+ // CompactFunc zeroes the elements between the new length and the original length.
327
+ // The result preserves the nilness of s.
328
+ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
329
+ if len(s) < 2 {
330
+ return s
331
+ }
332
+ for k := 1; k < len(s); k++ {
333
+ if eq(s[k], s[k-1]) {
334
+ s2 := s[k:]
335
+ for k2 := 1; k2 < len(s2); k2++ {
336
+ if !eq(s2[k2], s2[k2-1]) {
337
+ s[k] = s2[k2]
338
+ k++
339
+ }
340
+ }
341
+
342
+ clear(s[k:]) // zero/nil out the obsolete elements, for GC
343
+ return s[:k]
344
+ }
345
+ }
346
+ return s
347
+ }
348
+
349
+ // Grow increases the slice's capacity, if necessary, to guarantee space for
350
+ // another n elements. After Grow(n), at least n elements can be appended
351
+ // to the slice without another allocation. If n is negative or too large to
352
+ // allocate the memory, Grow panics.
353
+ // The result preserves the nilness of s.
354
+ func Grow[S ~[]E, E any](s S, n int) S {
355
+ if n < 0 {
356
+ panic("cannot be negative")
357
+ }
358
+ if n -= cap(s) - len(s); n > 0 {
359
+ // This expression allocates only once (see test).
360
+ s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
361
+ }
362
+ return s
363
+ }
364
+
365
+ // Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
366
+ // The result preserves the nilness of s.
367
+ func Clip[S ~[]E, E any](s S) S {
368
+ return s[:len(s):len(s)]
369
+ }
370
+
371
+ // Reverse reverses the elements of the slice in place.
372
+ //gofront:native slices.Reverse
373
+ func Reverse[S ~[]E, E any](s S) {
374
+ for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
375
+ s[i], s[j] = s[j], s[i]
376
+ }
377
+ }
378
+
379
+ // Concat returns a new slice concatenating the passed in slices.
380
+ // If the concatenation is empty, the result is nil.
381
+ func Concat[S ~[]E, E any](slices ...S) S {
382
+ size := 0
383
+ for _, s := range slices {
384
+ size += len(s)
385
+ if size < 0 {
386
+ panic("len out of range")
387
+ }
388
+ }
389
+ // Use Grow, not make, to round up to the size class:
390
+ // the extra space is otherwise unused and helps
391
+ // callers that append a few elements to the result.
392
+ newslice := Grow[S](nil, size)
393
+ for _, s := range slices {
394
+ newslice = append(newslice, s...)
395
+ }
396
+ return newslice
397
+ }
398
+
399
+ // repeatMaxInt is the largest int, as the overflow bound of Repeat.
400
+ const repeatMaxInt = 1<<63 - 1
401
+
402
+ // Repeat returns a new slice that repeats the provided slice the given number of times.
403
+ // The result has length and capacity (len(x) * count).
404
+ // The result is never nil.
405
+ // Repeat panics if count is negative or if the result of (len(x) * count)
406
+ // overflows.
407
+ func Repeat[S ~[]E, E any](x S, count int) S {
408
+ if count < 0 {
409
+ panic("cannot be negative")
410
+ }
411
+
412
+ if len(x) > 0 && count > repeatMaxInt/len(x) {
413
+ panic("the result of (len(x) * count) overflows")
414
+ }
415
+
416
+ newslice := make(S, len(x)*count)
417
+ n := copy(newslice, x)
418
+ for n < len(newslice) {
419
+ n += copy(newslice[n:], newslice[:n])
420
+ }
421
+ return newslice
422
+ }
423
+
424
+ // All returns an iterator over index-value pairs in the slice
425
+ // in the usual order.
426
+ func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] {
427
+ return func(yield func(int, E) bool) {
428
+ for i, v := range s {
429
+ if !yield(i, v) {
430
+ return
431
+ }
432
+ }
433
+ }
434
+ }
435
+
436
+ // Backward returns an iterator over index-value pairs in the slice,
437
+ // traversing it backward with descending indices.
438
+ func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] {
439
+ return func(yield func(int, E) bool) {
440
+ for i := len(s) - 1; i >= 0; i-- {
441
+ if !yield(i, s[i]) {
442
+ return
443
+ }
444
+ }
445
+ }
446
+ }
447
+
448
+ // Values returns an iterator that yields the slice elements in order.
449
+ func Values[Slice ~[]E, E any](s Slice) iter.Seq[E] {
450
+ return func(yield func(E) bool) {
451
+ for _, v := range s {
452
+ if !yield(v) {
453
+ return
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ // AppendSeq appends the values from seq to the slice and
460
+ // returns the extended slice.
461
+ // If seq is empty, the result preserves the nilness of s.
462
+ func AppendSeq[Slice ~[]E, E any](s Slice, seq iter.Seq[E]) Slice {
463
+ for v := range seq {
464
+ s = append(s, v)
465
+ }
466
+ return s
467
+ }
468
+
469
+ // Collect collects values from seq into a new slice and returns it.
470
+ // If seq is empty, the result is nil.
471
+ func Collect[E any](seq iter.Seq[E]) []E {
472
+ return AppendSeq([]E(nil), seq)
473
+ }
474
+
475
+ // Sorted collects values from seq into a new slice, sorts the slice,
476
+ // and returns it.
477
+ // If seq is empty, the result is nil.
478
+ func Sorted[E cmp.Ordered](seq iter.Seq[E]) []E {
479
+ s := Collect(seq)
480
+ Sort(s)
481
+ return s
482
+ }
483
+
484
+ // SortedFunc collects values from seq into a new slice, sorts the slice
485
+ // using the comparison function, and returns it.
486
+ // If seq is empty, the result is nil.
487
+ func SortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
488
+ s := Collect(seq)
489
+ SortFunc(s, cmp)
490
+ return s
491
+ }
492
+
493
+ // SortedStableFunc collects values from seq into a new slice.
494
+ // It then sorts the slice while keeping the original order of equal elements,
495
+ // using the comparison function to compare elements.
496
+ // It returns the new slice.
497
+ // If seq is empty, the result is nil.
498
+ func SortedStableFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
499
+ s := Collect(seq)
500
+ SortStableFunc(s, cmp)
501
+ return s
502
+ }
503
+
504
+ // Chunk returns an iterator over consecutive sub-slices of up to n elements of s.
505
+ // All but the last sub-slice will have size n.
506
+ // All sub-slices are clipped to have no capacity beyond the length.
507
+ // If s is empty, the sequence is empty: there is no empty slice in the sequence.
508
+ // Chunk panics if n is less than 1.
509
+ func Chunk[Slice ~[]E, E any](s Slice, n int) iter.Seq[Slice] {
510
+ if n < 1 {
511
+ panic("cannot be less than 1")
512
+ }
513
+
514
+ return func(yield func(Slice) bool) {
515
+ for i := 0; i < len(s); i += n {
516
+ // Clamp the last chunk to the slice bound as necessary.
517
+ end := min(n, len(s[i:]))
518
+
519
+ // Set the capacity of each chunk so that appending to a chunk does
520
+ // not modify the original slice.
521
+ if !yield(s[i : i+end : i+end]) {
522
+ return
523
+ }
524
+ }
525
+ }
526
+ }