rapydscript-ns 0.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 (144) hide show
  1. package/.agignore +1 -0
  2. package/.gitattributes +4 -0
  3. package/.github/workflows/ci.yml +38 -0
  4. package/.github/workflows/web-repl-page-deploy.yml +42 -0
  5. package/=template.pyj +5 -0
  6. package/CHANGELOG.md +456 -0
  7. package/CONTRIBUTORS +13 -0
  8. package/HACKING.md +103 -0
  9. package/LICENSE +24 -0
  10. package/README.md +2512 -0
  11. package/TODO.md +327 -0
  12. package/add-toc-to-readme +2 -0
  13. package/bin/export +75 -0
  14. package/bin/rapydscript +70 -0
  15. package/bin/web-repl-export +102 -0
  16. package/build +3 -0
  17. package/package.json +46 -0
  18. package/publish.py +37 -0
  19. package/release/baselib-plain-pretty.js +4370 -0
  20. package/release/baselib-plain-ugly.js +3 -0
  21. package/release/compiler.js +18394 -0
  22. package/release/signatures.json +31 -0
  23. package/session.vim +4 -0
  24. package/setup.cfg +2 -0
  25. package/src/ast.pyj +1356 -0
  26. package/src/baselib-builtins.pyj +279 -0
  27. package/src/baselib-containers.pyj +723 -0
  28. package/src/baselib-errors.pyj +37 -0
  29. package/src/baselib-internal.pyj +421 -0
  30. package/src/baselib-itertools.pyj +97 -0
  31. package/src/baselib-str.pyj +798 -0
  32. package/src/compiler.pyj +36 -0
  33. package/src/errors.pyj +30 -0
  34. package/src/lib/aes.pyj +646 -0
  35. package/src/lib/collections.pyj +695 -0
  36. package/src/lib/elementmaker.pyj +83 -0
  37. package/src/lib/encodings.pyj +126 -0
  38. package/src/lib/functools.pyj +148 -0
  39. package/src/lib/gettext.pyj +569 -0
  40. package/src/lib/itertools.pyj +580 -0
  41. package/src/lib/math.pyj +193 -0
  42. package/src/lib/numpy.pyj +2101 -0
  43. package/src/lib/operator.pyj +11 -0
  44. package/src/lib/pythonize.pyj +20 -0
  45. package/src/lib/random.pyj +118 -0
  46. package/src/lib/re.pyj +470 -0
  47. package/src/lib/traceback.pyj +63 -0
  48. package/src/lib/uuid.pyj +77 -0
  49. package/src/monaco-language-service/analyzer.js +526 -0
  50. package/src/monaco-language-service/builtins.js +543 -0
  51. package/src/monaco-language-service/completions.js +498 -0
  52. package/src/monaco-language-service/diagnostics.js +643 -0
  53. package/src/monaco-language-service/dts.js +550 -0
  54. package/src/monaco-language-service/hover.js +121 -0
  55. package/src/monaco-language-service/index.js +386 -0
  56. package/src/monaco-language-service/scope.js +162 -0
  57. package/src/monaco-language-service/signature.js +144 -0
  58. package/src/output/__init__.pyj +0 -0
  59. package/src/output/classes.pyj +296 -0
  60. package/src/output/codegen.pyj +492 -0
  61. package/src/output/comments.pyj +45 -0
  62. package/src/output/exceptions.pyj +105 -0
  63. package/src/output/functions.pyj +491 -0
  64. package/src/output/literals.pyj +109 -0
  65. package/src/output/loops.pyj +444 -0
  66. package/src/output/modules.pyj +329 -0
  67. package/src/output/operators.pyj +429 -0
  68. package/src/output/statements.pyj +463 -0
  69. package/src/output/stream.pyj +309 -0
  70. package/src/output/treeshake.pyj +182 -0
  71. package/src/output/utils.pyj +72 -0
  72. package/src/parse.pyj +3106 -0
  73. package/src/string_interpolation.pyj +72 -0
  74. package/src/tokenizer.pyj +702 -0
  75. package/src/unicode_aliases.pyj +576 -0
  76. package/src/utils.pyj +192 -0
  77. package/test/_import_one.pyj +37 -0
  78. package/test/_import_two/__init__.pyj +11 -0
  79. package/test/_import_two/level2/__init__.pyj +0 -0
  80. package/test/_import_two/level2/deep.pyj +4 -0
  81. package/test/_import_two/other.pyj +6 -0
  82. package/test/_import_two/sub.pyj +13 -0
  83. package/test/aes_vectors.pyj +421 -0
  84. package/test/annotations.pyj +80 -0
  85. package/test/baselib.pyj +319 -0
  86. package/test/classes.pyj +452 -0
  87. package/test/collections.pyj +152 -0
  88. package/test/decorators.pyj +77 -0
  89. package/test/dict_spread.pyj +76 -0
  90. package/test/docstrings.pyj +39 -0
  91. package/test/elementmaker_test.pyj +45 -0
  92. package/test/ellipsis.pyj +49 -0
  93. package/test/functions.pyj +151 -0
  94. package/test/generators.pyj +41 -0
  95. package/test/generic.pyj +370 -0
  96. package/test/imports.pyj +72 -0
  97. package/test/internationalization.pyj +73 -0
  98. package/test/lint.pyj +164 -0
  99. package/test/loops.pyj +85 -0
  100. package/test/numpy.pyj +734 -0
  101. package/test/omit_function_metadata.pyj +20 -0
  102. package/test/regexp.pyj +55 -0
  103. package/test/repl.pyj +121 -0
  104. package/test/scoped_flags.pyj +76 -0
  105. package/test/starargs.pyj +506 -0
  106. package/test/starred_assign.pyj +104 -0
  107. package/test/str.pyj +198 -0
  108. package/test/subscript_tuple.pyj +53 -0
  109. package/test/unit/fixtures/fibonacci_expected.js +46 -0
  110. package/test/unit/index.js +2989 -0
  111. package/test/unit/language-service-builtins.js +815 -0
  112. package/test/unit/language-service-completions.js +1067 -0
  113. package/test/unit/language-service-dts.js +543 -0
  114. package/test/unit/language-service-hover.js +455 -0
  115. package/test/unit/language-service-scope.js +833 -0
  116. package/test/unit/language-service-signature.js +458 -0
  117. package/test/unit/language-service.js +705 -0
  118. package/test/unit/run-language-service.js +41 -0
  119. package/test/unit/web-repl.js +484 -0
  120. package/tools/build-language-service.js +190 -0
  121. package/tools/cli.js +547 -0
  122. package/tools/compile.js +219 -0
  123. package/tools/compiler.js +108 -0
  124. package/tools/completer.js +131 -0
  125. package/tools/embedded_compiler.js +251 -0
  126. package/tools/export.js +316 -0
  127. package/tools/gettext.js +185 -0
  128. package/tools/ini.js +65 -0
  129. package/tools/lint.js +705 -0
  130. package/tools/msgfmt.js +187 -0
  131. package/tools/repl.js +223 -0
  132. package/tools/self.js +162 -0
  133. package/tools/test.js +118 -0
  134. package/tools/utils.js +128 -0
  135. package/tools/web_repl.js +95 -0
  136. package/try +41 -0
  137. package/web-repl/env.js +74 -0
  138. package/web-repl/index.html +163 -0
  139. package/web-repl/language-service.js +4084 -0
  140. package/web-repl/main.js +254 -0
  141. package/web-repl/prism.css +139 -0
  142. package/web-repl/prism.js +113 -0
  143. package/web-repl/rapydscript.js +435 -0
  144. package/web-repl/sha1.js +25 -0
