musa-dsl 0.14.16
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/Gemfile +20 -0
- data/LICENSE.md +157 -0
- data/README.md +8 -0
- data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
- data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
- data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
- data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
- data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
- data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
- data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
- data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
- data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
- data/lib/musa-dsl/core-ext.rb +13 -0
- data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
- data/lib/musa-dsl/datasets/gdv.rb +499 -0
- data/lib/musa-dsl/datasets/pdv.rb +44 -0
- data/lib/musa-dsl/datasets.rb +5 -0
- data/lib/musa-dsl/generative/darwin.rb +145 -0
- data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
- data/lib/musa-dsl/generative/markov.rb +78 -0
- data/lib/musa-dsl/generative/rules.rb +282 -0
- data/lib/musa-dsl/generative/variatio.rb +331 -0
- data/lib/musa-dsl/generative.rb +5 -0
- data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
- data/lib/musa-dsl/midi/midi-voices.rb +274 -0
- data/lib/musa-dsl/midi.rb +2 -0
- data/lib/musa-dsl/music/chord-definition.rb +99 -0
- data/lib/musa-dsl/music/chord-definitions.rb +13 -0
- data/lib/musa-dsl/music/chords.rb +326 -0
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
- data/lib/musa-dsl/music/scales.rb +584 -0
- data/lib/musa-dsl/music.rb +6 -0
- data/lib/musa-dsl/neuma/neuma.rb +181 -0
- data/lib/musa-dsl/neuma.rb +1 -0
- data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
- data/lib/musa-dsl/neumalang.rb +3 -0
- data/lib/musa-dsl/repl/repl.rb +143 -0
- data/lib/musa-dsl/repl.rb +1 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
- data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
- data/lib/musa-dsl/sequencer.rb +1 -0
- data/lib/musa-dsl/series/base-series.rb +245 -0
- data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
- data/lib/musa-dsl/series/holder-serie.rb +87 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
- data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
- data/lib/musa-dsl/series/proxy-serie.rb +69 -0
- data/lib/musa-dsl/series/queue-serie.rb +94 -0
- data/lib/musa-dsl/series/series.rb +8 -0
- data/lib/musa-dsl/series.rb +1 -0
- data/lib/musa-dsl/transport/clock.rb +36 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
- data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
- data/lib/musa-dsl/transport/timer-clock.rb +102 -0
- data/lib/musa-dsl/transport/timer.rb +40 -0
- data/lib/musa-dsl/transport/transport.rb +137 -0
- data/lib/musa-dsl/transport.rb +9 -0
- data/lib/musa-dsl.rb +17 -0
- data/musa-dsl.gemspec +17 -0
- metadata +174 -0
@@ -0,0 +1,1151 @@
|
|
1
|
+
module Musa
|
2
|
+
module SerieOperations
|
3
|
+
|
4
|
+
def autorestart
|
5
|
+
Autorestart.new self
|
6
|
+
end
|
7
|
+
|
8
|
+
def repeat(times = nil, condition: nil, &condition_block)
|
9
|
+
condition ||= condition_block
|
10
|
+
|
11
|
+
if times || condition
|
12
|
+
Repeater.new self, times, &condition
|
13
|
+
else
|
14
|
+
InfiniteRepeater.new self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def max_size(length)
|
19
|
+
LengthLimiter.new self, length
|
20
|
+
end
|
21
|
+
|
22
|
+
def skip(length)
|
23
|
+
Skipper.new self, length
|
24
|
+
end
|
25
|
+
|
26
|
+
def flatten
|
27
|
+
Flattener.new self
|
28
|
+
end
|
29
|
+
|
30
|
+
def process_with(**parameters, &processor)
|
31
|
+
Processor.new self, parameters, &processor
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO: test case
|
35
|
+
def hashify(*keys)
|
36
|
+
HashFromSeriesArray.new self, keys
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO: test case
|
40
|
+
def shift(shift)
|
41
|
+
Shifter.new self, shift
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO: test case
|
45
|
+
def lock
|
46
|
+
Locker.new self
|
47
|
+
end
|
48
|
+
|
49
|
+
# TODO: test case
|
50
|
+
def reverse
|
51
|
+
Reverser.new self
|
52
|
+
end
|
53
|
+
|
54
|
+
# TODO: test case
|
55
|
+
def randomize(random: nil)
|
56
|
+
random ||= Random.new
|
57
|
+
Randomizer.new self, random
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove(block = nil, &yield_block)
|
61
|
+
# TODO make history an optional block parameter (via keyparametersprocedurebinder)
|
62
|
+
block ||= yield_block
|
63
|
+
Remover.new self, &block
|
64
|
+
end
|
65
|
+
|
66
|
+
def select(block = nil, &yield_block)
|
67
|
+
# TODO add optional history (via keyparametersprocedurebinder)
|
68
|
+
block ||= yield_block
|
69
|
+
Selector.new self, &block
|
70
|
+
end
|
71
|
+
|
72
|
+
# TODO: test case
|
73
|
+
def switch(*indexed_series, **hash_series)
|
74
|
+
Switcher.new self, indexed_series, hash_series
|
75
|
+
end
|
76
|
+
|
77
|
+
def multiplex(*indexed_series, **hash_series)
|
78
|
+
MultiplexSelector.new self, indexed_series, hash_series
|
79
|
+
end
|
80
|
+
|
81
|
+
# TODO: test case
|
82
|
+
def switch_serie(*indexed_series, **hash_series)
|
83
|
+
SwitchFullSerie.new self, indexed_series, hash_series
|
84
|
+
end
|
85
|
+
|
86
|
+
def after(*series)
|
87
|
+
Sequence.new [self, *series]
|
88
|
+
end
|
89
|
+
|
90
|
+
def +(other)
|
91
|
+
Sequence.new [self, other]
|
92
|
+
end
|
93
|
+
|
94
|
+
def cut(length)
|
95
|
+
Cutter.new self, length
|
96
|
+
end
|
97
|
+
|
98
|
+
def merge
|
99
|
+
MergeSerieOfSeries.new self
|
100
|
+
end
|
101
|
+
|
102
|
+
def with(block = nil, on_restart: nil, **with_series, &yield_block)
|
103
|
+
block ||= yield_block
|
104
|
+
ProcessWith.new self, with_series, on_restart, &block
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :eval, :with
|
108
|
+
|
109
|
+
def map(&yield_block)
|
110
|
+
ProcessWith.new self, &yield_block
|
111
|
+
end
|
112
|
+
|
113
|
+
# TODO: test case
|
114
|
+
def slave
|
115
|
+
slave_serie = Slave.new self
|
116
|
+
|
117
|
+
@_slaves ||= []
|
118
|
+
@_slaves << slave_serie
|
119
|
+
|
120
|
+
slave_serie
|
121
|
+
end
|
122
|
+
|
123
|
+
###
|
124
|
+
### Implementation
|
125
|
+
###
|
126
|
+
|
127
|
+
class ProcessWith
|
128
|
+
include Serie
|
129
|
+
|
130
|
+
attr_reader :source, :with_sources, :on_restart, :block
|
131
|
+
|
132
|
+
def initialize(serie, with_series = nil, on_restart = nil, &block)
|
133
|
+
@source = serie
|
134
|
+
@with_sources = with_series || {}
|
135
|
+
@on_restart = on_restart
|
136
|
+
@block = KeyParametersProcedureBinder.new(block) if block_given?
|
137
|
+
|
138
|
+
if @source.prototype?
|
139
|
+
@with_sources = @with_sources.transform_values { |s| s.prototype }
|
140
|
+
else
|
141
|
+
@with_sources = @with_sources.transform_values { |s| s.instance }
|
142
|
+
end
|
143
|
+
|
144
|
+
mark_regarding! @source
|
145
|
+
end
|
146
|
+
|
147
|
+
def _prototype
|
148
|
+
@source = @source.prototype
|
149
|
+
@with_sources = @with_sources.transform_values { |s| s.prototype }
|
150
|
+
end
|
151
|
+
|
152
|
+
def _instance
|
153
|
+
@source = @source.instance
|
154
|
+
@with_sources = @with_sources.transform_values { |s| s.instance }
|
155
|
+
end
|
156
|
+
|
157
|
+
def _restart
|
158
|
+
@source.restart
|
159
|
+
@with_sources.values.each { |s| s.restart }
|
160
|
+
@on_restart.call if @on_restart
|
161
|
+
end
|
162
|
+
|
163
|
+
def _next_value
|
164
|
+
main = @source.next_value
|
165
|
+
others = @with_sources.transform_values { |v| v.next_value }
|
166
|
+
|
167
|
+
value = nil
|
168
|
+
|
169
|
+
if main && !others.values.include?(nil)
|
170
|
+
if @block
|
171
|
+
value = @block._call([main], others)
|
172
|
+
else
|
173
|
+
value = [main, others]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
value
|
178
|
+
end
|
179
|
+
|
180
|
+
def infinite?
|
181
|
+
@source.infinite? && !@with_sources.values.find { |s| !s.infinite? }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private_constant :ProcessWith
|
186
|
+
|
187
|
+
class Switcher
|
188
|
+
include Serie
|
189
|
+
|
190
|
+
attr_accessor :selector, :sources
|
191
|
+
|
192
|
+
def initialize(selector, indexed_series, hash_series)
|
193
|
+
|
194
|
+
@selector = selector
|
195
|
+
get = @selector.prototype? ? :prototype : :instance
|
196
|
+
|
197
|
+
if indexed_series && !indexed_series.empty?
|
198
|
+
@sources = indexed_series.collect(&get)
|
199
|
+
elsif hash_series && !hash_series.empty?
|
200
|
+
@sources = hash_series.clone.transform_values(&get)
|
201
|
+
end
|
202
|
+
|
203
|
+
if get == :_prototype
|
204
|
+
@sources.freeze
|
205
|
+
end
|
206
|
+
|
207
|
+
mark_regarding! @selector
|
208
|
+
end
|
209
|
+
|
210
|
+
def _prototype
|
211
|
+
@selector = @selector.prototype
|
212
|
+
@sources = @sources.collect(&:prototype).freeze if @sources.is_a? Array
|
213
|
+
@sources.transform_values(&:prototype).freeze if @sources.is_a? Hash
|
214
|
+
end
|
215
|
+
|
216
|
+
def _instance
|
217
|
+
@selector = @selector.instance
|
218
|
+
@sources = @sources.collect(&:instance) if @sources.is_a? Array
|
219
|
+
@sources.transform_values(&:_instance) if @sources.is_a? Hash
|
220
|
+
end
|
221
|
+
|
222
|
+
def _restart
|
223
|
+
@selector.restart
|
224
|
+
@sources.each(&:restart) if @sources.is_a? Array
|
225
|
+
@sources.each { |_key, serie| serie.restart } if @sources.is_a? Hash
|
226
|
+
end
|
227
|
+
|
228
|
+
def _next_value
|
229
|
+
value = nil
|
230
|
+
|
231
|
+
index_or_key = @selector.next_value
|
232
|
+
|
233
|
+
value = @sources[index_or_key].next_value unless index_or_key.nil?
|
234
|
+
|
235
|
+
value
|
236
|
+
end
|
237
|
+
|
238
|
+
def infinite?
|
239
|
+
@selector.infinite? && @sources.any? { |serie| serie.infinite? }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
private_constant :Switcher
|
244
|
+
|
245
|
+
class MultiplexSelector
|
246
|
+
include Serie
|
247
|
+
|
248
|
+
attr_accessor :selector, :sources
|
249
|
+
|
250
|
+
def initialize(selector, indexed_series, hash_series)
|
251
|
+
@selector = selector
|
252
|
+
get = @selector.prototype? ? :prototype : :instance
|
253
|
+
|
254
|
+
if indexed_series && !indexed_series.empty?
|
255
|
+
@sources = indexed_series.collect(&get)
|
256
|
+
elsif hash_series && !hash_series.empty?
|
257
|
+
@sources = hash_series.clone.transform_values(&get)
|
258
|
+
end
|
259
|
+
|
260
|
+
_restart false
|
261
|
+
|
262
|
+
if get == :_prototype
|
263
|
+
@sources.freeze
|
264
|
+
end
|
265
|
+
|
266
|
+
mark_regarding! @selector
|
267
|
+
end
|
268
|
+
|
269
|
+
def _prototype
|
270
|
+
@selector = @selector.prototype
|
271
|
+
@sources = @sources.collect(&:prototype).freeze if @sources.is_a? Array
|
272
|
+
@sources.transform_values(&:prototype).freeze if @sources.is_a? Hash
|
273
|
+
end
|
274
|
+
|
275
|
+
def _instance
|
276
|
+
@selector = @selector.instance
|
277
|
+
@sources = @sources.collect(&:instance) if @sources.is_a? Array
|
278
|
+
@sources.transform_values(&:_instance) if @sources.is_a? Hash
|
279
|
+
end
|
280
|
+
|
281
|
+
def _restart(restart_sources = true)
|
282
|
+
@current_value = nil
|
283
|
+
|
284
|
+
if restart_sources
|
285
|
+
@selector.restart
|
286
|
+
@sources.each(&:restart) if @sources.is_a? Array
|
287
|
+
@sources.each { |_key, serie| serie.restart } if @sources.is_a? Hash
|
288
|
+
end
|
289
|
+
|
290
|
+
@first = true
|
291
|
+
end
|
292
|
+
|
293
|
+
def _next_value
|
294
|
+
@current_value =
|
295
|
+
if @first || !@current_value.nil?
|
296
|
+
@first = false
|
297
|
+
index_or_key = @selector.next_value
|
298
|
+
unless index_or_key.nil?
|
299
|
+
@sources.each(&:next_value)
|
300
|
+
@sources[index_or_key].current_value
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def infinite?
|
306
|
+
@selector.infinite? && @sources.any? { |serie| serie.infinite? }
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
private_constant :MultiplexSelector
|
311
|
+
|
312
|
+
class SwitchFullSerie
|
313
|
+
include Serie
|
314
|
+
|
315
|
+
attr_accessor :selector, :sources
|
316
|
+
|
317
|
+
def initialize(selector, indexed_series, hash_series)
|
318
|
+
@selector = selector
|
319
|
+
get = @selector.prototype? ? :prototype : :instance
|
320
|
+
|
321
|
+
if indexed_series && !indexed_series.empty?
|
322
|
+
@sources = indexed_series.collect(&get)
|
323
|
+
elsif hash_series && !hash_series.empty?
|
324
|
+
@sources = hash_series.clone.transform_values(&get)
|
325
|
+
end
|
326
|
+
|
327
|
+
if get == :_prototype
|
328
|
+
@sources.freeze
|
329
|
+
end
|
330
|
+
|
331
|
+
mark_regarding! @selector
|
332
|
+
end
|
333
|
+
|
334
|
+
def _prototype
|
335
|
+
@selector = @selector.prototype
|
336
|
+
@sources = @sources.collect(&:prototype).freeze if @sources.is_a? Array
|
337
|
+
@sources.transform_values(&:prototype).freeze if @sources.is_a? Hash
|
338
|
+
end
|
339
|
+
|
340
|
+
def _instance
|
341
|
+
@selector = @selector.instance
|
342
|
+
@sources = @sources.collect(&:instance) if @sources.is_a? Array
|
343
|
+
@sources.transform_values(&:_instance) if @sources.is_a? Hash
|
344
|
+
end
|
345
|
+
|
346
|
+
def _restart
|
347
|
+
@selector.restart
|
348
|
+
@sources.each(&:restart)
|
349
|
+
end
|
350
|
+
|
351
|
+
def _next_value
|
352
|
+
value = nil
|
353
|
+
|
354
|
+
value = @sources[@index_or_key].next_value unless @index_or_key.nil?
|
355
|
+
|
356
|
+
if value.nil?
|
357
|
+
@index_or_key = @selector.next_value
|
358
|
+
|
359
|
+
value = next_value unless @index_or_key.nil?
|
360
|
+
end
|
361
|
+
|
362
|
+
value
|
363
|
+
end
|
364
|
+
|
365
|
+
def infinite?
|
366
|
+
!!(@selector.infinite? || @sources.find(&:infinite?))
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
private_constant :SwitchFullSerie
|
371
|
+
|
372
|
+
class InfiniteRepeater
|
373
|
+
include Serie
|
374
|
+
|
375
|
+
attr_reader :source
|
376
|
+
|
377
|
+
def initialize(serie)
|
378
|
+
@source = serie
|
379
|
+
|
380
|
+
mark_regarding! @source
|
381
|
+
end
|
382
|
+
|
383
|
+
def _prototype
|
384
|
+
@source = @source.prototype
|
385
|
+
end
|
386
|
+
|
387
|
+
def _instance
|
388
|
+
@source = @source.instance
|
389
|
+
end
|
390
|
+
|
391
|
+
def _restart
|
392
|
+
@source.restart
|
393
|
+
end
|
394
|
+
|
395
|
+
def _next_value
|
396
|
+
value = @source.next_value
|
397
|
+
|
398
|
+
if value.nil?
|
399
|
+
@source.restart
|
400
|
+
value = @source.next_value
|
401
|
+
end
|
402
|
+
|
403
|
+
value
|
404
|
+
end
|
405
|
+
|
406
|
+
def infinite?
|
407
|
+
true
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
private_constant :InfiniteRepeater
|
412
|
+
|
413
|
+
class Repeater
|
414
|
+
include Serie
|
415
|
+
|
416
|
+
attr_reader :source, :times, :condition
|
417
|
+
|
418
|
+
def initialize(serie, times = nil, &condition_block)
|
419
|
+
@source = serie
|
420
|
+
|
421
|
+
@times = times
|
422
|
+
@condition = condition_block
|
423
|
+
|
424
|
+
update_condition
|
425
|
+
_restart false
|
426
|
+
|
427
|
+
mark_regarding! @source
|
428
|
+
end
|
429
|
+
|
430
|
+
def _prototype
|
431
|
+
@source = @source.prototype
|
432
|
+
end
|
433
|
+
|
434
|
+
def _instance
|
435
|
+
@source = @source.instance
|
436
|
+
end
|
437
|
+
|
438
|
+
def _restart(restart_sources = true)
|
439
|
+
@count = 0
|
440
|
+
@source.restart if restart_sources
|
441
|
+
end
|
442
|
+
|
443
|
+
def _next_value
|
444
|
+
value = @source.next_value
|
445
|
+
|
446
|
+
if value.nil?
|
447
|
+
@count += 1
|
448
|
+
|
449
|
+
if instance_eval &@condition
|
450
|
+
@source.restart
|
451
|
+
value = @source.next_value
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
value
|
456
|
+
end
|
457
|
+
|
458
|
+
def infinite?
|
459
|
+
@source.infinite?
|
460
|
+
end
|
461
|
+
|
462
|
+
private
|
463
|
+
|
464
|
+
def update_condition
|
465
|
+
@condition = proc { @count < @times } if @times && !@condition
|
466
|
+
@condition ||= proc { false }
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
private_constant :Repeater
|
471
|
+
|
472
|
+
class LengthLimiter
|
473
|
+
include Serie
|
474
|
+
|
475
|
+
attr_reader :source, :length
|
476
|
+
|
477
|
+
def initialize(serie, length)
|
478
|
+
@source = serie
|
479
|
+
@length = length
|
480
|
+
|
481
|
+
_restart false
|
482
|
+
|
483
|
+
mark_regarding! @source
|
484
|
+
end
|
485
|
+
|
486
|
+
def _prototype
|
487
|
+
@source = @source.prototype
|
488
|
+
end
|
489
|
+
|
490
|
+
def _instance
|
491
|
+
@source = @source.instance
|
492
|
+
end
|
493
|
+
|
494
|
+
def _restart(restart_sources = true)
|
495
|
+
@position = 0
|
496
|
+
@source.restart if restart_sources
|
497
|
+
end
|
498
|
+
|
499
|
+
def _next_value
|
500
|
+
if @position < @length
|
501
|
+
@position += 1
|
502
|
+
@source.next_value
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
def infinite?
|
507
|
+
false
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
private_constant :LengthLimiter
|
512
|
+
|
513
|
+
class Skipper
|
514
|
+
include Serie
|
515
|
+
|
516
|
+
attr_reader :source, :length
|
517
|
+
|
518
|
+
def initialize(serie, length)
|
519
|
+
@source = serie
|
520
|
+
@length = length
|
521
|
+
|
522
|
+
_restart false
|
523
|
+
|
524
|
+
mark_regarding! @source
|
525
|
+
end
|
526
|
+
|
527
|
+
def _prototype
|
528
|
+
@source = @source.prototype
|
529
|
+
end
|
530
|
+
|
531
|
+
def _instance
|
532
|
+
@source = @source.instance
|
533
|
+
end
|
534
|
+
|
535
|
+
def _restart(restart_sources = true)
|
536
|
+
@source.restart if restart_sources
|
537
|
+
@first = true
|
538
|
+
end
|
539
|
+
|
540
|
+
def _next_value
|
541
|
+
@length.times { @source.next_value } if @first
|
542
|
+
@first = nil
|
543
|
+
|
544
|
+
@source.next_value
|
545
|
+
end
|
546
|
+
|
547
|
+
def infinite?
|
548
|
+
@source.infinite?
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
private_constant :Skipper
|
553
|
+
|
554
|
+
class Flattener
|
555
|
+
include Serie
|
556
|
+
|
557
|
+
attr_reader :source
|
558
|
+
|
559
|
+
def initialize(serie)
|
560
|
+
@source = serie
|
561
|
+
|
562
|
+
_restart false
|
563
|
+
|
564
|
+
mark_regarding! @source
|
565
|
+
end
|
566
|
+
|
567
|
+
def _prototype
|
568
|
+
@source = @source.prototype
|
569
|
+
_restart false
|
570
|
+
end
|
571
|
+
|
572
|
+
def _instance
|
573
|
+
@source = @source.instance
|
574
|
+
_restart false
|
575
|
+
end
|
576
|
+
|
577
|
+
def _restart(restart_sources = true)
|
578
|
+
if restart_sources
|
579
|
+
@source.restart
|
580
|
+
@restart_each_serie = true
|
581
|
+
else
|
582
|
+
@restart_each_serie = false
|
583
|
+
end
|
584
|
+
|
585
|
+
@stack = [@source]
|
586
|
+
end
|
587
|
+
|
588
|
+
def _next_value
|
589
|
+
if @stack.last
|
590
|
+
value = @stack.last.next_value
|
591
|
+
|
592
|
+
case value
|
593
|
+
when Serie
|
594
|
+
value = value.instance
|
595
|
+
value.restart if @restart_each_serie
|
596
|
+
@stack.push(value)
|
597
|
+
_next_value
|
598
|
+
when nil
|
599
|
+
@stack.pop
|
600
|
+
_next_value
|
601
|
+
else
|
602
|
+
value
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
def infinite?
|
608
|
+
@source.infinite? # TODO revisar porque las series hijas sí que pueden ser infinitas
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
private_constant :Flattener
|
613
|
+
|
614
|
+
class MergeSerieOfSeries
|
615
|
+
include Serie
|
616
|
+
|
617
|
+
attr_reader :source
|
618
|
+
|
619
|
+
def initialize(serie)
|
620
|
+
@source = serie
|
621
|
+
_restart false
|
622
|
+
|
623
|
+
mark_regarding! @source
|
624
|
+
end
|
625
|
+
|
626
|
+
def _prototype
|
627
|
+
@source = @source.prototype
|
628
|
+
end
|
629
|
+
|
630
|
+
def _instance
|
631
|
+
@source = @source.instance
|
632
|
+
end
|
633
|
+
|
634
|
+
def _restart(restart_sources = true)
|
635
|
+
if restart_sources
|
636
|
+
@source.restart
|
637
|
+
@restart_each_serie = true
|
638
|
+
end
|
639
|
+
@current_serie = nil
|
640
|
+
end
|
641
|
+
|
642
|
+
def _next_value
|
643
|
+
value = nil
|
644
|
+
|
645
|
+
restart_current_serie_if_needed = false
|
646
|
+
|
647
|
+
if @current_serie.nil?
|
648
|
+
@current_serie = @source.next_value
|
649
|
+
@current_serie = @current_serie.instance if @current_serie
|
650
|
+
|
651
|
+
if @restart_each_serie
|
652
|
+
@current_serie.restart if @current_serie
|
653
|
+
else
|
654
|
+
restart_current_serie_if_needed = true
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
if @current_serie
|
659
|
+
value = @current_serie.next_value
|
660
|
+
|
661
|
+
if value.nil?
|
662
|
+
if restart_current_serie_if_needed
|
663
|
+
@current_serie.restart
|
664
|
+
else
|
665
|
+
@current_serie = nil
|
666
|
+
end
|
667
|
+
|
668
|
+
value = _next_value
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
value
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
private_constant :MergeSerieOfSeries
|
677
|
+
|
678
|
+
class Processor
|
679
|
+
include Serie
|
680
|
+
|
681
|
+
attr_reader :source
|
682
|
+
|
683
|
+
def initialize(serie, parameters, &processor)
|
684
|
+
@source = serie
|
685
|
+
@parameters = parameters
|
686
|
+
@processor = KeyParametersProcedureBinder.new(processor)
|
687
|
+
|
688
|
+
_restart false
|
689
|
+
|
690
|
+
mark_regarding! @source
|
691
|
+
end
|
692
|
+
|
693
|
+
def _prototype
|
694
|
+
@source = @source.prototype
|
695
|
+
end
|
696
|
+
|
697
|
+
def _instance
|
698
|
+
@source = @source.instance
|
699
|
+
end
|
700
|
+
|
701
|
+
def _restart(restart_source = true)
|
702
|
+
@source.restart if restart_source
|
703
|
+
@pending_values = []
|
704
|
+
end
|
705
|
+
|
706
|
+
def _next_value
|
707
|
+
if @pending_values.empty?
|
708
|
+
|
709
|
+
v = @source.next_value
|
710
|
+
|
711
|
+
if v.nil?
|
712
|
+
nil
|
713
|
+
else
|
714
|
+
value = @processor.call(v, **@parameters)
|
715
|
+
|
716
|
+
if value.is_a?(Array)
|
717
|
+
@pending_values = value
|
718
|
+
value = _next_value
|
719
|
+
end
|
720
|
+
|
721
|
+
value
|
722
|
+
end
|
723
|
+
else
|
724
|
+
value = @pending_values.shift
|
725
|
+
|
726
|
+
if value.nil?
|
727
|
+
value = _next_value
|
728
|
+
end
|
729
|
+
|
730
|
+
value
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
def infinite?
|
735
|
+
@source.infinite?
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
class Autorestart
|
740
|
+
include Serie
|
741
|
+
|
742
|
+
attr_reader :source
|
743
|
+
|
744
|
+
def initialize(serie)
|
745
|
+
@source = serie
|
746
|
+
|
747
|
+
@restart_on_next = false
|
748
|
+
|
749
|
+
mark_regarding! @source
|
750
|
+
end
|
751
|
+
|
752
|
+
def _prototype
|
753
|
+
@source = @source.prototype
|
754
|
+
end
|
755
|
+
|
756
|
+
def _instance
|
757
|
+
@source = @source.instance
|
758
|
+
end
|
759
|
+
|
760
|
+
def _restart
|
761
|
+
@source.restart
|
762
|
+
end
|
763
|
+
|
764
|
+
def _next_value
|
765
|
+
if @restart_on_next
|
766
|
+
@source.restart
|
767
|
+
@restart_on_next = false
|
768
|
+
end
|
769
|
+
|
770
|
+
value = @source.next_value
|
771
|
+
|
772
|
+
@restart_on_next = value.nil?
|
773
|
+
|
774
|
+
value
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
private_constant :Autorestart
|
779
|
+
|
780
|
+
class Cutter
|
781
|
+
include Serie
|
782
|
+
|
783
|
+
attr_reader :source, :length
|
784
|
+
|
785
|
+
def initialize(serie, length)
|
786
|
+
@source = serie
|
787
|
+
@length = length
|
788
|
+
|
789
|
+
mark_regarding! @source
|
790
|
+
end
|
791
|
+
|
792
|
+
def _prototype
|
793
|
+
@source = @source.prototype
|
794
|
+
end
|
795
|
+
|
796
|
+
def _instance
|
797
|
+
@source = @source.instance
|
798
|
+
end
|
799
|
+
|
800
|
+
def _restart
|
801
|
+
@source.restart
|
802
|
+
end
|
803
|
+
|
804
|
+
def _next_value
|
805
|
+
@previous.materialize if @previous
|
806
|
+
|
807
|
+
@previous = CutSerie.new @source, @length if @source.peek_next_value
|
808
|
+
end
|
809
|
+
|
810
|
+
private
|
811
|
+
|
812
|
+
class CutSerie
|
813
|
+
include Serie
|
814
|
+
|
815
|
+
def initialize(serie, length)
|
816
|
+
@source = serie
|
817
|
+
@length = length
|
818
|
+
|
819
|
+
@values = []
|
820
|
+
_restart
|
821
|
+
|
822
|
+
mark_as_instance!
|
823
|
+
end
|
824
|
+
|
825
|
+
def _prototype
|
826
|
+
raise PrototypingSerieError, 'Cannot get prototype of a cut serie'
|
827
|
+
end
|
828
|
+
|
829
|
+
def _restart
|
830
|
+
@count = 0
|
831
|
+
end
|
832
|
+
|
833
|
+
def _next_value
|
834
|
+
value ||= @values[@count]
|
835
|
+
value ||= @values[@count] = @source.next_value if @count < @length
|
836
|
+
|
837
|
+
@count += 1
|
838
|
+
|
839
|
+
value
|
840
|
+
end
|
841
|
+
|
842
|
+
def materialize
|
843
|
+
(@values.size..@length - 1).each { |i| @values[i] = @source.next_value }
|
844
|
+
end
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
private_constant :Cutter
|
849
|
+
|
850
|
+
class Locker
|
851
|
+
include Serie
|
852
|
+
|
853
|
+
attr_reader :source
|
854
|
+
|
855
|
+
def initialize(serie)
|
856
|
+
@source = serie
|
857
|
+
@values = []
|
858
|
+
@first_round = true
|
859
|
+
|
860
|
+
_restart
|
861
|
+
|
862
|
+
mark_regarding! @source
|
863
|
+
end
|
864
|
+
|
865
|
+
def _prototype
|
866
|
+
@source = @source.prototype
|
867
|
+
end
|
868
|
+
|
869
|
+
def _instance
|
870
|
+
@source = @source.instance
|
871
|
+
end
|
872
|
+
|
873
|
+
def _restart
|
874
|
+
@index = 0
|
875
|
+
end
|
876
|
+
|
877
|
+
def _next_value
|
878
|
+
if @first_round
|
879
|
+
value = @source.next_value
|
880
|
+
|
881
|
+
@first_round = false if value.nil?
|
882
|
+
@values << value unless value.nil?
|
883
|
+
else
|
884
|
+
if @index < @values.size
|
885
|
+
value = @values[@index]
|
886
|
+
@index += 1
|
887
|
+
else
|
888
|
+
value = nil
|
889
|
+
end
|
890
|
+
end
|
891
|
+
|
892
|
+
value
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
private_constant :Locker
|
897
|
+
|
898
|
+
class Reverser
|
899
|
+
include Serie
|
900
|
+
|
901
|
+
attr_reader :source
|
902
|
+
|
903
|
+
def initialize(serie)
|
904
|
+
@source = serie
|
905
|
+
_restart false, false
|
906
|
+
|
907
|
+
mark_regarding! @source
|
908
|
+
end
|
909
|
+
|
910
|
+
def _prototype
|
911
|
+
@source = @source.prototype
|
912
|
+
end
|
913
|
+
|
914
|
+
def _instance
|
915
|
+
@source = @source.instance
|
916
|
+
_restart false, true
|
917
|
+
end
|
918
|
+
|
919
|
+
def _restart(restart_sources = true, get_reversed = true)
|
920
|
+
@source.restart if restart_sources
|
921
|
+
@reversed = FromArray.new(next_values_array_of(@source).reverse).instance if get_reversed
|
922
|
+
end
|
923
|
+
|
924
|
+
def _next_value
|
925
|
+
@reversed.next_value
|
926
|
+
end
|
927
|
+
|
928
|
+
private
|
929
|
+
|
930
|
+
def next_values_array_of(serie)
|
931
|
+
array = []
|
932
|
+
|
933
|
+
until (value = serie.next_value).nil?
|
934
|
+
array << value
|
935
|
+
end
|
936
|
+
|
937
|
+
array
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
private_constant :Reverser
|
942
|
+
|
943
|
+
class Randomizer
|
944
|
+
include Serie
|
945
|
+
|
946
|
+
attr_reader :source, :random
|
947
|
+
|
948
|
+
def initialize(serie, random)
|
949
|
+
@source = serie
|
950
|
+
@random = random
|
951
|
+
|
952
|
+
_restart false
|
953
|
+
|
954
|
+
mark_regarding! @source
|
955
|
+
end
|
956
|
+
|
957
|
+
def _prototype
|
958
|
+
@source = @source.prototype
|
959
|
+
end
|
960
|
+
|
961
|
+
def _instance
|
962
|
+
@source = @source.instance
|
963
|
+
end
|
964
|
+
|
965
|
+
def _restart(restart_sources = true)
|
966
|
+
@source.restart if restart_sources
|
967
|
+
@values = @source.to_a
|
968
|
+
end
|
969
|
+
|
970
|
+
def _next_value
|
971
|
+
_restart(false) if @needs_restart
|
972
|
+
|
973
|
+
if !@values.empty?
|
974
|
+
position = @random.rand(0...@values.size)
|
975
|
+
value = @values[position]
|
976
|
+
|
977
|
+
@values.delete_at position
|
978
|
+
else
|
979
|
+
value = nil
|
980
|
+
end
|
981
|
+
|
982
|
+
value
|
983
|
+
end
|
984
|
+
end
|
985
|
+
|
986
|
+
private_constant :Randomizer
|
987
|
+
|
988
|
+
class Shifter
|
989
|
+
include Serie
|
990
|
+
|
991
|
+
attr_reader :source, :shift
|
992
|
+
|
993
|
+
def initialize(serie, shift)
|
994
|
+
raise ArgumentError, "cannot shift to right an infinite serie #{serie}" if shift > 0 && serie.infinite?
|
995
|
+
raise ArgumentError, 'cannot shift to right: function not yet implemented' if shift > 0
|
996
|
+
|
997
|
+
@source = serie
|
998
|
+
@shift = shift
|
999
|
+
|
1000
|
+
_restart false
|
1001
|
+
|
1002
|
+
mark_regarding! @source
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
def _prototype
|
1006
|
+
@source = @source.prototype
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
def _instance
|
1010
|
+
@source = @source.instance
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def _restart(restart_sources = true)
|
1014
|
+
@source.restart if restart_sources
|
1015
|
+
|
1016
|
+
@shifted = []
|
1017
|
+
@shift.abs.times { @shifted << @source.next_value } if @shift < 0
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
def _next_value
|
1021
|
+
value = @source.next_value
|
1022
|
+
return value unless value.nil?
|
1023
|
+
|
1024
|
+
@shifted.shift
|
1025
|
+
end
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
private_constant :Shifter
|
1029
|
+
|
1030
|
+
class Remover
|
1031
|
+
include Serie
|
1032
|
+
|
1033
|
+
attr_reader :source
|
1034
|
+
|
1035
|
+
def initialize(serie, &block)
|
1036
|
+
@source = serie
|
1037
|
+
@block = block
|
1038
|
+
@history = []
|
1039
|
+
|
1040
|
+
_restart false
|
1041
|
+
|
1042
|
+
mark_regarding! @source
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def _prototype
|
1046
|
+
@source = @source.prototype
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
def _instance
|
1050
|
+
@source = @source.instance
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
def _restart(restart_sources = true)
|
1054
|
+
@source.restart if restart_sources
|
1055
|
+
@history.clear
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
def _next_value
|
1059
|
+
if value = @source.next_value
|
1060
|
+
while @block.call(value, @history)
|
1061
|
+
@history << value
|
1062
|
+
value = @source.next_value
|
1063
|
+
end
|
1064
|
+
@history << value
|
1065
|
+
end
|
1066
|
+
value
|
1067
|
+
end
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
private_constant :Remover
|
1071
|
+
|
1072
|
+
class Selector
|
1073
|
+
include Serie
|
1074
|
+
|
1075
|
+
attr_reader :source
|
1076
|
+
|
1077
|
+
def initialize(serie, &block)
|
1078
|
+
@source = serie
|
1079
|
+
@block = block
|
1080
|
+
|
1081
|
+
_restart false
|
1082
|
+
|
1083
|
+
mark_regarding! @source
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def _prototype
|
1087
|
+
@source = @source.prototype
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
def _instance
|
1091
|
+
@source = @source.instance
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
def _restart(restart_sources = true)
|
1095
|
+
@source.restart if restart_sources
|
1096
|
+
end
|
1097
|
+
|
1098
|
+
def _next_value
|
1099
|
+
value = @source.next_value
|
1100
|
+
until value.nil? || @block.call(value)
|
1101
|
+
value = @source.next_value
|
1102
|
+
end
|
1103
|
+
value
|
1104
|
+
end
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
private_constant :Selector
|
1108
|
+
|
1109
|
+
class HashFromSeriesArray
|
1110
|
+
include Serie
|
1111
|
+
|
1112
|
+
attr_reader :source, :keys
|
1113
|
+
|
1114
|
+
def initialize(serie, keys)
|
1115
|
+
@source = serie
|
1116
|
+
@keys = keys
|
1117
|
+
_restart false
|
1118
|
+
|
1119
|
+
mark_regarding! @source
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
def _prototype
|
1123
|
+
@source = @source.prototype
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
def _instance
|
1127
|
+
@source = @source.instance
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
def _restart(restart_sources = true)
|
1131
|
+
@source.restart if restart_sources
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
def _next_value
|
1135
|
+
array = @source.next_value
|
1136
|
+
|
1137
|
+
return nil unless array
|
1138
|
+
|
1139
|
+
value = array.length.times.collect { |i| [@keys[i], array[i]] }.to_h
|
1140
|
+
|
1141
|
+
if value.find { |_key, value| value.nil? }
|
1142
|
+
nil
|
1143
|
+
else
|
1144
|
+
value
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
private_constant :HashFromSeriesArray
|
1150
|
+
end
|
1151
|
+
end
|