musa-dsl 0.22.6 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e85f0a7bc9ddbb82ea9b6b36741a87c1dc04f2feb1c10ea0f5fcb92e4dfc7a37
4
- data.tar.gz: 13ad3537ac0a2e03c07c589174a12a8dd9af5013be79f5bd1ee769820cd94347
3
+ metadata.gz: b4a1fb5e2fc74d27266ed15f6edcc335c61b580f3c8fa83fd2c425066230a42b
4
+ data.tar.gz: 5778babbeeab02ea23d511369946990209929b284e0025f65a67602a1c8fa504
5
5
  SHA512:
6
- metadata.gz: 06f58c414bbbd873179850c378f3022e1bc40eba16325b787824e1cb88b27229c7ac19d08032c8b0385c792ae38324c982970dcc94c91e7fd3d924208b640aa4
7
- data.tar.gz: 63398fc18d40799119742df1587735f9736abec4a0c1d97e9a9b29202395b6f4223cea7c01075e95d6f0ae4d752dd7297ba88c9df8c2ac7c76dea439732a8435
6
+ metadata.gz: 33c4b5ab4b14c941ed36ede8919961f0c9bc4d0ec6acf34f2b02f297483c17dfb2e23d270118143c7199f2e073cf001591ad393cae09cbc41e75ac20d8f82c7a
7
+ data.tar.gz: 4ffcea9a0a82bd7f97ef659ba0a3b03d9b319980df8987986ee0f63eb694d144fc03d0299b3a87665b78a52fafb5d9b840cf10e7461f36cbfe58b30ce4712f22
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'logger', '~> 1.4', '>= 1.4.3'
4
+
3
5
  group :neuma do
4
6
  gem 'citrus', '~> 3.0.0'
5
7
  end
@@ -10,8 +12,8 @@ group :transport do
10
12
  end
11
13
 
12
14
  group :test do
13
- gem 'rspec', '~> 3.0'
14
15
  gem 'descriptive-statistics'
16
+ gem 'rspec', '~> 3.0'
15
17
  end
16
18
 
17
19
  group :documentation do
data/lib/musa-dsl.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Musa
2
- VERSION = '0.22.6'
2
+ VERSION = '0.23.0'
3
3
  end
4
4
 
5
5
  require_relative 'musa-dsl/core-ext'
@@ -27,21 +27,30 @@ require_relative 'musa-dsl/music'
27
27
  require_relative 'musa-dsl/generative'
28
28
 
29
29
  module Musa::All
30
+ # Core
31
+ #
30
32
  include Musa::Logger
31
33
 
32
34
  include Musa::Clock
33
35
  include Musa::Transport
34
36
  include Musa::Sequencer
35
37
 
36
- include Musa::Scales
37
- include Musa::Chords
38
+ include Musa::Series
38
39
  include Musa::Datasets
39
40
 
40
41
  include Musa::Neumalang
41
42
  include Musa::Neumas
42
- include Musa::Matrix
43
43
 
44
- include Musa::Series
44
+ include Musa::Transcription
45
+
46
+ include Musa::REPL
47
+
48
+ # Extensions: ojo, el nombre extensions ya se usa para algunos paquetes de core-ext que funcionan con Refinements
49
+ #
50
+ include Musa::Scales
51
+ include Musa::Chords
52
+
53
+ include Musa::Matrix
45
54
 
46
55
  include Musa::Darwin
47
56
  include Musa::Markov
@@ -53,8 +62,5 @@ module Musa::All
53
62
 
54
63
  include Musa::MusicXML
55
64
 
56
- include Musa::Transcription
57
65
  include Musa::Transcriptors
58
-
59
- include Musa::REPL
60
66
  end
@@ -118,7 +118,18 @@ module Musa
118
118
  end
119
119
 
120
120
  def deep_copy_proc(register, object, method, freeze)
