musa-dsl 0.22.6 → 0.23.0

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: 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