musa-dsl 0.23.3 → 0.23.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7ac7a74db8d0006786f871ba33f6d417704910b11eaab5a568fff617962ad52
4
- data.tar.gz: 771ea64584e00fe078f4959537472032ae8438e4cb38b9a7cf1f6798a92a91de
3
+ metadata.gz: aedf1b2e55be310702169b869ff68a41c79d0d787002b21918c096ad18373dcf
4
+ data.tar.gz: 4bc6bd9694bffe3c97040e2d33e4a451accdeb5e621346c030fc699c2325ba5d
5
5
  SHA512:
6
- metadata.gz: 9dd7592546589149d420e6681befca0acea4afde5d07676bb1bfa1f01ec9ff0ce541673618fbd5cd16e549d69034698c682e9a5a8eec61547cbc5be6f8e6c5bf
7
- data.tar.gz: 5e4d56c555bc66cf5574a73d58c1c4f17027e4b6256d1b2f866337cefb8f776b8b6ce3987ad586c5171da4e69308a8d957e98b83d1f2387ccff3211e6eaf152a
6
+ metadata.gz: 30173d87a84a7d4288ddd00f5b212a9178f6f1836f673972f4c29c6528d57231588c4e9152ce06ba24319e834aac087a25f793ca8bf862d83d8bfae898c7d620
7
+ data.tar.gz: de0f34c68858de9629d2e65f9c0d794c2bb122855716476130b35f921297b731facd1b039c339235ec7168bedafa1652611722cc9ac684e3f66748b5275fa101
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ ruby '2.7.3'
4
+
3
5
  gem 'logger', '~> 1.4', '>= 1.4.3'
4
6
 
5
7
  group :neuma do
@@ -9,7 +9,6 @@ module Musa
9
9
  include Musa::Extension::SmartProcBinder
10
10
  include Musa::Series::Serie.base
11
11
 
12
-
13
12
  def initialize(transitions:, start:, finish: nil, random: nil)
14
13
  @transitions = transitions.clone.freeze
15
14
 
@@ -21,6 +20,7 @@ module Musa
21
20
 
22
21
  @procedure_binders = {}
23
22
 
23
+ mark_as_prototype!
24
24
  init
25
25
  end
26
26
 
@@ -12,24 +12,36 @@ module Musa
12
12
 
13
13
  module Serie
14
14
  def self.base
15
- SerieImplementation
15
+ Module.new do
16
+ include SerieImplementation
17
+
18
+ def has_source; false; end
19
+ private def mandatory_source; false; end
20
+
21
+ def has_sources; false; end
22
+ private def mandatory_sources; false; end
23
+ end
16
24
  end
17
25
 
18
26
  def self.with(source: false,
19
27
  source_as: nil,
20
28
  private_source: nil,
29
+ mandatory_source: nil,
21
30
  sources: false,
22
31
  sources_as: nil,
23
32
  private_sources: nil,
33
+ mandatory_sources: nil,
24
34
  smart_block: false,
25
35
  block: false,
26
36
  block_as: nil)
27
37
 
28
38
  source_as ||= :source
29
39
  source_setter = (source_as.to_s + '=').to_sym
40
+ _mandatory_source = source if mandatory_source.nil?
30
41
 
31
42
  sources_as ||= :sources
32
43
  sources_setter = (sources_as.to_s + '=').to_sym
44
+ _mandatory_sources = sources if mandatory_sources.nil?
33
45
 
34
46
  block_as ||= :proc
35
47
  block_setter = (block_as.to_s + '=').to_sym
@@ -38,15 +50,19 @@ module Musa
38
50
  include SerieImplementation
39
51
 
40
52
  if source
53
+ private def has_source; true; end
54
+ define_method(:mandatory_source) { _mandatory_source }
55
+ private :mandatory_source
56
+
41
57
  define_method source_as do
42
58
  @source
43
59
  end
44
60
 
45
61
  define_method source_setter do |serie|
46
- raise ArgumentError, "New #{source_as} should be a #{@get}" unless @source.nil? || @source.prototype? == serie&.prototype?
62
+ unless @source.nil? || @source.undefined? || serie.state == @source.state
63
+ raise ArgumentError, "New serie for #{source_as} should be a #{@state} instead of a #{serie.state}"
64
+ end
47
65
 