121
- register(register, object, object.dup)
121
+ if (receiver_dup = registered(object.binding.receiver, register))
122
+ register(register,
123
+ object,
124
+ proc do |*args, **kargs|
125
+ # when the receiver of the proc is also a duplicated object
126
+ # the new copy of the proc should be the new object, not the original one.
127
+ #
128
+ receiver_dup.instance_exec(object, *args, **kargs, &object)
129
+ end)
130
+ else
131
+ register(register, object, object.dup)
132
+ end
122
133
  end
123
134
 
124
135
  def deep_copy_instance_variables(register, object, duplication, method, freeze)
@@ -2,8 +2,8 @@ module Musa
2
2
  module Extension
3
3
  module SmartProcBinder
4
4
  class SmartProcBinder
5
- def initialize(procedure, on_rescue: nil)
6
- @procedure = procedure
5
+ def initialize(block, on_rescue: nil)
6
+ @block = block
7
7
  @on_rescue = on_rescue
8
8
 
9
9
  @key_parameters = {}
@@ -12,7 +12,7 @@ module Musa
12
12
  @value_parameters_count = 0
13
13
  @has_value_rest = false
14
14
 
15
- procedure.parameters.each do |parameter|
15
+ block.parameters.each do |parameter|
16
16
  @key_parameters[parameter[1]] = nil if parameter[0] == :key || parameter[0] == :keyreq
17
17
  @has_key_rest = true if parameter[0] == :keyrest
18
18
 
@@ -21,8 +21,12 @@ module Musa
21
21
  end
22
22
  end
23
23
 
24
+ def proc
25
+ @block
26
+ end
27
+
24
28
  def parameters
25
- @procedure.parameters
29
+ @block.parameters
26
30
  end
27
31
 
28
32
  def call(*value_parameters, **key_parameters)
@@ -41,26 +45,24 @@ module Musa
41
45
  end
42
46
  end
43
47
 
44
- def __call(value_parameters, key_parameters)
48
+ private def __call(value_parameters, key_parameters)
45
49
  effective_value_parameters, effective_key_parameters = apply(*value_parameters, **key_parameters)
46
50
 
47
51
  if effective_key_parameters.empty?
48
52
  if effective_value_parameters.empty?
49
- @procedure.call
53
+ @block.call
50
54
  else
51
- @procedure.call *effective_value_parameters
55
+ @block.call *effective_value_parameters
52
56
  end
53
57
  else
54
58
  if effective_value_parameters.empty?
55
- @procedure.call **effective_key_parameters
59
+ @block.call **effective_key_parameters
56
60
  else
57
- @procedure.call *effective_value_parameters, **effective_key_parameters
61
+ @block.call *effective_value_parameters, **effective_key_parameters
58
62
  end
59
63
  end
60
64
  end
61
65
 
62
- private :__call
63
-
64
66
  def key?(key)
65
67
  @has_key_rest || @key_parameters.include?(key)
66
68
  end
@@ -13,7 +13,7 @@ module Musa::Datasets
13
13
 
14
14
  # TODO if instead of using clone (needed because of p.shift) we use index counter the P elements would be evaluated on the last moment
15
15
 
16
- Musa::Series::E(clone, base_duration) do |p, base_duration|
16
+ Musa::Series::Constructors.E(clone, base_duration) do |p, base_duration|
17
17
  (p.size >= 3) ?
