goscript 0.0.25 → 0.0.28

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 (190) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +259 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +201 -49
  8. package/compiler/compiler_test.go +53 -0
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +83 -0
  12. package/compiler/expr.go +1 -1
  13. package/compiler/protobuf.go +557 -0
  14. package/compiler/spec-struct.go +4 -0
  15. package/compiler/spec-value.go +11 -3
  16. package/compiler/spec.go +18 -1
  17. package/compiler/stmt-assign.go +35 -0
  18. package/compiler/type-assert.go +87 -0
  19. package/compiler/type.go +5 -2
  20. package/dist/gs/builtin/builtin.d.ts +19 -1
  21. package/dist/gs/builtin/builtin.js +85 -5
  22. package/dist/gs/builtin/builtin.js.map +1 -1
  23. package/dist/gs/builtin/channel.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +59 -26
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/cmp/index.js.map +1 -1
  28. package/dist/gs/context/context.d.ts +1 -1
  29. package/dist/gs/context/context.js +20 -11
  30. package/dist/gs/context/context.js.map +1 -1
  31. package/dist/gs/errors/errors.d.ts +7 -0
  32. package/dist/gs/errors/errors.js +190 -0
  33. package/dist/gs/errors/errors.js.map +1 -0
  34. package/dist/gs/errors/index.d.ts +1 -0
  35. package/dist/gs/errors/index.js +2 -0
  36. package/dist/gs/errors/index.js.map +1 -0
  37. package/dist/gs/internal/goarch/index.js +1 -1
  38. package/dist/gs/internal/goarch/index.js.map +1 -1
  39. package/dist/gs/io/index.d.ts +1 -0
  40. package/dist/gs/io/index.js +2 -0
  41. package/dist/gs/io/index.js.map +1 -0
  42. package/dist/gs/io/io.d.ts +107 -0
  43. package/dist/gs/io/io.js +385 -0
  44. package/dist/gs/io/io.js.map +1 -0
  45. package/dist/gs/iter/iter.js.map +1 -1
  46. package/dist/gs/math/bits/index.js +34 -32
  47. package/dist/gs/math/bits/index.js.map +1 -1
  48. package/dist/gs/runtime/runtime.d.ts +1 -0
  49. package/dist/gs/runtime/runtime.js +15 -18
  50. package/dist/gs/runtime/runtime.js.map +1 -1
  51. package/dist/gs/slices/slices.d.ts +1 -1
  52. package/dist/gs/slices/slices.js +1 -1
  53. package/dist/gs/slices/slices.js.map +1 -1
  54. package/dist/gs/strings/builder.d.ts +18 -0
  55. package/dist/gs/strings/builder.js +205 -0
  56. package/dist/gs/strings/builder.js.map +1 -0
  57. package/dist/gs/strings/clone.d.ts +1 -0
  58. package/dist/gs/strings/clone.js +16 -0
  59. package/dist/gs/strings/clone.js.map +1 -0
  60. package/dist/gs/strings/compare.d.ts +1 -0
  61. package/dist/gs/strings/compare.js +14 -0
  62. package/dist/gs/strings/compare.js.map +1 -0
  63. package/dist/gs/strings/index.d.ts +2 -0
  64. package/dist/gs/strings/index.js +3 -0
  65. package/dist/gs/strings/index.js.map +1 -0
  66. package/dist/gs/strings/iter.d.ts +8 -0
  67. package/dist/gs/strings/iter.js +160 -0
  68. package/dist/gs/strings/iter.js.map +1 -0
  69. package/dist/gs/strings/reader.d.ts +34 -0
  70. package/dist/gs/strings/reader.js +418 -0
  71. package/dist/gs/strings/reader.js.map +1 -0
  72. package/dist/gs/strings/replace.d.ts +106 -0
  73. package/dist/gs/strings/replace.js +1136 -0
  74. package/dist/gs/strings/replace.js.map +1 -0
  75. package/dist/gs/strings/search.d.ts +24 -0
  76. package/dist/gs/strings/search.js +169 -0
  77. package/dist/gs/strings/search.js.map +1 -0
  78. package/dist/gs/strings/strings.d.ts +47 -0
  79. package/dist/gs/strings/strings.js +418 -0
  80. package/dist/gs/strings/strings.js.map +1 -0
  81. package/dist/gs/stringslite/index.d.ts +1 -0
  82. package/dist/gs/stringslite/index.js +2 -0
  83. package/dist/gs/stringslite/index.js.map +1 -0
  84. package/dist/gs/stringslite/strings.d.ts +11 -0
  85. package/dist/gs/stringslite/strings.js +67 -0
  86. package/dist/gs/stringslite/strings.js.map +1 -0
  87. package/dist/gs/sync/index.d.ts +1 -0
  88. package/dist/gs/sync/index.js +2 -0
  89. package/dist/gs/sync/index.js.map +1 -0
  90. package/dist/gs/sync/sync.d.ts +79 -0
  91. package/dist/gs/sync/sync.js +392 -0
  92. package/dist/gs/sync/sync.js.map +1 -0
  93. package/dist/gs/time/time.js +7 -7
  94. package/dist/gs/time/time.js.map +1 -1
  95. package/dist/gs/unicode/index.d.ts +1 -0
  96. package/dist/gs/unicode/index.js +2 -0
  97. package/dist/gs/unicode/index.js.map +1 -0
  98. package/dist/gs/unicode/unicode.d.ts +105 -0
  99. package/dist/gs/unicode/unicode.js +332 -0
  100. package/dist/gs/unicode/unicode.js.map +1 -0
  101. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  102. package/dist/gs/unicode/utf8/index.js +3 -0
  103. package/dist/gs/unicode/utf8/index.js.map +1 -0
  104. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  105. package/dist/gs/unicode/utf8/utf8.js +196 -0
  106. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  107. package/dist/gs/unsafe/index.d.ts +1 -0
  108. package/dist/gs/unsafe/index.js +2 -0
  109. package/dist/gs/unsafe/index.js.map +1 -0
  110. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  111. package/dist/gs/unsafe/unsafe.js +44 -0
  112. package/dist/gs/unsafe/unsafe.js.map +1 -0
  113. package/go.mod +2 -1
  114. package/go.sum +6 -2
  115. package/gs/README.md +6 -0
  116. package/gs/builtin/builtin.ts +158 -0
  117. package/gs/builtin/channel.ts +683 -0
  118. package/gs/builtin/defer.ts +58 -0
  119. package/gs/builtin/index.ts +1 -0
  120. package/gs/builtin/io.ts +22 -0
  121. package/gs/builtin/map.ts +50 -0
  122. package/gs/builtin/slice.ts +1030 -0
  123. package/gs/builtin/type.ts +1106 -0
  124. package/gs/builtin/varRef.ts +25 -0
  125. package/gs/cmp/godoc.txt +8 -0
  126. package/gs/cmp/index.ts +29 -0
  127. package/gs/context/context.ts +401 -0
  128. package/gs/context/godoc.txt +69 -0
  129. package/gs/context/index.ts +1 -0
  130. package/gs/errors/errors.ts +223 -0
  131. package/gs/errors/godoc.txt +63 -0
  132. package/gs/errors/index.ts +1 -0
  133. package/gs/internal/goarch/godoc.txt +39 -0
  134. package/gs/internal/goarch/index.ts +18 -0
  135. package/gs/io/godoc.txt +61 -0
  136. package/gs/io/index.ts +1 -0
  137. package/gs/io/io.go +75 -0
  138. package/gs/io/io.ts +546 -0
  139. package/gs/iter/godoc.txt +203 -0
  140. package/gs/iter/index.ts +1 -0
  141. package/gs/iter/iter.ts +117 -0
  142. package/gs/math/bits/index.ts +356 -0
  143. package/gs/math/godoc.txt +76 -0
  144. package/gs/runtime/godoc.txt +331 -0
  145. package/gs/runtime/index.ts +1 -0
  146. package/gs/runtime/runtime.ts +178 -0
  147. package/gs/slices/godoc.txt +44 -0
  148. package/gs/slices/index.ts +1 -0
  149. package/gs/slices/slices.ts +22 -0
  150. package/gs/strings/builder.test.ts +121 -0
  151. package/gs/strings/builder.ts +223 -0
  152. package/gs/strings/clone.test.ts +43 -0
  153. package/gs/strings/clone.ts +17 -0
  154. package/gs/strings/compare.test.ts +84 -0
  155. package/gs/strings/compare.ts +13 -0
  156. package/gs/strings/godoc.txt +66 -0
  157. package/gs/strings/index.ts +2 -0
  158. package/gs/strings/iter.test.ts +343 -0
  159. package/gs/strings/iter.ts +171 -0
  160. package/gs/strings/reader.test.ts +243 -0
  161. package/gs/strings/reader.ts +451 -0
  162. package/gs/strings/replace.test.ts +181 -0
  163. package/gs/strings/replace.ts +1310 -0
  164. package/gs/strings/search.test.ts +214 -0
  165. package/gs/strings/search.ts +213 -0
  166. package/gs/strings/strings.test.ts +477 -0
  167. package/gs/strings/strings.ts +510 -0
  168. package/gs/stringslite/godoc.txt +17 -0
  169. package/gs/stringslite/index.ts +1 -0
  170. package/gs/stringslite/strings.ts +82 -0
  171. package/gs/sync/godoc.txt +21 -0
  172. package/gs/sync/index.ts +1 -0
  173. package/gs/sync/sync.go +64 -0
  174. package/gs/sync/sync.ts +449 -0
  175. package/gs/time/godoc.md +116 -0
  176. package/gs/time/godoc.txt +116 -0
  177. package/gs/time/index.ts +1 -0
  178. package/gs/time/time.ts +272 -0
  179. package/gs/unicode/godoc.txt +52 -0
  180. package/gs/unicode/index.ts +1 -0
  181. package/gs/unicode/unicode.go +38 -0
  182. package/gs/unicode/unicode.ts +418 -0
  183. package/gs/unicode/utf8/godoc.txt +22 -0
  184. package/gs/unicode/utf8/index.ts +2 -0
  185. package/gs/unicode/utf8/utf8.ts +227 -0
  186. package/gs/unsafe/godoc.txt +19 -0
  187. package/gs/unsafe/index.ts +1 -0
  188. package/gs/unsafe/unsafe.test.ts +68 -0
  189. package/gs/unsafe/unsafe.ts +77 -0
  190. package/package.json +6 -4