48
- serie ||= Musa::Series::Constructors.NIL
49
- @get = serie&.instance? ? :instance : :prototype
50
66
  @source = serie
51
67
  mark_regarding! @source
52
68
  end
@@ -55,45 +71,49 @@ module Musa
55
71
  private source_as
56
72
  private source_setter
57
73
  end
74
+ else
75
+ private def has_source; false; end
76
+ private def mandatory_source; false; end
58
77
  end
59
78
 
60
79
  if sources
61
- define_method sources_as do ||
80
+ private def has_sources; true; end
81
+ define_method(:mandatory_sources) { _mandatory_sources }
82
+ private :mandatory_source
83
+
84
+ define_method sources_as do
62
85
  @sources
63
86
  end
64
87
 
65
88
  define_method sources_setter do |series|
66
- case series
67
- when Array
68
- getter = @get || ((series.first)&.instance? ? :instance : :prototype)
69
- @sources = series.collect(&getter)
70
- when Hash
71
- getter = @get || ((series.values.first)&.instance? ? :instance : :prototype)
72
- @sources = series.transform_values(&getter)
73
- else
74
- raise ArgumentError, "Only allowed Array or Hash"
89
+ unless series.is_a?(Hash) || series.is_a?(Array)
90
+ raise ArgumentError, "New series for #{sources_as} should be a Hash or an Array instead of a #{series.class.name}"
75
91
  end
76
92
 
77
- mark_as! getter
93
+ @sources = series
94
+ try_to_resolve_undefined_state_if_needed
78
95
  end
79
96
 
80
97
  if private_sources
81
98
  private sources_as
82
99
  private sources_setter
83
100
  end
101
+ else
102
+ private def has_sources; false; end
103
+ private def mandatory_sources; false; end
84
104
  end
85
105
 
86
106
  if smart_block
87
107
  define_method block_as do |&block|
88
108
  if block
89
- @block = Musa::Extension::SmartProcBinder::SmartProcBinder.new(block)
109
+ @block = Extension::SmartProcBinder::SmartProcBinder.new(block)
90
110
  else
91
111
  @block.proc
92
112
  end
93
113
  end
94
114
 
95
115
  define_method block_setter do |block|
96
- @block = Musa::Extension::SmartProcBinder::SmartProcBinder.new(block)
116
+ @block = Extension::SmartProcBinder::SmartProcBinder.new(block)
97
117
  end
98
118
 
99
119
  elsif block
@@ -113,35 +133,53 @@ module Musa
113
133
  end
114
134
 
115
135
  module Prototyping
136
+ def state
137
+ try_to_resolve_undefined_state_if_needed
138
+ @state || :undefined
139
+ end
140
+
116
141
  def prototype?
117
- @is_instance ? false : true
142
+ try_to_resolve_undefined_state_if_needed
143
+ @state&.==(:prototype)
118
144
  end
119
145
 
120
146
  def instance?
121
- @is_instance ? true : false
147
+ try_to_resolve_undefined_state_if_needed
148
+ @state&.==(:instance)
149
+ end
150
+
151
+ def undefined?
152
+ try_to_resolve_undefined_state_if_needed
153
+ @state.nil? || @state == :undefined
154
+ end
155
+
156
+ def defined?
157
+ !undefined?
122
158
  end
123
159
 
124
160
  def prototype
125
- if @is_instance
126
- if !@instance_of
127
- @instance_of = clone
128
- @instance_of._prototype!
129
- @instance_of.mark_as_prototype!
130
- @instance_of.init if @instance_of.respond_to?(:init)
131
- end
161
+ try_to_resolve_undefined_state_if_needed
132
162
 
163
+ if prototype?
164
+ self
165
+ elsif instance?
166
+ # if the series has been directly created as an instance (i.e., because is an operation over an instance)
167
+ # the prototype doesn't exist.
168
+ #
133
169
  @instance_of
134
170
  else
135
- self
171
+ raise PrototypingError, 'Can\'t get the prototype of an undefined serie'
136
172
  end
137
173
  end