18
18
  { from: p.shift,
19
19
  duration: p.shift * base_duration,
@@ -46,30 +46,34 @@ module Musa::Datasets
46
46
  end
47
47
 
48
48
  class PtoTimedSerie
49
- include Musa::Series::Serie
50
-
51
- attr_reader :origin
49
+ include Musa::Series::Serie.base
52
50
 
53
51
  def initialize(origin, base_duration, time_start)
54
52
  @origin = origin
55
53
  @base_duration = base_duration
56
54
  @time_start = time_start
57
55
 
58
- _restart
56
+ init
59
57
 
60
58
  mark_as_prototype!
61
59
  end
62
60
 
63
- def _restart
64
- @p = @origin.clone
61
+ attr_accessor :origin
62
+ attr_accessor :base_duration
63
+ attr_accessor :time_start
64
+
65
+ private def _init
66
+ @index = 0
65
67
  @time = @time_start
66
68
  end
67
69
 
68
- def _next_value
69
- if value = @p.shift
70
+ private def _next_value
71
+ if value = @origin[@index]
72
+ @index += 1
70
73
  r = { time: @time, value: value }.extend(AbsTimed)
71
74
 
72
- delta_time = @p.shift
75
+ delta_time = @origin[@index]
76
+ @index += 1
73
77
  @time += delta_time * @base_duration if delta_time
74
78
 
75
79
  r
@@ -3,13 +3,8 @@ require_relative '../core-ext/with'
3
3
 
4
4
  using Musa::Extension::Arrayfy
5
5
 
6
- # incluir With -> hecho
7
- # eliminar method_missing
8
- # crear rama tb debe recibir la serie de la history -> ya lo hace
9
- # crear rama puede repetirse (hasta terminar según ended_when) -> no
10
- #
11
- # hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
12
- # esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
6
+ # TODO hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
7
+ # TODO esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
13
8
 
14
9
  module Musa
15
10
  module Backboner
@@ -17,12 +12,12 @@ module Musa
17
12
  include Musa::Extension::With
18
13
 
19
14
  def initialize(&block)
20
- @context = RulesEvalContext.new(&block)
15
+ @dsl = RulesEvalContext.new(&block)
21
16
  end
22
17
 
23
18
  def generate_possibilities(object, confirmed_node = nil, node = nil, grow_rules = nil)
24
19
  node ||= Node.new
25
- grow_rules ||= @context._grow_rules
20
+ grow_rules ||= @dsl._grow_rules
26
21
 
27
22
  history = confirmed_node.history if confirmed_node
28
23
  history ||= []
@@ -33,9 +28,9 @@ module Musa
33
28
  if grow_rule
34
29
  grow_rule.generate_possibilities(object, history).each do |new_object|
35
30
  new_node = Node.new new_object, node
36
- new_node.mark_as_ended! if @context._ended? new_object
31
+ new_node.mark_as_ended! if @dsl._ended? new_object
37
32
 
38
- rejection = @context._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
33
+ rejection = @dsl._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
39
34
  # TODO: include rejection secondary reasons in rejection message
40
35
 
41
36
  new_node.reject! rejection if rejection
@@ -100,9 +100,7 @@ module Musa
100
100
  options[index].to_serie.to_node
101
101
  end
102
102
 
103
- def to_serie(flatten: nil, &condition)
104
- flatten ||= true
105
-
103
+ def to_serie(flatten: true, &condition)
106
104
  serie = _options(&condition).collect { |o| o.collect(&:content) }.to_serie(of_series: true).merge
107
105
  serie = serie.flatten if flatten
108
106
 
@@ -7,9 +7,8 @@ module Musa
7
7
  module Markov
8
8
  class Markov
9
9
  include Musa::Extension::SmartProcBinder
10
- include Musa::Series::Serie
10
+ include Musa::Series::Serie.base
11
11
 
12
- attr_accessor :start, :finish, :random, :transitions
13
12
 
14
13
  def initialize(transitions:, start:, finish: nil, random: nil)
15
14
  @transitions = transitions.clone.freeze
@@ -22,23 +21,28 @@ module Musa
22
21
 
23
22
  @procedure_binders = {}
24
23
 
25
- _restart
24
+ init
26
25
  end
27
26
 
28
- def _restart
27
+ attr_accessor :start
28
+ attr_accessor :finish
29
+ attr_accessor :random
30
+ attr_accessor :transitions
31
+
32
+ private def _init
29
33
  @current = nil
30
34
  @finished = false
31
35
  @history = []
32
36
  end
33
37
 
34
- def _next_value
38
+ private def _next_value
35
39
  if @finished
36
40
  @current = nil
37
41
  else
38
42
  if @current.nil?
39
43
  @current = @start
40
44
  else
41
- if @transitions.has_key? @current
45
+ if @transitions.has_key?(@current)
42
46
  options = @transitions[@current]
43
47
 
44
48
  case options
@@ -15,7 +15,7 @@ module Musa
15
15
  include Musa::Neumas
16
16
 
17
17
  def value
18
- _SE(captures(:expression).collect(&:value), extends: Neuma::Serie)
18
+ S(*captures(:expression).collect(&:value)).extend(Neuma::Serie)
19
19
  end
20
20
  end
21
21
 
@@ -21,7 +21,7 @@ module Musa
21
21
  def convert_to_neumas(e)
22
22
  case e
23
23
  when Musa::Neumas::Neuma::Serie then e
24
- when Musa::Neumas::Neuma::Parallel then _SE([e], extends: Musa::Neumas::Neuma::Serie)
24
+ when Musa::Neumas::Neuma::Parallel then S(e).extend(Musa::Neumas::Neuma::Serie)
25
25
  when String then e.to_neumas
26
26
  else
27
27
  raise ArgumentError, "Don't know how to convert to neumas #{e}"
@@ -262,11 +262,11 @@ module Musa
262
262
 
263
263
  when Musa::Series::Serie
264
264
  { current_operation: :play,
265
- current_parameter: element.restart }
265
+ current_parameter: element.instance.restart }
266
266
 