@@ -0,0 +1,343 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import * as $ from '@goscript/builtin/builtin.js'
3
+ import {
4
+ Lines,
5
+ SplitSeq,
6
+ SplitAfterSeq,
7
+ FieldsSeq,
8
+ FieldsFuncSeq,
9
+ } from './iter.js'
10
+
11
+ describe('strings/iter', () => {
12
+ describe('Lines', () => {
13
+ it('should yield lines with newlines', () => {
14
+ const lines: string[] = []
15
+ const seq = Lines('line1\nline2\nline3')
16
+ seq((line: string) => {
17
+ lines.push(line)
18
+ return true
19
+ })
20
+ expect(lines).toEqual(['line1\n', 'line2\n', 'line3'])
21
+ })
22
+
23
+ it('should handle empty string', () => {
24
+ const lines: string[] = []
25
+ const seq = Lines('')
26
+ seq((line: string) => {
27
+ lines.push(line)
28
+ return true
29
+ })
30
+ expect(lines).toEqual([])
31
+ })
32
+
33
+ it('should handle string without final newline', () => {
34
+ const lines: string[] = []
35
+ const seq = Lines('line1\nline2')
36
+ seq((line: string) => {
37
+ lines.push(line)
38
+ return true
39
+ })
40
+ expect(lines).toEqual(['line1\n', 'line2'])
41
+ })
42
+
43
+ it('should handle single line', () => {
44
+ const lines: string[] = []
45
+ const seq = Lines('single line')
46
+ seq((line: string) => {
47
+ lines.push(line)
48
+ return true
49
+ })
50
+ expect(lines).toEqual(['single line'])
51
+ })
52
+
53
+ it('should handle early termination', () => {
54
+ const lines: string[] = []
55
+ const seq = Lines('line1\nline2\nline3\n')
56
+ seq((line: string) => {
57
+ lines.push(line)
58
+ return lines.length < 2 // Stop after 2 lines
59
+ })
60
+ expect(lines).toEqual(['line1\n', 'line2\n'])
61
+ })
62
+
63
+ it('should handle multiple consecutive newlines', () => {
64
+ const lines: string[] = []
65
+ const seq = Lines('line1\n\nline3\n')
66
+ seq((line: string) => {
67
+ lines.push(line)
68
+ return true
69
+ })
70
+ expect(lines).toEqual(['line1\n', '\n', 'line3\n'])
71
+ })
72
+ })
73
+
74
+ describe('SplitSeq', () => {
75
+ it('should split by separator', () => {
76
+ const parts: string[] = []
77
+ const seq = SplitSeq('a,b,c', ',')
78
+ seq((part: string) => {
79
+ parts.push(part)
80
+ return true
81
+ })
82
+ expect(parts).toEqual(['a', 'b', 'c'])
83
+ })
84
+
85
+ it('should handle empty separator (explode)', () => {
86
+ const parts: string[] = []
87
+ const seq = SplitSeq('abc', '')
88
+ seq((part: string) => {
89
+ parts.push(part)
90
+ return true
91
+ })
92
+ expect(parts).toEqual(['a', 'b', 'c'])
93
+ })
94
+
95
+ it('should handle no separator found', () => {
96
+ const parts: string[] = []
97
+ const seq = SplitSeq('hello', ',')
98
+ seq((part: string) => {
99
+ parts.push(part)
100
+ return true
101
+ })
102
+ expect(parts).toEqual(['hello'])
103
+ })
104
+
105
+ it('should handle empty string', () => {
106
+ const parts: string[] = []
107
+ const seq = SplitSeq('', ',')
108
+ seq((part: string) => {
109
+ parts.push(part)
110
+ return true
111
+ })
112
+ expect(parts).toEqual([''])
113
+ })
114
+
115
+ it('should handle early termination', () => {
116
+ const parts: string[] = []
117
+ const seq = SplitSeq('a,b,c,d', ',')
118
+ seq((part: string) => {
119
+ parts.push(part)
120
+ return parts.length < 2
121
+ })
122
+ expect(parts).toEqual(['a', 'b'])
123
+ })
124
+
125
+ it('should handle unicode', () => {
126
+ const parts: string[] = []
127
+ const seq = SplitSeq('世界,你好', ',')
128
+ // This test expects an error due to UTF-8 slicing limitations in JavaScript
129
+ expect(() => {
130
+ seq((part: string) => {
131
+ parts.push(part)
132
+ return true
133
+ })
134
+ }).toThrow('Cannot slice string at byte indices')
135
+ })
136
+ })
137
+
138
+ describe('SplitAfterSeq', () => {
139
+ it('should split after separator', () => {
140
+ const parts: string[] = []
141
+ const seq = SplitAfterSeq('a,b,c', ',')
142
+ seq((part: string) => {
143
+ parts.push(part)
144
+ return true
145
+ })
146
+ expect(parts).toEqual(['a,', 'b,', 'c'])
147
+ })
148
+
149
+ it('should handle empty separator (explode)', () => {
150
+ const parts: string[] = []
151
+ const seq = SplitAfterSeq('abc', '')
152
+ seq((part: string) => {
153
+ parts.push(part)
154
+ return true
155
+ })
156
+ expect(parts).toEqual(['a', 'b', 'c'])
157
+ })
158
+
159
+ it('should handle no separator found', () => {
160
+ const parts: string[] = []
161
+ const seq = SplitAfterSeq('hello', ',')
162
+ seq((part: string) => {
163
+ parts.push(part)
164
+ return true
165
+ })
166
+ expect(parts).toEqual(['hello'])
167
+ })
168
+
169
+ it('should handle trailing separator', () => {
170
+ const parts: string[] = []
171
+ const seq = SplitAfterSeq('a,b,', ',')
172
+ seq((part: string) => {
173
+ parts.push(part)
174
+ return true
175
+ })
176
+ expect(parts).toEqual(['a,', 'b,', ''])
177
+ })
178
+
179
+ it('should handle early termination', () => {
180
+ const parts: string[] = []
181
+ const seq = SplitAfterSeq('a,b,c,d', ',')
182
+ seq((part: string) => {
183
+ parts.push(part)
184
+ return parts.length < 2
185
+ })
186
+ expect(parts).toEqual(['a,', 'b,'])
187
+ })
188
+ })
189
+
190
+ describe('FieldsSeq', () => {
191
+ it('should split on whitespace', () => {
192
+ const fields: string[] = []
193
+ const seq = FieldsSeq(' hello world ')
194
+ seq((field: string) => {
195
+ fields.push(field)
196
+ return true
197
+ })
198
+ expect(fields).toEqual(['hello', 'world'])
199
+ })
200
+
201
+ it('should handle empty string', () => {
202
+ const fields: string[] = []
203
+ const seq = FieldsSeq('')
204
+ seq((field: string) => {
205
+ fields.push(field)
206
+ return true
207
+ })
208
+ expect(fields).toEqual([])
209
+ })
210
+
211
+ it('should handle only whitespace', () => {
212
+ const fields: string[] = []
213
+ const seq = FieldsSeq(' \t\n ')
214
+ seq((field: string) => {
215
+ fields.push(field)
216
+ return true
217
+ })
218
+ expect(fields).toEqual([])
219
+ })
220
+
221
+ it('should handle single field', () => {
222
+ const fields: string[] = []
223
+ const seq = FieldsSeq('hello')
224
+ seq((field: string) => {
225
+ fields.push(field)
226
+ return true
227
+ })
228
+ expect(fields).toEqual(['hello'])
229
+ })
230
+
231
+ it('should handle mixed whitespace', () => {
232
+ const fields: string[] = []
233
+ const seq = FieldsSeq('hello\tworld\ntest')
234
+ seq((field: string) => {
235
+ fields.push(field)
236
+ return true
237
+ })
238
+ expect(fields).toEqual(['hello', 'world', 'test'])
239
+ })
240
+
241
+ it('should handle early termination', () => {
242
+ const fields: string[] = []
243
+ const seq = FieldsSeq('one two three four')
244
+ seq((field: string) => {
245
+ fields.push(field)
246
+ return fields.length < 2
247
+ })
248
+ expect(fields).toEqual(['one', 'two'])
249
+ })
250
+
251
+ it('should handle unicode whitespace', () => {
252
+ const fields: string[] = []
253
+ const seq = FieldsSeq('hello world') // contains unicode space
254
+ seq((field: string) => {
255
+ fields.push(field)
256
+ return true
257
+ })
258
+ expect(fields).toEqual(['hello', 'world'])
259
+ })
260
+ })
261
+
262
+ describe('FieldsFuncSeq', () => {
263
+ it('should split using predicate function', () => {
264
+ const fields: string[] = []
265
+ const seq = FieldsFuncSeq('a,b,c', (r: number) => r === 44) // comma
266
+ seq((field: string) => {
267
+ fields.push(field)
268
+ return true
269
+ })
270
+ expect(fields).toEqual(['a', 'b', 'c'])
271
+ })
272
+
273
+ it('should handle null predicate', () => {
274
+ const fields: string[] = []
275
+ const seq = FieldsFuncSeq('hello world', null)
276
+ seq((field: string) => {
277
+ fields.push(field)
278
+ return true
279
+ })
280
+ expect(fields).toEqual([])
281
+ })
282
+
283
+ it('should handle empty string', () => {
284
+ const fields: string[] = []
285
+ const seq = FieldsFuncSeq('', (r: number) => r === 32) // space
286
+ seq((field: string) => {
287
+ fields.push(field)
288
+ return true
289
+ })
290
+ expect(fields).toEqual([])
291
+ })
292
+
293
+ it('should handle no separator matches', () => {
294
+ const fields: string[] = []
295
+ const seq = FieldsFuncSeq('hello', (r: number) => r === 44) // comma
296
+ seq((field: string) => {
297
+ fields.push(field)
298
+ return true
299
+ })
300
+ expect(fields).toEqual(['hello'])
301
+ })
302
+
303
+ it('should handle all characters match predicate', () => {
304
+ const fields: string[] = []
305
+ const seq = FieldsFuncSeq('aaa', (r: number) => r === 97) // 'a'
306
+ seq((field: string) => {
307
+ fields.push(field)
308
+ return true
309
+ })
310
+ expect(fields).toEqual([])
311
+ })
312
+
313
+ it('should handle mixed ascii and unicode', () => {
314
+ const fields: string[] = []
315
+ const seq = FieldsFuncSeq('hello世world', (r: number) => r === 0x4e16) // '世'
316
+ seq((field: string) => {
317
+ fields.push(field)
318
+ return true
319
+ })
320
+ expect(fields).toEqual(['hello', 'world'])
321
+ })
322
+
323
+ it('should handle early termination', () => {
324
+ const fields: string[] = []
325
+ const seq = FieldsFuncSeq('a;b;c;d', (r: number) => r === 59) // semicolon
326
+ seq((field: string) => {
327
+ fields.push(field)
328
+ return fields.length < 2
329
+ })
330
+ expect(fields).toEqual(['a', 'b'])
331
+ })
332
+
333
+ it('should handle consecutive separators', () => {
334
+ const fields: string[] = []
335
+ const seq = FieldsFuncSeq('a,,b', (r: number) => r === 44) // comma
336
+ seq((field: string) => {
337
+ fields.push(field)
338
+ return true
339
+ })
340
+ expect(fields).toEqual(['a', 'b'])
341
+ })
342
+ })
343
+ })
@@ -0,0 +1,171 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+ import { Index, IndexByte } from './strings.js'
3
+
4
+ import * as iter from '@goscript/iter/index.js'
5
+
6
+ import * as unicode from '@goscript/unicode/index.js'
7
+
8
+ import * as utf8 from '@goscript/unicode/utf8/index.js'
9
+
10
+ // ASCII space characters lookup map
11
+ const asciiSpace: { [key: number]: boolean } = {
12
+ 9: true, // \t
13
+ 10: true, // \n
14
+ 11: true, // \v
15
+ 12: true, // \f
16
+ 13: true, // \r
17
+ 32: true, // space
18
+ }
19
+
20
+ // Lines returns an iterator over the newline-terminated lines in the string s.
21
+ // The lines yielded by the iterator include their terminating newlines.
22
+ // If s is empty, the iterator yields no lines at all.
23
+ // If s does not end in a newline, the final yielded line will not end in a newline.
24
+ // It returns a single-use iterator.
25
+ export function Lines(s: string): iter.Seq<string> {
26
+ return (_yield: ((p0: string) => boolean) | null): void => {
27
+ for (; $.len(s) > 0; ) {
28
+ let line: string = ''
29
+ {
30
+ let i = IndexByte(s, 10)
31
+ if (i >= 0) {
32
+ ;[line, s] = [
33
+ $.sliceString(s, undefined, i + 1),
34
+ $.sliceString(s, i + 1, undefined),
35
+ ]
36
+ } else {
37
+ ;[line, s] = [s, '']
38
+ }
39
+ }
40
+ if (!_yield!(line)) {
41
+ return
42
+ }
43
+ }
44
+ return
45
+ }
46
+ }
47
+
48
+ // explodeSeq returns an iterator over the runes in s.
49
+ export function explodeSeq(s: string): iter.Seq<string> {
50
+ return (_yield: ((p0: string) => boolean) | null): void => {
51
+ for (; $.len(s) > 0; ) {
52
+ let [, size] = utf8.DecodeRuneInString(s)
53
+ if (!_yield!($.sliceString(s, undefined, size))) {
54
+ return
55
+ }
56
+ s = $.sliceString(s, size, undefined)
57
+ }
58
+ }
59
+ }
60
+
61
+ // splitSeq is SplitSeq or SplitAfterSeq, configured by how many
62
+ // bytes of sep to include in the results (none or all).
63
+ export function splitSeq(
64
+ s: string,
65
+ sep: string,
66
+ sepSave: number,
67
+ ): iter.Seq<string> {
68
+ if ($.len(sep) == 0) {
69
+ return explodeSeq(s)
70
+ }
71
+ return (_yield: ((p0: string) => boolean) | null): void => {
72
+ for (;;) {
73
+ let i = Index(s, sep)
74
+ if (i < 0) {
75
+ break
76
+ }
77
+ let frag = $.sliceString(s, undefined, i + sepSave)
78
+ if (!_yield!(frag)) {
79
+ return
80
+ }
81
+ s = $.sliceString(s, i + $.len(sep), undefined)
82
+ }
83
+ _yield!(s)
84
+ }
85
+ }
86
+
87
+ // SplitSeq returns an iterator over all substrings of s separated by sep.
88
+ // The iterator yields the same strings that would be returned by [Split](s, sep),
89
+ // but without constructing the slice.
90
+ // It returns a single-use iterator.
91
+ export function SplitSeq(s: string, sep: string): iter.Seq<string> {
92
+ return splitSeq(s, sep, 0)
93
+ }
94
+
95
+ // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
96
+ // The iterator yields the same strings that would be returned by [SplitAfter](s, sep),
97
+ // but without constructing the slice.
98
+ // It returns a single-use iterator.
99
+ export function SplitAfterSeq(s: string, sep: string): iter.Seq<string> {
100
+ return splitSeq(s, sep, $.len(sep))
101
+ }
102
+
103
+ // FieldsSeq returns an iterator over substrings of s split around runs of
104
+ // whitespace characters, as defined by [unicode.IsSpace].
105
+ // The iterator yields the same strings that would be returned by [Fields](s),
106
+ // but without constructing the slice.
107
+ export function FieldsSeq(s: string): iter.Seq<string> {
108
+ return (_yield: ((p0: string) => boolean) | null): void => {
109
+ let start = -1
110
+ for (let i = 0; i < $.len(s); ) {
111
+ let size = 1
112
+ let r = $.indexString(s, i) as number
113
+ let isSpace = asciiSpace[$.indexString(s, i)] === true
114
+ if (r >= utf8.RuneSelf) {
115
+ ;[r, size] = utf8.DecodeRuneInString($.sliceString(s, i, undefined))
116
+ isSpace = unicode.IsSpace(r)
117
+ }
118
+ if (isSpace) {
119
+ if (start >= 0) {
120
+ if (!_yield!($.sliceString(s, start, i))) {
121
+ return
122
+ }
123
+ start = -1
124
+ }
125
+ } else if (start < 0) {
126
+ start = i
127
+ }
128
+ i += size
129
+ }
130
+ if (start >= 0) {
131
+ _yield!($.sliceString(s, start, undefined))
132
+ }
133
+ }
134
+ }
135
+
136
+ // FieldsFuncSeq returns an iterator over substrings of s split around runs of
137
+ // Unicode code points satisfying f(c).
138
+ // The iterator yields the same strings that would be returned by [FieldsFunc](s),
139
+ // but without constructing the slice.
140
+ export function FieldsFuncSeq(
141
+ s: string,
142
+ f: ((p0: number) => boolean) | null,
143
+ ): iter.Seq<string> {
144
+ return (_yield: ((p0: string) => boolean) | null): void => {
145
+ if (f === null) {
146
+ return
147
+ }
148
+ let start = -1
149
+ for (let i = 0; i < $.len(s); ) {
150
+ let size = 1
151
+ let r = $.indexString(s, i) as number
152
+ if (r >= utf8.RuneSelf) {
153
+ ;[r, size] = utf8.DecodeRuneInString($.sliceString(s, i, undefined))
154
+ }
155
+ if (f(r)) {
156
+ if (start >= 0) {
157
+ if (!_yield!($.sliceString(s, start, i))) {
158
+ return
159
+ }
160
+ start = -1
161
+ }
162
+ } else if (start < 0) {
163
+ start = i
164
+ }
165
+ i += size
166
+ }
167
+ if (start >= 0) {
168
+ _yield!($.sliceString(s, start, undefined))
169
+ }
170
+ }
171
+ }