musa-dsl 0.23.0 → 0.23.5

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: b4a1fb5e2fc74d27266ed15f6edcc335c61b580f3c8fa83fd2c425066230a42b
4
- data.tar.gz: 5778babbeeab02ea23d511369946990209929b284e0025f65a67602a1c8fa504
3
+ metadata.gz: 19683437b5ef89739c0d1283c86b18c547a24dd058ca5013abdea4f9c6335f5c
4
+ data.tar.gz: 99fea2b0076baf8976050bd9467f4ecafb87a44bad1b37933e741116f1f5ec96
5
5
  SHA512:
6
- metadata.gz: 33c4b5ab4b14c941ed36ede8919961f0c9bc4d0ec6acf34f2b02f297483c17dfb2e23d270118143c7199f2e073cf001591ad393cae09cbc41e75ac20d8f82c7a
7
- data.tar.gz: 4ffcea9a0a82bd7f97ef659ba0a3b03d9b319980df8987986ee0f63eb694d144fc03d0299b3a87665b78a52fafb5d9b840cf10e7461f36cbfe58b30ce4712f22
6
+ metadata.gz: 26765814873920f392a76fdef1f8f7fc6ce3baca086d47ba443fb74246768943dbe074ebc35b71d946aab7136fd6a433fe03ad897bcff8a16e7045a1fd0c5e7f
7
+ data.tar.gz: 57a1761af4bb50cb40c75680e89716e8f21b8f5a4ea345b42bdb3e2065f58a315fac8b579227741b601c25f2e2e8a617d7fef2cd799366f7df4b749c9a532ec9
@@ -10,7 +10,7 @@ using Musa::Extension::ExplodeRanges
10
10
  module Musa
11
11
  module MIDIVoices
12
12
  class MIDIVoices
13
- attr_accessor :log
13
+ attr_accessor :do_log
14
14
 
15
15
  def initialize(sequencer:, output:, channels:, do_log: nil)
16
16
  do_log ||= false
@@ -24,7 +24,7 @@ module Musa
24
24
  end
25
25
 
26
26
  def reset
27
- @voices = @channels.collect { |channel| MIDIVoice.new sequencer: @sequencer, output: @output, channel: channel, log: @do_log }.freeze
27
+ @voices = @channels.collect { |channel| MIDIVoice.new(sequencer: @sequencer, output: @output, channel: channel, do_log: @do_log) }.freeze
28
28
  end
29
29
 
30
30
  attr_reader :voices
@@ -48,14 +48,14 @@ module Musa
48
48
  attr_accessor :name, :do_log
49
49
  attr_reader :sequencer, :output, :channel, :active_pitches, :tick_duration
50
50
 
51
- def initialize(sequencer:, output:, channel:, name: nil, log: nil)
52
- log ||= false
51
+ def initialize(sequencer:, output:, channel:, name: nil, do_log: nil)
52
+ do_log ||= false
53
53
 
54
54
  @sequencer = sequencer
55
55
  @output = output
56
56
  @channel = channel
57
57
  @name = name
58
- @do_log = log
58
+ @do_log = do_log
59
59
 
60
60
  @tick_duration = Rational(1, @sequencer.ticks_per_bar)
61
61
 
@@ -64,7 +64,7 @@ module Musa
64
64
  @active_pitches = []
65
65
  fill_active_pitches @active_pitches
66
66
 
67
- log 'Warning: voice without output' unless @output
67
+ @sequencer.logger.warn 'voice without output' unless @output
68
68
 
69
69
  self
70
70
  end
@@ -118,7 +118,7 @@ module Musa
118
118
  end
119
119
 
120
120
  def log(msg)
121
- @sequencer.log "voice #{name || @channel}: #{msg}" if @do_log
121
+ @sequencer.logger.info('MIDIVoice') { "voice #{name || @channel}: #{msg}" } if @do_log
122
122
  end
123
123
 
124
124
  def to_s
@@ -38,12 +38,12 @@ module Musa
38
38
  include SerieImplementation
39
39
 
40
40
  if source
41
- define_method source_as do ||
41
+ define_method source_as do
42
42
  @source
43
43
  end
44
44
 
45
45
  define_method source_setter do |serie|