138
174
 
139
175
  alias_method :p, :prototype
140
176
 
141
177
  def instance
142
- if @is_instance
178
+ try_to_resolve_undefined_state_if_needed
179
+
180
+ if instance?
143
181
  self
144
- else
182
+ elsif prototype?
145
183
  new_instance = clone
146
184
 
147
185
  new_instance._instance!
@@ -149,6 +187,8 @@ module Musa
149
187
  new_instance.init if new_instance.respond_to?(:init)
150
188
 
151
189
  new_instance
190
+ else
191
+ raise PrototypingError, 'Can\'t get an instance of an undefined serie'
152
192
  end
153
193
  end
154
194
 
@@ -163,61 +203,128 @@ module Musa
163
203
  protected def _prototype!
164
204
  @source = @source.prototype if @source
165
205
 
166
- if @sources
167
- if @sources.is_a?(Array)
168
- @sources = @sources.collect(&:prototype)
169
- elsif @sources.is_a?(Hash)
170
- @sources = @sources.transform_values(&:prototype)
171
- end
206
+ case @sources
207
+ when Array
208
+ @sources = @sources.collect(&:prototype)
209
+ when Hash
210
+ @sources = @sources.transform_values(&:prototype)
172
211
  end
173
212
  end
174
213
 
175
214
  protected def _instance!
176
215
  @source = @source.instance if @source
177
216
 
178
- if @sources
179
- if @sources.is_a?(Array)
180
- @sources = @sources.collect(&:instance)
181
- elsif @sources.is_a?(Hash)
182
- @sources = @sources.transform_values(&:instance)
183
- end
217
+ case @sources
218
+ when Array
219
+ @sources = @sources.collect(&:instance)
220
+ when Hash
221
+ @sources = @sources.transform_values(&:instance)
184
222
  end
185
223
  end
186
224
 
187
- protected def mark_as!(getter)
188
- case getter
225
+ protected def mark_as!(state)
226
+ case state
227
+ when nil, :undefined
228
+ mark_as_undefined!
189
229
  when :prototype
190
230
  mark_as_prototype!
191
231
  when :instance
192
232
  mark_as_instance!
193
233
  else
194
- raise ArgumentError, "Only can be marked as :prototype or :instance"
234
+ raise ArgumentError, "Unexpected state #{state}. Only accepted nil, :undefined, :prototype or :instance."
195
235
  end
196
236
  end
197
237
 
198
238
  protected def mark_regarding!(source)
199
- if source.prototype?
239
+ if source.nil? || source.undefined?
240
+ mark_as_undefined!
241
+ elsif source.prototype?
200
242
  mark_as_prototype!
201
- else
243
+ elsif source.instance?
202
244
  mark_as_instance!
203
245
  end
204
246
  end
205
247
 
248
+ protected def mark_as_undefined!
249
+ @state = :undefined
250
+ self
251
+ end
252
+
206
253
  protected def mark_as_prototype!
207
- @get = :prototype
254
+ notify = @state != :prototype
208
255
 
209
- @is_instance = nil
256
+ @state = :prototype
257
+
258
+ _sources_resolved if notify
210
259
  self
211
260
  end
212
261
 
213
262
  protected def mark_as_instance!(prototype = nil)
214
- @get = :instance
263
+ notify = @state != :instance
215
264
 
265
+ @state = :instance
216
266
  @instance_of = prototype
217
- @is_instance = true
267
+
268
+ _sources_resolved if notify
218
269
  self
219
270
  end
220
271
 