267
267
  when Parallel
268
268
  { current_operation: :parallel_play,
269
- current_parameter: element.tap { |e| e.each(&:restart) } }
269
+ current_parameter: element.instance.tap { |e| e.each(&:restart) } }
270
270
 
271
271
  when Array
272
272
  { current_operation: :no_eval_play,
@@ -17,11 +17,11 @@ module Musa
17
17
  :position=,
18
18
  :event_handler
19
19
 
20
- def_delegators :@context, :position, :quantize_position, :logger, :debug
21
- def_delegators :@context, :with, :now, :at, :wait, :play, :play_timed, :every, :move
22
- def_delegators :@context, :everying, :playing, :moving
23
- def_delegators :@context, :launch, :on
24
- def_delegators :@context, :run
20
+ def_delegators :@dsl, :position, :quantize_position, :logger, :debug
21
+ def_delegators :@dsl, :with, :now, :at, :wait, :play, :play_timed, :every, :move
22
+ def_delegators :@dsl, :everying, :playing, :moving
23
+ def_delegators :@dsl, :launch, :on
24
+ def_delegators :@dsl, :run
25
25
 
26
26
  def initialize(beats_per_bar = nil,
27
27
  ticks_per_beat = nil,
@@ -37,7 +37,7 @@ module Musa
37
37
  do_error_log: do_error_log,
38
38
  log_position_format: log_position_format
39
39
 
40
- @context = DSLContext.new @sequencer
40
+ @dsl = DSLContext.new @sequencer
41
41
 
42
42
  with &block if block_given?
43
43
  end
@@ -5,209 +5,358 @@ using Musa::Extension::DeepCopy
5
5
 
6
6
  module Musa
7
7
  module Series
8
- module SerieOperations end
8
+ module Constructors; extend self; end
9
+ module Operations; end
9
10
 
10
- module SeriePrototyping
11
- def prototype?
12
- @is_instance ? false : true
13
- end
11
+ include Constructors
14
12
 
15
- def instance?
16
- @is_instance ? true : false
13
+ module Serie
14
+ def self.base
15
+ SerieImplementation
17
16
  end
18
17
 
19
- def prototype
20
- if @is_instance
21
- @instance_of || (@instance_of = self.clone.tap(&:_prototype!).mark_as_prototype!)
22
- else
23
- self
18
+ def self.with(source: false,
19
+ source_as: nil,
20
+ private_source: nil,
21
+ sources: false,
22
+ sources_as: nil,
23
+ private_sources: nil,
24
+ smart_block: false,
25
+ block: false,
26
+ block_as: nil)
27
+
28
+ source_as ||= :source
29
+ source_setter = (source_as.to_s + '=').to_sym
30
+
31
+ sources_as ||= :sources
32
+ sources_setter = (sources_as.to_s + '=').to_sym
33
+
34
+ block_as ||= :proc
35
+ block_setter = (block_as.to_s + '=').to_sym
36
+
37
+ Module.new do
38
+ include SerieImplementation
39
+
40
+ if source
41
+ define_method source_as do ||
42
+ @source
43
+ end
44
+
45
+ define_method source_setter do |serie|
46
+ raise ArgumentError, "New source should be a #{@get}" unless @source.nil? || @source.prototype? == serie&.prototype?
47
+
48
+ serie ||= Musa::Series::Constructors.NIL
49
+ @get = serie&.instance? ? :instance : :prototype
50
+ @source = serie
51
+ mark_regarding! @source
52
+ end
53
+
54
+ if private_source
55
+ private source_as
56
+ private source_setter
57
+ end
58
+ end
59
+
60
+ if sources
61
+ define_method sources_as do ||
62
+ @sources
63
+ end
64
+
65
+ 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"
75
+ end
76
+
77
+ mark_as! getter
78
+ end
79
+
80
+ if private_sources
81
+ private sources_as
82
+ private sources_setter
83
+ end
84
+ end
85
+
86
+ if smart_block
87
+ define_method block_as do |&block|
88
+ if block
89
+ @block = Musa::Extension::SmartProcBinder::SmartProcBinder.new(block)
90
+ else
91
+ @block.proc
92
+ end
93
+ end
94
+
95
+ define_method block_setter do |block|
96
+ @block = Musa::Extension::SmartProcBinder::SmartProcBinder.new(block)
97
+ end
98
+
99
+ elsif block
100
+ define_method block_as do |&block|
101
+ if block
102
+ @block = block
103
+ else
104
+ @block
105
+ end
106
+ end
107
+
108
+ define_method block_setter do |block|
109
+ @block = block
110
+ end
111
+ end
24
112
  end
25
113
  end
26
114
 
27
- alias_method :p, :prototype
115
+ module Prototyping
116
+ def prototype?
117
+ @is_instance ? false : true
118
+ end
28
119
 
29
- def instance
30
- if @is_instance
31
- self
32
- else
33
- clone(freeze: false).tap(&:_instance!).mark_as_instance!(self).tap(&:restart)
120
+ def instance?
121
+ @is_instance ? true : false
34
122
  end
35
- end
36
123
 
37
- alias_method :i, :instance
38
-
39
- # By default, if there is a @source attribute that contains the source of the serie, SeriePrototyping will
40
- # handle prototyping/instancing automatically.
41
- # If there is a @sources attribute with the eventual several sources, SeriePrototyping will handle them by
42
- # default.
43
- # If needed the subclasses can override this behaviour to accommodate to real subclass specificities.
44
- #
45
- protected def _prototype!
46
- @source = @source.prototype if @source
47
-
48
- if @sources
49
- if @sources.is_a?(Array)
50
- @sources = @sources.collect(&:prototype).freeze
51
- elsif @sources.is_a?(Hash)
52
- @sources = @sources.transform_values(&:prototype).freeze
124
+ 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
132
+
133
+ @instance_of
134
+ else
135
+ self
53
136
  end
54
137
  end
55
- end
56
138
 
57
- protected def _instance!
58
- @source = @source.instance if @source
139
+ alias_method :p, :prototype
59
140
 
60
- if @sources
61
- if @sources.is_a?(Array)
62
- @sources = @sources.collect(&:instance)
63
- elsif @sources.is_a?(Hash)
64
- @sources = @sources.transform_values(&:instance)
141
+ def instance
142
+ if @is_instance
143
+ self
144
+ else
145
+ new_instance = clone
146
+
147
+ new_instance._instance!
148
+ new_instance.mark_as_instance!(self)
149
+ new_instance.init if new_instance.respond_to?(:init)
150
+
151
+ new_instance
65
152
  end
66
153
  end
67
- end
68
154
 
69
- protected def mark_regarding!(source)
70
- if source.prototype?
71
- mark_as_prototype!
72
- else
73
- mark_as_instance!
155
+ alias_method :i, :instance
156
+
157
+ # By default, if there is a @source attribute that contains the source of the serie, SeriePrototyping will
158
+ # handle prototyping/instancing automatically.
159
+ # If there is a @sources attribute with the eventual several sources, SeriePrototyping will handle them by
160
+ # default.
161
+ # If needed the subclasses can override this behaviour to accommodate to real subclass specificities.
162
+ #
163
+ protected def _prototype!
164
+ @source = @source.prototype if @source
165
+
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
172
+ end
74
173
  end
75
- end
76
174
 
77
- protected def mark_as_prototype!
78
- @is_instance = nil
79
- freeze
80
- end
175
+ protected def _instance!
176
+ @source = @source.instance if @source
81
177
 
82
- protected def mark_as_instance!(prototype = nil)
83
- @instance_of = prototype
84
- @is_instance = true
85
- self
86
- end
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
184
+ end
185
+ end
87
186
 
88
- class PrototypingSerieError < RuntimeError
89
- def initialize(message = nil)
90
- message ||= 'This serie is a prototype serie: cannot be consumed. To consume the serie use an instance serie via .instance method'
91
- super message
187
+ protected def mark_as!(getter)
188
+ case getter
189
+ when :prototype
190
+ mark_as_prototype!
191
+ when :instance
192
+ mark_as_instance!
193
+ else
194
+ raise ArgumentError, "Only can be marked as :prototype or :instance"
195
+ end
92
196
  end
93
- end
94
- end
95
197
 
96
- module Serie
97
- include SeriePrototyping
98
- include SerieOperations
198
+ protected def mark_regarding!(source)
199
+ if source.prototype?
200
+ mark_as_prototype!
201
+ else
202
+ mark_as_instance!
203
+ end
204
+ end
99
205
 
100
- def restart
101
- raise PrototypingSerieError unless @is_instance
206
+ protected def mark_as_prototype!
207
+ @get = :prototype
102
208
 
103
- @_have_peeked_next_value = false
104
- @_peeked_next_value = nil
105
- @_have_current_value = false
106
- @_current_value = nil
209
+ @is_instance = nil
210
+ self
211
+ end
107
212
 
108
- _restart if respond_to? :_restart
213
+ protected def mark_as_instance!(prototype = nil)
214
+ @get = :instance
109
215
 
110
- self
216
+ @instance_of = prototype
217
+ @is_instance = true
218
+ self
219
+ end
220
+
221
+ class PrototypingError < RuntimeError
222
+ def initialize(message = nil)
223
+ message ||= 'This serie is a prototype serie: cannot be consumed. To consume the serie use an instance serie via .instance method'
224
+ super message
225
+ end
226
+ end
111
227
  end
112
228
 
113
- def next_value
114
- raise PrototypingSerieError unless @is_instance
229
+ module SerieImplementation
230
+ include Serie
231
+ include Prototyping
232
+ include Operations
115
233
 
116
- unless @_have_current_value && @_current_value.nil?
117
- if @_have_peeked_next_value
118
- @_have_peeked_next_value = false
119
- @_current_value = @_peeked_next_value
120
- else
121
- @_current_value = _next_value
234
+ def init
235
+ @_have_peeked_next_value = false
236
+ @_peeked_next_value = nil
237
+ @_have_current_value = false
238
+ @_current_value = nil
239
+
240
+ _init
241
+
242
+ self
243
+ end
244
+
245
+ private def _init; end
246
+
247
+ def restart(...)
248
+ raise PrototypingError unless @is_instance
249
+ init
250
+ _restart(...)
251
+
252
+ self
253
+ end
254
+
255
+ private def _restart; end
256
+
257
+ def next_value
258
+ raise PrototypingError unless @is_instance
259
+
260
+ unless @_have_current_value && @_current_value.nil?
261
+ if @_have_peeked_next_value
262
+ @_have_peeked_next_value = false
263
+ @_current_value = @_peeked_next_value
264
+ else
265
+ @_current_value = _next_value
266
+ end
122
267
  end
268
+
269
+ @_current_value
123
270
  end
124
271
 
125
- @_current_value
126
- end
272
+ private def _next_value; end
127
273
 
128
- alias_method :v, :next_value
274
+ alias_method :v, :next_value
129
275
 
130
- def peek_next_value
131
- raise PrototypingSerieError unless @is_instance
276
+ def peek_next_value
277
+ raise PrototypingError unless @is_instance
132
278
 
133
- if !@_have_peeked_next_value
134
- @_have_peeked_next_value = true
135
- @_peeked_next_value = _next_value
279
+ if !@_have_peeked_next_value
280
+ @_have_peeked_next_value = true
281
+ @_peeked_next_value = _next_value
282
+ end
283
+
284
+ @_peeked_next_value
136
285
  end
137
286
 
138
- @_peeked_next_value
139
- end
287
+ def current_value
288
+ raise PrototypingError unless @is_instance
140
289
 
141
- def current_value
142
- raise PrototypingSerieError unless @is_instance
290
+ @_current_value
291
+ end
143
292
 
144
- @_current_value
145
- end
293
+ def infinite?
294
+ @source&.infinite? || false
295
+ end
146
296
 
147
- def infinite?
148
- false
149
- end
297
+ def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
298
+ recursive ||= false
150
299
 
151
- def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
152
- recursive ||= false
300
+ dr = instance? if dr.nil?
153
301
 
154
- dr ||= instance?
302
+ duplicate = dr if duplicate.nil?
303
+ restart = dr if restart.nil?
155
304
 
156
- duplicate = dr if duplicate.nil?
157
- restart = dr if restart.nil?
305
+ raise 'Cannot convert to array an infinite serie' if infinite?
158
306
 
159
- raise 'Cannot convert to array an infinite serie' if infinite?
307
+ array = []
160
308
 
161
- array = []
309
+ serie = instance
162
310
 
163
- serie = instance
311
+ serie = serie.clone(deep: true) if duplicate
312
+ serie = serie.restart if restart
164
313
 
165
- serie = serie.clone(deep: true) if duplicate
166
- serie = serie.restart if restart
314
+ while value = serie.next_value
315
+ array << if recursive
316
+ process_for_to_a(value)
317
+ else
318
+ value
319
+ end
320
+ end
167
321
 
168
- while value = serie.next_value
169
- array << if recursive
170
- process_for_to_a(value)
171
- else
172
- value
173
- end
322
+ array
174
323
  end
175
324
 
176
- array
177
- end
325
+ alias_method :a, :to_a
178
326
 
179
- alias_method :a, :to_a
180
-
181
- def to_node(**attributes)
182
- Nodificator.to_node(self, **attributes)
183
- end
327
+ def to_node(**attributes)
328
+ Nodificator.to_node(self, **attributes)
329
+ end
184
330
 
185
- alias_method :node, :to_node
331
+ alias_method :node, :to_node
186
332
 
187
- class Nodificator
188
- extend Musa::GenerativeGrammar
333
+ class Nodificator
334
+ extend Musa::GenerativeGrammar
189
335
 
190
- def self.to_node(serie, **attributes)
191
- N(serie, **attributes)
336
+ def self.to_node(serie, **attributes)
337
+ N(serie, **attributes)
338
+ end
192
339
  end
193
- end
194
340
 
195
- private_constant :Nodificator
196
-
197
- private def process_for_to_a(value)
198
- case value
199
- when Serie
200
- value.to_a(recursive: true, restart: false, duplicate: false)
201
- when Array
202
- a = value.clone
203
- a.collect! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
204
- when Hash
205
- h = value.clone
206
- h.transform_values! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
207
- else
208
- value
341
+ 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
209
356
  end
210
357
  end
358
+
359
+ private_constant :SerieImplementation
211
360
  end
212
361
  end
213
362
  end