46
- raise ArgumentError, "New source should be a #{@get}" unless @source.nil? || @source.prototype? == serie&.prototype?
46
+ raise ArgumentError, "New #{source_as} should be a #{@get}" unless @source.nil? || @source.prototype? == serie&.prototype?
47
47
 
48
48
  serie ||= Musa::Series::Constructors.NIL
49
49
  @get = serie&.instance? ? :instance : :prototype
@@ -294,7 +294,7 @@ module Musa
294
294
  @source&.infinite? || false
295
295
  end
296
296
 
297
- def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
297
+ def to_a(duplicate: nil, recursive: nil, restart: nil, dr: nil)
298
298
  recursive ||= false
299
299
 
300
300
  dr = instance? if dr.nil?
@@ -117,18 +117,18 @@ module Musa
117
117
  @buffer
118
118
  end
119
119
 
120
- private def _restart(main)
121
- raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless main
120
+ private def _restart(buffer)
121
+ raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless buffer
122
122
  return if @source_just_restarted
123
123
 
124
- next_nil = @nils.find { |_| _ > main.index }
124
+ next_nil = @nils.find { |_| _ > buffer.index }
125
125
 
126
- if next_nil && main.index < next_nil
127
- main.last_nil_index = main.index = next_nil
126
+ if next_nil && buffer.index < next_nil
127
+ buffer.last_nil_index = buffer.index = next_nil
128
128
 
129
129
  else
130
130
  until _next_value.nil?; end
131
- main.last_nil_index = main.index = @nils.last
131
+ buffer.last_nil_index = buffer.index = @nils.last
132
132
  end
133
133
 
134
134
  clear_old_history
@@ -216,8 +216,7 @@ module Musa
216
216
  @index += 1
217
217
  value = @history[@index]
218
218
  else
219
- @source.next_value
220
- value = _next_value
219
+ value = _next_value unless @source.next_value.nil?
221
220
  end
222
221
 
223
222
  if value.nil?
@@ -1,19 +1,32 @@
1
1
  module Musa
2
2
  module Series::Operations
3
3
  def split
4
- Splitter.new(Splitter::BufferedProxy.new(self))
4
+ Splitter.new(self)
5
5
  end
6
6
 
7
7
  class Splitter
8
8
  include Enumerable
9
+ include Series::Serie::Prototyping
9
10
 
10
- def initialize(proxy)
11
- @proxy = proxy
11
+ def initialize(source)
12
+ @source = source
12
13
  @series = {}
13
14
  end
14
15
 
16
+ def source=(serie)
17
+ @source = serie
18
+ @proxy.source = @source if @proxy
19
+ end
20
+
21
+ protected def _instance!
22
+ super
23
+ @proxy = SplitterProxy.new(@source)
24
+ end
25
+
15
26
  def [](key_or_index)
