musa-dsl 0.23.3 → 0.23.8

Sign up to get free protection for your applications and to get access to all the features.
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