272
+ protected def _sources_resolved; end
273
+
274
+ private def try_to_resolve_undefined_state_if_needed
275
+
276
+ return unless @state.nil? || @state == :undefined
277
+
278
+ states = []
279
+
280
+ if has_source
281
+ if mandatory_source
282
+ states << @source&.state || :undefined
283
+ elsif @source
284
+ states << @source.state
285
+ end
286
+ end
287
+
288
+ if has_sources
289
+ sources = case @sources
290
+ when Array
291
+ @sources
292
+ when Hash
293
+ @sources.values
294
+ when nil
295
+ []
296
+ end
297
+
298
+ undefined_sources =
299
+ sources.empty? ||
300
+ sources.any?(&:undefined?) ||
301
+ sources.any?(&:instance?) && sources.any?(&:prototype?)
302
+
303
+ instance_sources = sources.all?(&:instance?) unless undefined_sources
304
+
305
+ sources_state = if undefined_sources
306
+ :undefined
307
+ elsif instance_sources
308
+ :instance
309
+ else
310
+ :prototype
311
+ end
312
+
313
+ if mandatory_sources
314
+ states << sources_state
315
+ elsif !(@sources.nil? || @sources.empty?)
316
+ states << sources_state
317
+ end
318
+ end
319
+
320
+ # in case of having source and sources, if both states are equal the final state is that one, else the final state is undefined
321
+ #
322
+ new_state = states.first if states.first == states.last
323
+ new_state ||= :undefined
324
+
325
+ mark_as!(new_state)
326
+ end
327
+
221
328
  class PrototypingError < RuntimeError
222
329
  def initialize(message = nil)
223
330
  message ||= 'This serie is a prototype serie: cannot be consumed. To consume the serie use an instance serie via .instance method'
@@ -245,7 +352,7 @@ module Musa
245
352
  private def _init; end
246
353
 
247
354
  def restart(...)
248
- raise PrototypingError unless @is_instance
355
+ check_state_permissions
249
356
  init
250
357
  _restart(...)
251
358
 
@@ -255,7 +362,7 @@ module Musa
255
362
  private def _restart; end
256
363
 
257
364
  def next_value
258
- raise PrototypingError unless @is_instance
365
+ check_state_permissions
259
366
 
260
367
  unless @_have_current_value && @_current_value.nil?
261
368
  if @_have_peeked_next_value
@@ -274,7 +381,7 @@ module Musa
274
381
  alias_method :v, :next_value
275
382
 
276
383
  def peek_next_value
277
- raise PrototypingError unless @is_instance
384
+ check_state_permissions
278
385
 
279
386
  if !@_have_peeked_next_value
280
387
  @_have_peeked_next_value = true
@@ -285,16 +392,20 @@ module Musa
285
392
  end
286
393
 
287
394
  def current_value
288
- raise PrototypingError unless @is_instance
395
+ check_state_permissions
289
396
 
290
397
  @_current_value
291
398
  end
292
399
 
293
400
  def infinite?
401
+ check_state_permissions(allows_prototype: true)
294
402
  @source&.infinite? || false
295
403
  end
296
404
 
297
- def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
405
+ def to_a(duplicate: nil, recursive: nil, restart: nil, dr: nil)
406
+ check_state_permissions(allows_prototype: true)
407
+ raise 'Cannot convert to array an infinite serie' if infinite?
408
+
298
409
  recursive ||= false
299
410
 
300
411
  dr = instance? if dr.nil?
@@ -302,8 +413,6 @@ module Musa
302
413
  duplicate = dr if duplicate.nil?
303
414
  restart = dr if restart.nil?
304
415
 
305
- raise 'Cannot convert to array an infinite serie' if infinite?
306
-
307
416
  array = []
308
417
 
309
418
  serie = instance
@@ -324,12 +433,37 @@ module Musa
324
433
 
325
434
  alias_method :a, :to_a
326
435
 
436
+ private def process_for_to_a(value)
437
+ case value
438
+ when Serie
439
+ value.to_a(recursive: true, restart: false, duplicate: false)
440
+ when Array
441
+ a = value.clone
442
+ a.collect! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
443
+ when Hash
444
+ h = value.clone
445
+ h.transform_values! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
446
+ else
447
+ value
448
+ end
449
+ end
450
+
327
451
  def to_node(**attributes)
328
452
  Nodificator.to_node(self, **attributes)
329
453
  end
330
454
 
331
455
  alias_method :node, :to_node
332
456
 
457
+ private def check_state_permissions(allows_prototype: nil)
458
+ try_to_resolve_undefined_state_if_needed
459
+
460
+ raise PrototypingError if !allows_prototype && prototype?
461
+
462
+ unless instance? || prototype?
463
+ raise PrototypingError, 'This serie is in undefined state: cannot be consumed. To consume the serie be sure the serie\'s sources are all in a defined state.'
464
+ end
465
+ end
466
+
333
467
  class Nodificator