@@ -0,0 +1,580 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+ # RapydScript implementation of Python's itertools standard library.
4
+ #
5
+ # Supported: count, cycle, repeat, accumulate, chain, compress,
6
+ # dropwhile, filterfalse, groupby, islice, pairwise,
7
+ # starmap, takewhile, zip_longest, product,
8
+ # permutations, combinations, combinations_with_replacement
9
+
10
+ # Sentinel: distinguishes "initial not provided" from "initial=None"
11
+ _NO_INITIAL = {}
12
+
13
+
14
+ def _to_array(iterable):
15
+ """Convert any iterable to a plain JavaScript array."""
16
+ if Array.isArray(iterable):
17
+ return iterable.slice()
18
+ if jstype(iterable) is 'string':
19
+ return iterable.split('')
20
+ a = []
21
+ it = iter(iterable)
22
+ r = it.next()
23
+ while not r.done:
24
+ a.push(r.value)
25
+ r = it.next()
26
+ return a
27
+
28
+
29
+ # ── Infinite iterators ─────────────────────────────────────────────────────
30
+
31
+ class count:
32
+ """count(start=0, step=1) -> count from start by step indefinitely."""
33
+
34
+ def __init__(self, start=0, step=1):
35
+ self._n = start
36
+ self._step = step
37
+
38
+ def __iter__(self):
39
+ return self
40
+
41
+ def next(self):
42
+ val = self._n
43
+ self._n += self._step
44
+ return {'value': val, 'done': False}
45
+
46
+ def __next__(self):
47
+ return self.next()['value']
48
+
49
+
50
+ class cycle:
51
+ """cycle(p) -> p0, p1, ... plast, p0, p1, ... indefinitely."""
52
+
53
+ def __init__(self, iterable):
54
+ self._data = _to_array(iterable)
55
+ self._i = 0
56
+
57
+ def __iter__(self):
58
+ return self
59
+
60
+ def next(self):
61
+ if self._data.length == 0:
62
+ return {'value': undefined, 'done': True}
63
+ val = self._data[self._i]
64
+ self._i = (self._i + 1) % self._data.length
65
+ return {'value': val, 'done': False}
66
+
67
+ def __next__(self):
68
+ r = self.next()
69
+ if r.done:
70
+ raise StopIteration()
71
+ return r.value
72
+
73
+
74
+ class repeat:
75
+ """repeat(elem, n=None) -> repeat elem n times, or forever if n is None."""
76
+
77
+ def __init__(self, obj, times=None):
78
+ self._obj = obj
79
+ self._times = times
80
+ self._n = 0
81
+
82
+ def __iter__(self):
83
+ return self
84
+
85
+ def next(self):
86
+ if self._times is not None and self._n >= self._times:
87
+ return {'value': undefined, 'done': True}
88
+ self._n += 1
89
+ return {'value': self._obj, 'done': False}
90
+
91
+ def __next__(self):
92
+ r = self.next()
93
+ if r.done:
94
+ raise StopIteration()
95
+ return r.value
96
+
97
+
98
+ # ── Finite iterators ───────────────────────────────────────────────────────
99
+
100
+ class accumulate:
101
+ """accumulate(p, func=add, initial=no_value) -> p0, p0+p1, p0+p1+p2, ..."""
102
+
103
+ def __init__(self, iterable, func=None, initial=_NO_INITIAL):
104
+ self._it = iter(iterable)
105
+ self._func = func
106
+ self._has_initial = initial is not _NO_INITIAL
107
+ self._total = initial if self._has_initial else None
108
+ self._started = self._has_initial
109
+ self._initial_pending = self._has_initial
110
+
111
+ def __iter__(self):
112
+ return self
113
+
114
+ def next(self):
115
+ if self._initial_pending:
116
+ self._initial_pending = False
117
+ return {'value': self._total, 'done': False}
118
+ r = self._it.next()
119
+ if r.done:
120
+ return {'value': undefined, 'done': True}
121
+ if not self._started:
122
+ self._total = r.value
123
+ self._started = True
124
+ else:
125
+ if self._func is None:
126
+ self._total += r.value
127
+ else:
128
+ self._total = self._func(self._total, r.value)
129
+ return {'value': self._total, 'done': False}
130
+
131
+ def __next__(self):
132
+ r = self.next()
133
+ if r.done:
134
+ raise StopIteration()
135
+ return r.value
136
+
137
+
138
+ class _ChainIter:
139
+ """Internal: chain from a pre-built list of iterators."""
140
+
141
+ def __init__(self, iters):
142
+ self._iters = iters
143
+ self._i = 0
144
+
145
+ def __iter__(self):
146
+ return self
147
+
148
+ def next(self):
149
+ while self._i < self._iters.length:
150
+ r = self._iters[self._i].next()
151
+ if not r.done:
152
+ return r
153
+ self._i += 1
154
+ return {'value': undefined, 'done': True}
155
+
156
+ def __next__(self):
157
+ r = self.next()
158
+ if r.done:
159
+ raise StopIteration()
160
+ return r.value
161
+
162
+
163
+ class _ChainFromIterable:
164
+ """Internal: chain.from_iterable implementation."""
165
+
166
+ def __init__(self, iterable):
167
+ self._outer = iter(iterable)
168
+ self._inner = None
169
+
170
+ def __iter__(self):
171
+ return self
172
+
173
+ def next(self):
174
+ while True:
175
+ if self._inner is not None:
176
+ r = self._inner.next()
177
+ if not r.done:
178
+ return r
179
+ self._inner = None
180
+ outer_r = self._outer.next()
181
+ if outer_r.done:
182
+ return {'value': undefined, 'done': True}
183
+ self._inner = iter(_to_array(outer_r.value))
184
+
185
+ def __next__(self):
186
+ r = self.next()
187
+ if r.done:
188
+ raise StopIteration()
189
+ return r.value
190
+
191
+
192
+ def chain(*iterables):
193
+ """chain(p, q, ...) -> p0, p1, ... plast, q0, q1, ..."""
194
+ return _ChainIter([iter(it) for it in iterables])
195
+
196
+ chain.from_iterable = def(iterable):
197
+ """chain.from_iterable([[A,B],[C,D]]) -> A B C D"""
198
+ return _ChainFromIterable(iterable)
199
+
200
+
201
+ class compress:
202
+ """compress(data, selectors) -> (d[i] if s[i]) for each i."""
203
+
204
+ def __init__(self, data, selectors):
205
+ self._data = iter(data)
206
+ self._sel = iter(selectors)
207
+
208
+ def __iter__(self):
209
+ return self
210
+
211
+ def next(self):
212
+ while True:
213
+ dr = self._data.next()
214
+ sr = self._sel.next()
215
+ if dr.done or sr.done:
216
+ return {'value': undefined, 'done': True}
217
+ if sr.value:
218
+ return {'value': dr.value, 'done': False}
219
+
220
+ def __next__(self):
221
+ r = self.next()
222
+ if r.done:
223
+ raise StopIteration()
224
+ return r.value
225
+
226
+
227
+ class dropwhile:
228
+ """dropwhile(pred, seq) -> seq[n], seq[n+1], ... (starting where pred fails)."""
229
+
230
+ def __init__(self, predicate, iterable):
231
+ self._pred = predicate
232
+ self._it = iter(iterable)
233
+ self._dropping = True
234
+
235
+ def __iter__(self):
236
+ return self
237
+
238
+ def next(self):
239
+ while True:
240
+ r = self._it.next()
241
+ if r.done:
242
+ return {'value': undefined, 'done': True}
243
+ if self._dropping:
244
+ if not self._pred(r.value):
245
+ self._dropping = False
246
+ return {'value': r.value, 'done': False}
247
+ else:
248
+ return {'value': r.value, 'done': False}
249
+
250
+ def __next__(self):
251
+ r = self.next()
252
+ if r.done:
253
+ raise StopIteration()
254
+ return r.value
255
+
256
+
257
+ class filterfalse:
258
+ """filterfalse(pred, seq) -> elements of seq where pred(elem) is falsy."""
259
+
260
+ def __init__(self, predicate, iterable):
261
+ self._pred = predicate
262
+ self._it = iter(iterable)
263
+
264
+ def __iter__(self):
265
+ return self
266
+
267
+ def next(self):
268
+ while True:
269
+ r = self._it.next()
270
+ if r.done:
271
+ return {'value': undefined, 'done': True}
272
+ if not self._pred(r.value):
273
+ return {'value': r.value, 'done': False}
274
+
275
+ def __next__(self):
276
+ r = self.next()
277
+ if r.done:
278
+ raise StopIteration()
279
+ return r.value
280
+
281
+
282
+ class groupby:
283
+ """groupby(iterable, key=None) -> (k, group_iter) pairs for consecutive equal keys."""
284
+
285
+ def __init__(self, iterable, key=None):
286
+ self._it = iter(iterable)
287
+ self._key = key
288
+ self._curr = {'value': undefined, 'done': False}
289
+ self._curr_key = undefined
290
+ self._initialized = False
291
+
292
+ def __iter__(self):
293
+ return self
294
+
295
+ def _get_key(self, val):
296
+ if self._key is not None:
297
+ return self._key(val)
298
+ return val
299
+
300
+ def _advance(self):
301
+ self._curr = self._it.next()
302
+ if not self._curr.done:
303
+ self._curr_key = self._get_key(self._curr.value)
304
+
305
+ def next(self):
306
+ if not self._initialized:
307
+ self._initialized = True
308
+ self._advance()
309
+ if self._curr.done:
310
+ return {'value': undefined, 'done': True}
311
+ group_key = self._curr_key
312
+ group_items = []
313
+ while not self._curr.done and self._curr_key == group_key:
314
+ group_items.push(self._curr.value)
315
+ self._advance()
316
+ return {'value': [group_key, iter(group_items)], 'done': False}
317
+
318
+ def __next__(self):
319
+ r = self.next()
320
+ if r.done:
321
+ raise StopIteration()
322
+ return r.value
323
+
324
+
325
+ class islice:
326
+ """islice(p, stop) or islice(p, start, stop[, step]) -> sliced iterator."""
327
+
328
+ def __init__(self, iterable, *args):
329
+ self._it = iter(iterable)
330
+ if len(args) == 1:
331
+ self._start = 0
332
+ self._stop = args[0]
333
+ self._step = 1
334
+ elif len(args) == 2:
335
+ self._start = args[0] if args[0] is not None else 0
336
+ self._stop = args[1]
337
+ self._step = 1
338
+ elif len(args) >= 3:
339
+ self._start = args[0] if args[0] is not None else 0
340
+ self._stop = args[1]
341
+ self._step = args[2] if args[2] is not None else 1
342
+ else:
343
+ raise TypeError('islice() requires at least 2 arguments')
344
+ if self._step < 1:
345
+ raise ValueError('Step for islice() must be a positive integer or None')
346
+ self._consumed = 0
347
+ self._next_pos = self._start
348
+
349
+ def __iter__(self):
350
+ return self
351
+
352
+ def next(self):
353
+ if self._stop is not None and self._next_pos >= self._stop:
354
+ return {'value': undefined, 'done': True}
355
+ # Advance underlying iterator to _next_pos
356
+ while self._consumed < self._next_pos:
357
+ r = self._it.next()
358
+ if r.done:
359
+ return {'value': undefined, 'done': True}
360
+ self._consumed += 1
361
+ # Get element at _next_pos
362
+ r = self._it.next()
363
+ if r.done:
364
+ return {'value': undefined, 'done': True}
365
+ self._consumed += 1
366
+ self._next_pos += self._step
367
+ return {'value': r.value, 'done': False}
368
+
369
+ def __next__(self):
370
+ r = self.next()
371
+ if r.done:
372
+ raise StopIteration()
373
+ return r.value
374
+
375
+
376
+ class pairwise:
377
+ """pairwise(iterable) -> (a,b), (b,c), (c,d), ..."""
378
+
379
+ def __init__(self, iterable):
380
+ self._it = iter(iterable)
381
+ self._prev = undefined
382
+ self._started = False
383
+
384
+ def __iter__(self):
385
+ return self
386
+
387
+ def next(self):
388
+ if not self._started:
389
+ r = self._it.next()
390
+ if r.done:
391
+ return {'value': undefined, 'done': True}
392
+ self._prev = r.value
393
+ self._started = True
394
+ r = self._it.next()
395
+ if r.done:
396
+ return {'value': undefined, 'done': True}
397
+ pair = [self._prev, r.value]
398
+ self._prev = r.value
399
+ return {'value': pair, 'done': False}
400
+
401
+ def __next__(self):
402
+ r = self.next()
403
+ if r.done:
404
+ raise StopIteration()
405
+ return r.value
406
+
407
+
408
+ class starmap:
409
+ """starmap(func, iterable) -> func(*it[0]), func(*it[1]), ..."""
410
+
411
+ def __init__(self, func, iterable):
412
+ self._func = func
413
+ self._it = iter(iterable)
414
+
415
+ def __iter__(self):
416
+ return self
417
+
418
+ def next(self):
419
+ r = self._it.next()
420
+ if r.done:
421
+ return {'value': undefined, 'done': True}
422
+ args = _to_array(r.value)
423
+ v"var _result = this._func.apply(undefined, args)"
424
+ return {'value': _result, 'done': False}
425
+
426
+ def __next__(self):
427
+ r = self.next()
428
+ if r.done:
429
+ raise StopIteration()
430
+ return r.value
431
+
432
+
433
+ class takewhile:
434
+ """takewhile(pred, seq) -> seq[0], seq[1], ... until pred fails."""
435
+
436
+ def __init__(self, predicate, iterable):
437
+ self._pred = predicate
438
+ self._it = iter(iterable)
439
+ self._done = False
440
+
441
+ def __iter__(self):
442
+ return self
443
+
444
+ def next(self):
445
+ if self._done:
446
+ return {'value': undefined, 'done': True}
447
+ r = self._it.next()
448
+ if r.done:
449
+ self._done = True
450
+ return {'value': undefined, 'done': True}
451
+ if self._pred(r.value):
452
+ return {'value': r.value, 'done': False}
453
+ self._done = True
454
+ return {'value': undefined, 'done': True}
455
+
456
+ def __next__(self):
457
+ r = self.next()
458
+ if r.done:
459
+ raise StopIteration()
460
+ return r.value
461
+
462
+
463
+ class zip_longest:
464
+ """zip_longest(*iterables, fillvalue=None) -> zip with fill for shorter iterables."""
465
+
466
+ def __init__(self, *iterables, **kwargs):
467
+ self._iters = [iter(it) for it in iterables]
468
+ self._fill = kwargs['fillvalue'] if kwargs and 'fillvalue' in kwargs else None
469
+ self._active = self._iters.length
470
+ self._exhausted = [False for _ in range(self._iters.length)]
471
+
472
+ def __iter__(self):
473
+ return self
474
+
475
+ def next(self):
476
+ if self._active == 0:
477
+ return {'value': undefined, 'done': True}
478
+ values = []
479
+ all_done = True
480
+ for i in range(self._iters.length):
481
+ if self._exhausted[i]:
482
+ values.push(self._fill)
483
+ else:
484
+ r = self._iters[i].next()
485
+ if r.done:
486
+ self._exhausted[i] = True
487
+ self._active -= 1
488
+ values.push(self._fill)
489
+ else:
490
+ all_done = False
491
+ values.push(r.value)
492
+ if all_done:
493
+ return {'value': undefined, 'done': True}
494
+ return {'value': values, 'done': False}
495
+
496
+ def __next__(self):
497
+ r = self.next()
498
+ if r.done:
499
+ raise StopIteration()
500
+ return r.value
501
+
502
+
503
+ # ── Combinatoric generators ─────────────────────────────────────────────────
504
+
505
+ def product(*iterables, **kwargs):
506
+ """product(*iterables, repeat=1) -> cartesian product of iterables."""
507
+ repeat_n = kwargs['repeat'] if kwargs and 'repeat' in kwargs else 1
508
+ pools = [_to_array(it) for it in iterables]
509
+ # Build a flat list of pools repeated repeat_n times
510
+ all_pools = []
511
+ for i in range(repeat_n):
512
+ for p in pools:
513
+ all_pools.push(p)
514
+ result = [[]]
515
+ for pool in all_pools:
516
+ new_result = []
517
+ for x in result:
518
+ for y in pool:
519
+ new_result.push(x.concat([y]))
520
+ result = new_result
521
+ return iter(result)
522
+
523
+
524
+ def permutations(iterable, r=None):
525
+ """permutations(p, r=None) -> r-length permutations of elements in p."""
526
+ pool = _to_array(iterable)
527
+ n = pool.length
528
+ if r is None:
529
+ r = n
530
+ if r > n or (n == 0 and r > 0):
531
+ return iter([])
532
+ result = []
533
+ def _helper(current, remaining):
534
+ if current.length == r:
535
+ result.push(current.slice())
536
+ return
537
+ for i in range(remaining.length):
538
+ current.push(remaining[i])
539
+ _helper(current, remaining.slice(0, i).concat(remaining.slice(i + 1)))
540
+ current.pop()
541
+ _helper([], pool.slice())
542
+ return iter(result)
543
+
544
+
545
+ def combinations(iterable, r):
546
+ """combinations(p, r) -> r-length subsequences of elements in p (no repeats)."""
547
+ pool = _to_array(iterable)
548
+ n = pool.length
549
+ if r > n:
550
+ return iter([])
551
+ result = []
552
+ def _helper(start, current):
553
+ if current.length == r:
554
+ result.push(current.slice())
555
+ return
556
+ for i in range(start, n):
557
+ current.push(pool[i])
558
+ _helper(i + 1, current)
559
+ current.pop()
560
+ _helper(0, [])
561
+ return iter(result)
562
+
563
+
564
+ def combinations_with_replacement(iterable, r):
565
+ """combinations_with_replacement(p, r) -> r-length subsequences allowing repeats."""
566
+ pool = _to_array(iterable)
567
+ n = pool.length
568
+ if n == 0 and r > 0:
569
+ return iter([])
570
+ result = []
571
+ def _helper(start, current):
572
+ if current.length == r:
573
+ result.push(current.slice())
574
+ return
575
+ for i in range(start, n):
576
+ current.push(pool[i])
577
+ _helper(i, current)
578
+ current.pop()
579
+ _helper(0, [])
580
+ return iter(result)