16
- if @series.has_key?(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
28
+
29
+ if @series.key?(key_or_index)
17
30
  @series[key_or_index]
18
31
  else
19
32
  @series[key_or_index] = Split.new(@proxy, key_or_index)
@@ -21,6 +34,8 @@ module Musa
21
34
  end
22
35
 
23
36
  def each
37
+ raise "Can't iterate because Splitter is a prototype. To iterate you need a Splitter instance." unless @is_instance
38
+
24
39
  if block_given?
25
40
  if @proxy.hash_mode?
26
41
  @proxy.components.each do |key|
@@ -60,24 +75,24 @@ module Musa
60
75
  end
61
76
  end
62
77
 
63
- class BufferedProxy
64
- include Series::Serie::Prototyping
65
-
78
+ class SplitterProxy
66
79
  def initialize(hash_or_array_serie)
67
80
  @source = hash_or_array_serie
68
- mark_regarding! @source
69
-
70
- init
81
+ infer_components
71
82
  end
72
83
 
73
- attr_reader :components
84
+ attr_reader :source
85
+
86
+ def source=(hash_or_array_serie)
87
+ @source = hash_or_array_serie
88
+ infer_components
89
+ end
74
90
 
75
91
  def hash_mode?; @hash_mode; end
92
+
76
93
  def array_mode?; @array_mode; end
77
94
 
78
- def init
79
- infer_components
80
- end
95
+ attr_reader :components
81
96
 
82
97
  def restart(key_or_index = nil)
83
98
  if key_or_index
@@ -151,18 +166,18 @@ module Musa
151
166
  include Series::Serie.base
152
167
 
153
168
  def initialize(proxy, key_or_index)
154
- @source = proxy
169
+ @proxy = proxy
155
170
  @key_or_index = key_or_index
156
171
 
157
- mark_regarding! @source
172
+ mark_as_instance!
158
173
  end
159
174
 
160
175
  private def _restart
161
- @source.restart @key_or_index
176
+ @proxy.restart(@key_or_index)
162
177
  end
163
178
 
164
179
  private def _next_value
165
- @source.next_value(@key_or_index)
180
+ @proxy.next_value(@key_or_index)
166
181
  end
167
182
  end
168
183
 
@@ -566,7 +566,7 @@ module Musa
566
566
  end
567
567
 
568
568
  private def _next_value
569
- unless @have_current && @value.nil?
569
+ unless @sources.empty? || @have_current && @value.nil?
570
570
  pre_value = @sources.collect(&:peek_next_value)
571
571
 
572
572
  nils = 0
@@ -116,6 +116,10 @@ module Musa
116
116
  Anticipate.new self, &block
117
117
  end
118
118
 
119
+ def lazy(&block)
120
+ LazySerieEval.new self, &block
121
+ end
122
+
119
123
  ###
120
124
  ### Implementation
121
125
  ###
@@ -1006,6 +1010,45 @@ module Musa
1006
1010
  end
1007
1011
 
1008
1012
  private_constant :HashFromSeriesArray
1013
+
1014
+ class LazySerieEval
1015
+ include Serie.with(source: true, block: true)
1016
+
1017
+ def initialize(serie, &block)
1018
+ self.source = serie
1019
+ self.proc = block
1020
+
1021
+ init
1022
+ end
1023
+
1024
+ def source=(serie)
1025
+ super
1026
+ @processed = nil
1027
+ end
1028
+
1029
+ def proc(&block)
1030
+ super
1031
+ @processed = nil if block
1032
+ end
1033
+
1034
+ def proc=(block)
1035
+ super
1036
+ @processed = nil if block
1037
+ end
1038
+
1039
+ private def _restart
1040
+ @processed = nil
1041
+ @source.restart
1042
+ end
1043
+
1044
+ private def _next_value
1045
+ @processed ||= @block.call(@source)
1046
+ @processed.next_value
1047
+ end
1048
+ end
1049
+
1050
+ private_constant :LazySerieEval
1009
1051
  end
1052
+
1010
1053
  end
1011
1054
  end
@@ -7,10 +7,10 @@ module Musa
7
7
  end
8
8
 
9
9
  class ProxySerie
10
- include Series::Serie.with(source: true)
10
+ include Series::Serie.with(source: true, source_as: :proxy_source)
11
11
 
12
12
  def initialize(serie)
13
- self.source = serie
13
+ self.proxy_source = serie
14
14
  init
15
15
  end
16
16
 
@@ -27,15 +27,19 @@ module Musa
27
27
  end
28
28
 
29
29
  private def method_missing(method_name, *args, **key_args, &block)
30
- if @source && @source.respond_to?(method_name)
31
- @source.send method_name, *args, **key_args, &block
30
+ if @source
31
+ if @source.respond_to?(method_name)
32
+ @source.send method_name, *args, **key_args, &block
33
+ else
34
+ raise NoMethodError, "undefined method '#{method_name}' for proxied #{@source.to_s}"
35
+ end
32
36
  else
33
37
  super
34
38
  end
35
39
  end
36
40
 
37
41
  private def respond_to_missing?(method_name, include_private)
38
- @source && @source.respond_to?(method_name, include_private) # || super
42
+ @source && @source.respond_to?(method_name, include_private) # || super ??
39
43
  end
40
44
  end
41
45
  end
@@ -4,38 +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
+ Composer::Composer.new(&block).tap { |_| _.input.proxy_source = self}.output
10
+ end
11
+ end
12
+
7
13
  module Composer
8
14
  class Composer
9
15
  using Musa::Extension::Arrayfy
10
16
 
11
- attr_reader :inputs, :outputs
17
+ def initialize(inputs: [:input], outputs: [:output], auto_commit: nil, &block)
18
+ auto_commit = true if auto_commit.nil?
12
19
 
13
- def initialize(inputs: [:input], outputs: [:output], &block)
14
20
  @pipelines = {}
15
21
 
16
- @links = Set[]
17
- @links_from = {}
18
- @links_to = {}
22
+ def @pipelines.[]=(name, pipeline)
23
+ pipeline_to_add = @commited ? pipeline.commit! : pipeline
24
+ super(name, pipeline_to_add)
25
+ end
19
26
 
20
- @dsl = DSLContext.new(@pipelines, @links, @links_from, @links_to)
27
+ @dsl = DSLContext.new(@pipelines)
21
28
  @inputs = {}
22
29
  @outputs = {}
23
30
 
24
31
  inputs&.each do |input|
25
- @inputs[input] = Series::Constructors.PROXY
26
- @pipelines[input] = { input: nil, output: @inputs[input].buffered }
32
+ p = PROXY()
33
+ @inputs[input] = @pipelines[input] = Pipeline.new(input, input: p, output: p.buffered, pipelines: @pipelines)
27
34
 
28
35
  @dsl.define_singleton_method(input) { input }
29
36
  end
30
37
 
31
38
  outputs&.each do |output|
32
- @outputs[output] = Series::Constructors.PROXY
33
- @pipelines[output] = { input: @outputs[output], output: nil }
39
+ p = PROXY()
40
+ @outputs[output] = @pipelines[output] = Pipeline.new(output, is_output: true, input: p, output: p, pipelines: @pipelines)
34
41
 
35
42
  @dsl.define_singleton_method(output) { output }
36
43
  end
37
44
 
38
45
  @dsl.with &block if block
46
+ commit! if auto_commit
47
+ end
48
+
49
+ def input(name = nil)
50
+ name ||= :input
51
+ @inputs[name].input
52
+ end
53
+
54
+ def output(name = nil)
55
+ raise "Can't access output if the Composer is uncommited. Call '.commit' first." unless @commited
56
+
57
+ name ||= :output
58
+ @outputs[name].output
39
59
  end
40
60
 
41
61
  def route(from, to:, on: nil, as: nil)
@@ -50,15 +70,76 @@ module Musa
50
70
  @dsl.with &block
51
71
  end
52
72
 
73
+ def commit!
74
+ raise 'Already commited' if @commited
75
+
76
+ @outputs.each_value do |pipeline|
77
+ pipeline.commit!
78
+ end
79
+
80
+ @commited = true
81
+ end
82
+
83
+ class Pipeline
84
+ def initialize(name, is_output: false, input: nil, output: nil, first_proc: nil, chain_proc: nil, pipelines:)
85
+ @name = name
86
+ @is_output = is_output
87
+ @input = input
88
+ @output = output
89
+ @first_proc = first_proc
90
+ @chain_proc = chain_proc
91
+ @routes = {}
92
+ @pipelines = pipelines
93
+ end
94
+
95
+ attr_reader :name, :is_output
96
+ attr_accessor :input, :output, :proc
97
+
98
+ def [](on, as)
99
+ @routes[[on, as]]
100
+ end
101
+
102
+ def []=(on, as, source)
103
+ @routes[[on, as]] = Route.new(on, as, source)
104
+ end
105
+
106
+ def commit!
107
+ first_serie_operation = @first_proc&.call(NIL())
108
+ @input ||= first_serie_operation
109
+
110
+ @routes.each_value do |route|
111
+ route.source.commit!
112
+
113
+ if @is_output
114
+ @input.proxy_source = route.source.output.buffer
115
+ elsif route.as
116
+ @input.send(route.on)[route.as] = route.source.output.buffer
117
+ else
118
+ @input.send("#{route.on.to_s}=".to_sym, route.source.output.buffer)
119
+ end
120
+ end
121
+
122
+ chain_serie_operation = @chain_proc&.call(@input) || @input
123
+ @output ||= chain_serie_operation.buffered
124
+
125
+ self
126
+ end
127
+ end
128
+
129
+ class Route
130
+ def initialize(on, as, source)
131
+ @on = on
132
+ @as = as
133
+ @source = source
134
+ end
135
+ attr_accessor :on, :as, :source
136
+ end
137
+
53
138
  class DSLContext
54
139
  include Musa::Extension::With
55
140
 
56
- def initialize(pipelines, links, links_from, links_to)
141
+ def initialize(pipelines)
57
142
  @pipelines = pipelines
58
-
59
- @links = links
60
- @links_from = links_from
61
- @links_to = links_to
62
143
  end
63
144
 
64
145
  def route(from, to:, on: nil, as: nil)
@@ -68,69 +149,159 @@ module Musa
68
149
  raise ArgumentError, "Pipeline '#{from}' not found." unless from_pipeline
69
150
  raise ArgumentError, "Pipeline '#{to}' not found." unless to_pipeline
70
151
 
71
- @links_from[from] ||= Set[]
152
+ if to_pipeline.is_output && (on || as)
153
+ raise ArgumentError, "Output pipeline #{to_pipeline.name} only allows default routing"
154
+ end
72
155
 
73
- on ||= as ? :sources : :source
156
+ on ||= (as ? :sources : :source)
74
157
 
75
- raise ArgumentError, "Pipeline #{@links_to[[to, on, as]]} already connected to pipeline #{to} on #{on} as #{as}" if @links_to[[to, on, as]]
158
+ raise ArgumentError,
159
+ "Source of pipeline #{to} on #{on} as #{as} already connected to #{to_pipeline[on, as].source.name}" \
160
+ unless to_pipeline[on, as].nil?
76
161
 
77
- if as
78
- to_pipeline[:input].send(on)[as] = from_pipeline[:output].buffer
79
- else
80
- to_pipeline[:input].send("#{on.to_s}=".to_sym, from_pipeline[:output].buffer)
81
- end
82
162
 
83
- @links_from[from] << [to, on, as]
84
- @links_to[[to, on, as]] = from
85
- @links << [from, to, on, as]
163
+ to_pipeline[on, as] = from_pipeline
86
164
  end
87
165
 
88
166
  def pipeline(name, elements)
89
- first = last = nil
167
+ first, chain = parse(elements)
168
+ @pipelines[name] = Pipeline.new(name, first_proc: first, chain_proc: chain, pipelines: @pipelines)
169
+
170
+ define_singleton_method(name) { name }
171
+ end
90
172
 
91
- elements.each do |e|
92
- case e
93
- when Hash
94
- if e.size == 1
95
- operation = e.keys.first
96
- parameters = e.values.first
173
+ private def parse(thing)
174
+ case thing
175
+ when Array
176
+ first = chain = nil
177
+
178
+ thing.each do |element|
179
+ case element
180
+ when Hash
181
+ new_chain = parse(element)
182
+ when Symbol
183
+ new_chain = operation_as_chained_proc(element, nil)
184
+ when Proc
185
+ new_chain = operation_as_chained_proc(:map, element)
186
+ else
187
+ raise ArgumentError, "Syntax error: don't know how to handle #{element}"
188
+ end
97
189
 
98
- if Musa::Series::Constructors.instance_methods.include?(operation)
99
- raise ArgumentError, "Called constructor '#{operation}' ignoring previous elements" unless last.nil?
190
+ if first.nil?
191
+ first = new_chain unless first
192
+ else
193
+ chain = chain ? chain >> new_chain : new_chain
194
+ end
195
+ end
100
196
 
101
- last = Musa::Series::Constructors.method(operation).call(*parameters)
197
+ [first, chain]
102
198
 
103
- elsif Musa::Series::Operations.instance_methods.include?(operation)
104
- first = last = Musa::Series::Constructors.PROXY if last.nil?
105
- last = last.send(operation, *parameters)
199
+ when Hash
200
+ if thing.size == 1
201
+ operation = thing.first[0] # key
202
+ parameter = thing.first[1] # value
106
203
 
107
- end
204
+ if is_a_series_constructor?(operation)
205
+ operation_as_chained_proc(operation, parameter)
108
206
  else
109
- raise ArgumentError, "Don't know how to handle #{e}"
207
+ operation_as_chained_proc(operation, parse(parameter))
110
208
  end
111
- when Symbol
112
- first = last = Musa::Series::Constructors.PROXY if last.nil?
113
- # operation == e
114
- last = last.send(e) if Musa::Series::Operations.instance_methods.include?(e)
209
+ else
210
+ raise ArgumentError, "Syntax error: don't know how to handle #{element}"
115
211
  end
116
212
 
117
- first ||= last
213
+ when Symbol
214
+ operation_as_chained_proc(operation)
215
+
216
+ when Proc
217
+ thing
218
+
219
+ else
220
+ thing
118
221
  end
222
+ end
119
223
 
120
- @pipelines[name] = { input: first, output: last.buffered }
224
+ private def operation_as_chained_proc(operation, parameter = nil)
225
+ if is_a_series_constructor?(operation)
226
+ proc do |last|
227
+ call_constructor_according_to_last_and_parameter(last, operation, parameter)
228
+ end
121
229
 
122
- define_singleton_method(name) { name }
230
+ elsif is_a_series_operation?(operation)
231
+ proc { |last| call_operation_according_to_parameter(last, operation, parameter) }
232
+
233
+ else
234
+ # non-series operation
235
+ proc { |last| call_operation_according_to_parameter(last, operation, parameter) }
236
+ end
123
237
  end
124
238
 
125
- private def method_missing(symbol, *args, &block)
126
- if Musa::Series::Operations.instance_methods.include?(symbol)
127
- symbol
128
- elsif Musa::Series::Constructors.instance_methods.include?(symbol)
129
- symbol
239
+ private def call_constructor_according_to_last_and_parameter(last, constructor, parameter)
240
+ case last
241
+ when Proc
242
+ call_constructor_according_to_last_and_parameter(last.call, constructor, parameter)
243
+
244
+ when Serie
245
+ # TODO: ignoring last, should make an error?
246
+ Musa::Series::Constructors.method(constructor).call(*parameter)
247
+
248
+ when nil
249
+ Musa::Series::Constructors.method(constructor).call(*parameter)
250
+
251
+ when Array
252
+ raise "Unexpected parameter #{parameter} for constructor #{constructor} " \
253
+ "because the previous operation on the pipeline chain returned non-nil #{last}" \
254
+ unless parameter.nil?
255
+
256
+ Musa::Series::Constructors.method(constructor).call(*last)
257
+
258
+ when Hash
259
+ raise "Unexpected parameter #{parameter} for constructor #{constructor} " \
260
+ "because the previous operation on the pipeline chain returned non-nil #{last}" \
261
+ unless parameter.nil?
262
+
263
+ Musa::Series::Constructors.method(constructor).call(**last)
264
+
265
+ else
266
+ raise ArgumentError, "Don't know how to handle last #{last}"
267
+ end
268
+ end
269
+
270
+ private def call_operation_according_to_parameter(target, operation, parameter)
271
+ case parameter
272
+ when nil
273
+ target.send(operation)
274
+ when Symbol
275
+ target.send(operation).send(parameter)
276
+ when Proc
277
+ target.send(operation, &parameter)
278
+ when Array
279
+ unless parameter.size == 2 && parameter.all? { |_| _.is_a?(Proc) }
280
+ raise ArgumentError, "Don't know how to handle parameter #{parameter}"
281
+ end
282
+
283
+ target.send(operation, &(parameter.first >> parameter.last))
130
284
  else
131
- raise ArgumentError, "Pipeline '#{symbol}' is undefined" if args.empty?
285
+ target.send(operation, parameter)
286
+ end
287
+ end
288
+
289
+ private def is_a_series_constructor?(operation)
290
+ Musa::Series::Constructors.instance_methods.include?(operation)
291
+ end
132
292
 
293
+ private def is_a_series_operation?(operation)
294
+ Musa::Series::Operations.instance_methods.include?(operation)
295
+ end
296
+
297
+ private def method_missing(symbol, *args, &block)
298
+ if is_a_series_constructor?(symbol) || is_a_series_operation?(symbol)
299
+ symbol
300
+ elsif args.any? || block
301
+ args += [block] if block
133
302
  pipeline(symbol, args)
303
+ else # for non-series methods
304
+ symbol
134
305
  end
135
306
  end
136
307
 
@@ -142,6 +313,8 @@ module Musa
142
313
  end
143
314
  end
144
315
 
316
+ private_constant :Pipeline
317
+ private_constant :Route
145
318
  private_constant :DSLContext
146
319
  end
147
320
  end
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.0'
4
- s.date = '2021-06-29'
3
+ s.version = '0.23.5'
4
+ s.date = '2021-07-28'
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.0
4
+ version: 0.23.5
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-06-29 00:00:00.000000000 Z
11
+ date: 2021-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: citrus