334
468
  extend Musa::GenerativeGrammar
335
469
 
@@ -339,21 +473,6 @@ module Musa
339
473
  end
340
474
 
341
475
  private_constant :Nodificator
342
-
343
- private def process_for_to_a(value)
344
- case value
345
- when Serie
346
- value.to_a(recursive: true, restart: false, duplicate: false)
347
- when Array
348
- a = value.clone
349
- a.collect! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
350
- when Hash
351
- h = value.clone
352
- h.transform_values! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
353
- else
354
- value
355
- end
356
- end
357
476
  end
358
477
 
359
478
  private_constant :SerieImplementation
@@ -30,7 +30,7 @@ module Musa
30
30
 
31
31
  def buffer
32
32
  @buffer ||= Buffer.new(@history)
33
- @buffer.send(@get).tap { |_| @buffers << _ }
33
+ @buffer.send(state).tap { |_| @buffers << _ }
34
34
  end
35
35
 
36
36
  private def clear_old_history
@@ -51,6 +51,7 @@ module Musa
51
51
  def initialize(history)
52
52
  @history = history
53
53
  @last_nil_index = -1
54
+ mark_as_prototype!
54
55
  init
55
56
  end
56
57
 
@@ -102,19 +103,31 @@ module Musa
102
103
  @nils = [0]
103
104
  @buffers = Set[]
104
105
 
105
- @singleton = nil
106
106
  @buffer = nil
107
107
 
108
108
  init
109
109
  end
110
110
 
111
- def instance
112
- @singleton ||= super
111
+ def buffer
112
+ Buffer.new(self)
113
113
  end
114
114
 
115
- def buffer
116
- @buffer ||= Buffer.new(self)
117
- @buffer
115
+ def _sources_resolved
116
+ (prototype || self).singleton = self if instance?
117
+ end
118
+
119
+ protected def singleton=(the_instance)
120
+ @singleton ||= the_instance
121
+ end
122
+
123
+ def singleton
124
+ if instance?
125
+ prototype.nil? ? @singleton : prototype.singleton
126
+ elsif prototype?
127
+ @singleton
128
+ else
129
+ raise "ES UNDEFINED!"
130
+ end
118
131
  end
119
132
 
120
133
  private def _restart(buffer)
@@ -163,9 +176,7 @@ module Musa
163
176
  private def clear_old_history
164
177
  min_last_nil_index = @buffers.collect(&:last_nil_index).min
165
178
 
166
- if min_last_nil_index && min_last_nil_index >=0
167
-
168
- pre_nils = @nils.clone
179
+ if min_last_nil_index && min_last_nil_index >= 0
169
180
  @history = @history.drop(min_last_nil_index)
170
181
 
171
182
  @nils.collect! { |_| _ - min_last_nil_index }
@@ -182,9 +193,6 @@ module Musa
182
193
 
183
194
  def initialize(base)
184
195
  self.source = base
185
-
186
- mark_as_prototype! # necesario para que se creen instancias diferentes cada vez que se ejecute BufferSerie.buffer()
187
-
188
196
  init
189
197
  end
190
198
 
@@ -198,13 +206,18 @@ module Musa
198
206
  @index -= offset
199
207
  end
200
208
 
201
- private def _init
202
- @source._register(self) if instance?
209
+ # private def _init
210
+ # @source.prototype.singleton._register(self) if instance?
211
+ # @index = @last_nil_index
212
+ # end
213
+ #
214
+ private def _sources_resolved
215
+ @source.singleton._register(self) if instance?
203
216
  @index = @last_nil_index
204
217
  end
205
218
 
206
219
  private def _restart
207
- @source.restart(self)
220
+ @source.singleton.restart(self)
208
221
  @needs_restart = false
209
222
  end
210
223
 
@@ -216,7 +229,7 @@ module Musa
216
229
  @index += 1
217
230
  value = @history[@index]
218
231
  else
219
- value = _next_value unless @source.next_value.nil?
232
+ value = _next_value unless @source.singleton.next_value.nil?
220
233
  end
221
234
 
222
235
  if value.nil?
@@ -5,26 +5,30 @@ module Musa
5
5
  end
6
6
 
7
7
  class Splitter
8
+ include Series::Serie.with(source: true)
8
9
  include Enumerable
9
- include Series::Serie::Prototyping
10
+
11
+ private def has_source; true; end
12
+ private def has_sources; false; end
10
13
 
11
14
  def initialize(source)
12
- @source = source
15
+ self.source = source
13
16
  @series = {}
17
+
18
+ init
14
19
  end
15
20
 
16
21
  def source=(serie)
17
- @source = serie
22
+ super
18
23
  @proxy.source = @source if @proxy
19
24
  end
20
25
 
21
- protected def _instance!
22
- super
26
+ def _sources_resolved
23
27
  @proxy = SplitterProxy.new(@source)
24
28
  end
25
29
 
26
30
  def [](key_or_index)
27
- raise "Can't get a component because Splitter is a prototype. To get a component you need a Splitter instance." unless @is_instance
31
+ raise "Can't get a component because Splitter is a prototype. To get a component you need a Splitter instance." unless instance?
28
32
 
29
33
  if @series.key?(key_or_index)
30
34
  @series[key_or_index]
@@ -34,7 +38,7 @@ module Musa
34
38
  end
35
39
 
36
40
  def each
37
- raise "Can't iterate because Splitter is a prototype. To iterate you need a Splitter instance." unless @is_instance
41
+ raise "Can't iterate because Splitter is in state '#{state}'. To iterate you need a Splitter in state 'instance'." unless instance?
38
42
 
39
43
  if block_given?
40
44
  if @proxy.hash_mode?
@@ -162,6 +166,8 @@ module Musa
162
166
  end
163
167
  end
164
168
 
169
+ private_constant :SplitterProxy
170
+
165
171
  class Split
166
172
  include Series::Serie.base
167
173
 
@@ -10,6 +10,10 @@ using Musa::Extension::ExplodeRanges
10
10
 
11
11
  module Musa
12
12
  module Series::Constructors
13
+ def UNDEFINED
14
+ UndefinedSerie.new
15
+ end
16
+
13
17
  def NIL
14
18
  NilSerie.new
15
19
  end
@@ -99,8 +103,22 @@ module Musa
99
103
  ### Implementation
100
104
  ###
101
105
 
106
+ class UndefinedSerie
107
+ include Series::Serie.base
108
+
109
+ def initialize
110
+ mark_as_undefined!
111
+ end
112
+ end
113
+
114
+ private_constant :UndefinedSerie
115
+
102
116
  class NilSerie
103
- include Musa::Series::Serie.base
117
+ include Series::Serie.base
118
+
119
+ def initialize
120
+ mark_as_prototype!
121
+ end
104
122
 
105
123
  def _next_value; nil; end
106
124
  end
@@ -108,7 +126,7 @@ module Musa
108
126
  private_constant :NilSerie
109
127
 
110
128
  class FromArray
111
- include Musa::Series::Serie.base
129
+ include Series::Serie.base
112
130
 
113
131
  def initialize(values = nil, extends = nil)
114
132
  @values = values
@@ -143,15 +161,14 @@ module Musa
143
161
  # private_constant :FromArray
144
162
 
145
163
  class Sequence
146
- include Musa::Series::Serie.with(sources: true)
164
+ include Series::Serie.with(sources: true)
147
165
 
148
166
  def initialize(series)
149
167
  self.sources = series
150
-
151
168
  init
152
169
  end
153
170
 
154
- attr_accessor :sources
171
+ attr_reader :sources
155
172
 
156
173
  private def _init
157
174
  @index = 0
@@ -189,9 +206,9 @@ module Musa
189
206
  private_constant :Sequence
190
207
 
191
208
  class FromEvalBlockWithParameters
192
- include Musa::Series::Serie.with(smart_block: true)
209
+ include Series::Serie.with(smart_block: true)
193
210
 
194
- using Musa::Extension::DeepCopy
211
+ using Extension::DeepCopy
195
212
 
196
213
  def initialize(*parameters, **key_parameters, &block)
197
214
  raise ArgumentError, 'Yield block is undefined' unless block
@@ -245,7 +262,7 @@ module Musa
245
262
  private_constant :FromEvalBlockWithParameters
246
263
 
247
264
  class ForLoop
248
- include Musa::Series::Serie.base
265
+ include Series::Serie.base
249
266
 
250
267
  def initialize(from, to, step)
251
268
  @from = from
@@ -303,7 +320,7 @@ module Musa
303
320
  private_constant :ForLoop
304
321
 
305
322
  class RandomValueFromArray
306
- include Musa::Series::Serie.base
323
+ include Series::Serie.base
307
324
 
308
325
  def initialize(values, random)
309
326
  @values = values
@@ -332,7 +349,7 @@ module Musa
332
349
  private_constant :RandomValueFromArray
333
350
 
334
351
  class RandomNumberFromRange
335
- include Musa::Series::Serie.base
352
+ include Series::Serie.base
336
353
 
337
354
  def initialize(from, to, step, random)
338
355
  @from = from
@@ -392,7 +409,7 @@ module Musa
392
409
  private_constant :RandomNumberFromRange
393
410
 
394
411
  class RandomValuesFromArray
395
- include Musa::Series::Serie.base
412
+ include Series::Serie.base
396
413
 
397
414
  def initialize(values, random)
398
415
  @values = values.clone.freeze
@@ -424,7 +441,7 @@ module Musa
424
441
  private_constant :RandomValuesFromArray
425
442
 
426
443
  class RandomNumbersFromRange
427
- include Musa::Series::Serie.base
444
+ include Series::Serie.base
428
445
 
429
446
  def initialize(from, to, step, random)
430
447
  @from = from
@@ -486,7 +503,7 @@ module Musa
486
503
  private_constant :RandomNumbersFromRange
487
504
 
488
505
  class FromHashOfSeries
489
- include Musa::Series::Serie.with(sources: true)
506
+ include Series::Serie.with(sources: true)
490
507
 
491
508
  def initialize(hash_of_series, cycle_all_series)
492
509
  self.sources = hash_of_series
@@ -545,7 +562,7 @@ module Musa
545
562
  private_constant :FromHashOfSeries
546
563
 
547
564
  class FromArrayOfSeries
548
- include Musa::Series::Serie.with(sources: true)
565
+ include Series::Serie.with(sources: true)
549
566
 
550
567
  def initialize(series_array, cycle_all_series)
551
568
  self.sources = series_array
@@ -604,7 +621,7 @@ module Musa
604
621
  private_constant :FromArrayOfSeries
605
622
 
606
623
  class SinFunction
607
- include Musa::Series::Serie.base
624
+ include Series::Serie.base
608
625
 
609
626
  def initialize(start, steps, amplitude, center)
610
627
  @start = start.to_f
@@ -679,7 +696,7 @@ module Musa
679
696
  private_constant :SinFunction
680
697
 
681
698
  class Fibonacci
682
- include Musa::Series::Serie.base
699
+ include Series::Serie.base
683
700
 
684
701
  def initialize
685
702
  mark_as_prototype!
@@ -707,7 +724,7 @@ module Musa
707
724
  private_constant :Fibonacci
708
725
 
709
726
  class HarmonicNotes
710
- include Musa::Series::Serie.base
727
+ include Series::Serie.base
711
728
 
712
729
  def initialize(error, extended)
713
730
  @error = error
@@ -125,7 +125,9 @@ module Musa
125
125
  ###
126
126
 
127
127
  class ProcessWith
128
- include Serie.with(source: true, sources: true, sources_as: :with_sources, smart_block: true)
128
+ include Serie.with(source: true,
129
+ sources: true, sources_as: :with_sources, mandatory_sources: false,
130
+ smart_block: true)
129
131
 
130
132
  def initialize(serie, with_series = nil, on_restart = nil, &block)
131
133
  self.source = serie
@@ -800,12 +802,6 @@ module Musa
800
802
  init
801
803
  end
802
804
 
803
- def source=(serie)
804
- raise ArgumentError, "A serie to reverse can't be infinite" if serie.infinite?
805
- super
806
- init
807
- end
808
-
809
805
  private def _init
810
806
  @reversed = nil
811
807
  end
@@ -815,6 +811,8 @@ module Musa
815
811
  end
816
812
 
817
813
  private def _next_value
814
+ raise ArgumentError, "A serie to reverse can't be infinite" if @source.infinite?
815
+
818
816
  @reversed ||= Constructors.S(*next_values_array_of(@source).reverse).instance
819
817
  @reversed.next_value
820
818
  end
@@ -22,10 +22,6 @@ module Musa
22
22
  @source.next_value if @source
23
23
  end
24
24
 
25
- def infinite?
26
- @source.infinite? if @source
27
- end
28
-
29
25
  private def method_missing(method_name, *args, **key_args, &block)
30
26
  if @source
31
27
  if @source.respond_to?(method_name)
@@ -4,13 +4,58 @@ require_relative '../core-ext/with'
4
4
 
5
5
  module Musa
6
6
  module Series
7
+ module Operations
8
+ def composer(&block)
9
+ ComposerAsOperationSerie.new(self, &block)
10
+ end
11
+
12
+ class ComposerAsOperationSerie
13
+ include Serie.with(source: true)
14
+
15
+ def initialize(serie, &block)
16
+ self.source = serie
17
+ @block = block
18
+
19
+ init
20
+ end
21
+
22
+ attr_reader :composer
23
+
24
+ private def _init
25
+ @composer = Composer::Composer.new(input: @source, &@block)
26
+ @output = @composer.output
27
+ end
28
+
29
+ private def _restart
30
+ @output.restart
31
+ end
32
+
33
+ private def _next_value
34
+ @output.next_value
35
+ end
36
+ end
37
+ end
38
+
7
39
  module Composer
8
40
  class Composer
9
41
  using Musa::Extension::Arrayfy
10
42
 
11
- def initialize(inputs: [:input], outputs: [:output], auto_commit: nil, &block)
43
+ def initialize(input: nil, inputs: [:input], outputs: [:output], auto_commit: nil, &block)
12
44
  auto_commit = true if auto_commit.nil?
13
45
 
46
+ inputs = case inputs
47
+ when Array
48
+ inputs.collect { |_| [_, nil] }.to_h
49
+ when nil
50
+ {}
51
+ when Hash
52
+ inputs
53
+ else
54
+ raise ArgumentError, "inputs: expected a Hash with input names and source series { name: serie, ... } or an Array with names [name, ...] but received #{inputs}"
55
+ end
56
+
57
+ inputs[:input] = input if input
58
+
14
59
  @pipelines = {}
15
60
 
16
61
  def @pipelines.[]=(name, pipeline)
@@ -22,8 +67,9 @@ module Musa
22
67
  @inputs = {}
23
68
  @outputs = {}
24
69
 
25
- inputs&.each do |input|
26
- p = PROXY()
70
+ inputs.keys&.each do |input|
71
+ p = PROXY(inputs[input])
72
+
27
73
  @inputs[input] = @pipelines[input] = Pipeline.new(input, input: p, output: p.buffered, pipelines: @pipelines)
28
74
 
29
75
  @dsl.define_singleton_method(input) { input }
@@ -98,7 +144,8 @@ module Musa
98
144
  end
99
145
 
100
146
  def commit!
101
- first_serie_operation = @first_proc&.call(NIL())
147
+ first_serie_operation = @first_proc&.call(UNDEFINED())
148
+
102
149
  @input ||= first_serie_operation
103
150
 
104
151
  @routes.each_value do |route|
data/musa-dsl.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'musa-dsl'
3
- s.version = '0.23.3'
4
- s.date = '2021-07-28'
3
+ s.version = '0.23.8'
4
+ s.date = '2021-08-03'
5
5
  s.summary = 'A simple Ruby DSL for making complex music'
6
6
  s.description = 'Musa-DSL: A Ruby framework and DSL for algorithmic sound and musical thinking and composition'
7
7
  s.authors = ['Javier Sánchez Yeste']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: musa-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.3
4
+ version: 0.23.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javier Sánchez Yeste
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-28 00:00:00.000000000 Z
11
+ date: 2021-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: citrus