musa-dsl 0.14.16
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 +7 -0
- data/.gitignore +10 -0
- data/Gemfile +20 -0
- data/LICENSE.md +157 -0
- data/README.md +8 -0
- data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
- data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
- data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
- data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
- data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
- data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
- data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
- data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
- data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
- data/lib/musa-dsl/core-ext.rb +13 -0
- data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
- data/lib/musa-dsl/datasets/gdv.rb +499 -0
- data/lib/musa-dsl/datasets/pdv.rb +44 -0
- data/lib/musa-dsl/datasets.rb +5 -0
- data/lib/musa-dsl/generative/darwin.rb +145 -0
- data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
- data/lib/musa-dsl/generative/markov.rb +78 -0
- data/lib/musa-dsl/generative/rules.rb +282 -0
- data/lib/musa-dsl/generative/variatio.rb +331 -0
- data/lib/musa-dsl/generative.rb +5 -0
- data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
- data/lib/musa-dsl/midi/midi-voices.rb +274 -0
- data/lib/musa-dsl/midi.rb +2 -0
- data/lib/musa-dsl/music/chord-definition.rb +99 -0
- data/lib/musa-dsl/music/chord-definitions.rb +13 -0
- data/lib/musa-dsl/music/chords.rb +326 -0
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
- data/lib/musa-dsl/music/scales.rb +584 -0
- data/lib/musa-dsl/music.rb +6 -0
- data/lib/musa-dsl/neuma/neuma.rb +181 -0
- data/lib/musa-dsl/neuma.rb +1 -0
- data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
- data/lib/musa-dsl/neumalang.rb +3 -0
- data/lib/musa-dsl/repl/repl.rb +143 -0
- data/lib/musa-dsl/repl.rb +1 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
- data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
- data/lib/musa-dsl/sequencer.rb +1 -0
- data/lib/musa-dsl/series/base-series.rb +245 -0
- data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
- data/lib/musa-dsl/series/holder-serie.rb +87 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
- data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
- data/lib/musa-dsl/series/proxy-serie.rb +69 -0
- data/lib/musa-dsl/series/queue-serie.rb +94 -0
- data/lib/musa-dsl/series/series.rb +8 -0
- data/lib/musa-dsl/series.rb +1 -0
- data/lib/musa-dsl/transport/clock.rb +36 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
- data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
- data/lib/musa-dsl/transport/timer-clock.rb +102 -0
- data/lib/musa-dsl/transport/timer.rb +40 -0
- data/lib/musa-dsl/transport/transport.rb +137 -0
- data/lib/musa-dsl/transport.rb +9 -0
- data/lib/musa-dsl.rb +17 -0
- data/musa-dsl.gemspec +17 -0
- metadata +174 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Musa
|
4
|
+
class REPL
|
5
|
+
@@repl_mutex = Mutex.new
|
6
|
+
|
7
|
+
def initialize(binder, port: nil, redirect_stderr: nil, after_eval: nil)
|
8
|
+
port ||= 1327
|
9
|
+
redirect_stderr ||= false
|
10
|
+
|
11
|
+
@block_source = nil
|
12
|
+
|
13
|
+
if binder.receiver.respond_to?(:sequencer) &&
|
14
|
+
binder.receiver.sequencer.respond_to?(:on_block_error)
|
15
|
+
|
16
|
+
binder.receiver.sequencer.on_block_error do |e|
|
17
|
+
send_exception e
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@client_threads = []
|
22
|
+
|
23
|
+
@main_thread = Thread.new do
|
24
|
+
@server = TCPServer.new(port)
|
25
|
+
begin
|
26
|
+
while connection = @server.accept
|
27
|
+
@client_threads << Thread.new do
|
28
|
+
buffer = nil
|
29
|
+
|
30
|
+
begin
|
31
|
+
while line = connection.gets
|
32
|
+
line.chomp!
|
33
|
+
case line
|
34
|
+
when '#begin'
|
35
|
+
buffer = StringIO.new
|
36
|
+
when '#end'
|
37
|
+
@@repl_mutex.synchronize do
|
38
|
+
original_stdout = $stdout
|
39
|
+
original_stderr = $stderr
|
40
|
+
|
41
|
+
$stdout = connection
|
42
|
+
$stderr = connection if redirect_stderr
|
43
|
+
|
44
|
+
@block_source = buffer.string
|
45
|
+
|
46
|
+
begin
|
47
|
+
send_echo @block_source
|
48
|
+
|
49
|
+
binder.eval @block_source, "(repl)", 1
|
50
|
+
rescue StandardError, ScriptError => e
|
51
|
+
send_exception e
|
52
|
+
else
|
53
|
+
after_eval.call @block_source if after_eval
|
54
|
+
end
|
55
|
+
|
56
|
+
$stdout = original_stdout
|
57
|
+
$stderr = original_stderr if redirect_stderr
|
58
|
+
end
|
59
|
+
else
|
60
|
+
buffer.puts line
|
61
|
+
end
|
62
|
+
end
|
63
|
+
rescue IOError, Errno::ECONNRESET, Errno::EPIPE => e
|
64
|
+
warn e.message
|
65
|
+
end
|
66
|
+
|
67
|
+
connection.close
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rescue Errno::ECONNRESET, Errno::EPIPE => e
|
71
|
+
warn e.message
|
72
|
+
retry
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def stop
|
78
|
+
# TODO
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def send_echo(e)
|
84
|
+
send command: '//echo'
|
85
|
+
send content: e
|
86
|
+
send command: '//end'
|
87
|
+
end
|
88
|
+
|
89
|
+
def send_exception(e)
|
90
|
+
|
91
|
+
send command: '//error'
|
92
|
+
|
93
|
+
selected_backtrace_locations = e.backtrace_locations.select { |bt| bt.path == '(repl)' }
|
94
|
+
|
95
|
+
if e.is_a?(ScriptError)
|
96
|
+
send content: e.class.name
|
97
|
+
send command: '//backtrace'
|
98
|
+
send content: e.message
|
99
|
+
|
100
|
+
elsif selected_backtrace_locations.empty?
|
101
|
+
send content: "#{e.class.name}: #{e.message}"
|
102
|
+
send command: '//backtrace'
|
103
|
+
send content: e.backtrace_locations.first.to_s
|
104
|
+
|
105
|
+
else
|
106
|
+
lines = @block_source.split("\n")
|
107
|
+
|
108
|
+
lineno = selected_backtrace_locations.first.lineno
|
109
|
+
|
110
|
+
source_before = lines[lineno - 2] if lineno >= 2
|
111
|
+
source_error = lines[lineno - 1]
|
112
|
+
source_after = lines[lineno]
|
113
|
+
|
114
|
+
send content: '***'
|
115
|
+
send content: "[#{lineno - 1}] #{source_before}" if source_before
|
116
|
+
send content: "[#{lineno}] #{source_error} \t\t<<< ERROR !!!"
|
117
|
+
send content: "[#{lineno + 1}] #{source_after}" if source_after
|
118
|
+
send content: '***'
|
119
|
+
send content: e.class.name
|
120
|
+
send content: e.message
|
121
|
+
send command: '//backtrace'
|
122
|
+
selected_backtrace_locations.each do |bt|
|
123
|
+
send content: bt.to_s
|
124
|
+
end
|
125
|
+
end
|
126
|
+
send content: ' '
|
127
|
+
send command: '//end'
|
128
|
+
end
|
129
|
+
|
130
|
+
def send(content: nil, command: nil)
|
131
|
+
puts escape(content) if content
|
132
|
+
puts command if command
|
133
|
+
end
|
134
|
+
|
135
|
+
def escape(text)
|
136
|
+
if text.start_with? '//'
|
137
|
+
"//#{text}"
|
138
|
+
else
|
139
|
+
text
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'musa-dsl/repl/repl'
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
class Musa::BaseSequencer
|
4
|
+
class EventHandler
|
5
|
+
attr_reader :stdout, :stderr
|
6
|
+
attr_accessor :continue_parameters
|
7
|
+
|
8
|
+
@@counter = 0
|
9
|
+
|
10
|
+
def initialize(parent = nil, capture_stdout: nil)
|
11
|
+
capture_stdout ||= false
|
12
|
+
|
13
|
+
@id = (@@counter += 1)
|
14
|
+
|
15
|
+
@parent = parent
|
16
|
+
@handlers = {}
|
17
|
+
|
18
|
+
@stop = false
|
19
|
+
|
20
|
+
if capture_stdout || !parent
|
21
|
+
@stdout = $stdout
|
22
|
+
@stderr = $stderr
|
23
|
+
else
|
24
|
+
@stdout = @parent.stdout
|
25
|
+
@stderr = @parent.stderr
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop
|
30
|
+
@stop = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def stopped?
|
34
|
+
@stop
|
35
|
+
end
|
36
|
+
|
37
|
+
def pause
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
40
|
+
|
41
|
+
def continue
|
42
|
+
@paused = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def paused?
|
46
|
+
@paused
|
47
|
+
end
|
48
|
+
|
49
|
+
def on(event, name: nil, only_once: nil, &block)
|
50
|
+
only_once ||= false
|
51
|
+
|
52
|
+
@handlers[event] ||= {}
|
53
|
+
|
54
|
+
# TODO: add on_rescue: proc { |e| _rescue_block_error(e) } [this method is on Sequencer, not in EventHandler]
|
55
|
+
@handlers[event][name] = { block: KeyParametersProcedureBinder.new(block), only_once: only_once }
|
56
|
+
end
|
57
|
+
|
58
|
+
def launch(event, *value_parameters, **key_parameters)
|
59
|
+
_launch event, value_parameters, key_parameters
|
60
|
+
end
|
61
|
+
|
62
|
+
def _launch(event, value_parameters = nil, key_parameters = nil)
|
63
|
+
processed = false
|
64
|
+
|
65
|
+
if @handlers.key? event
|
66
|
+
@handlers[event].each do |name, handler|
|
67
|
+
handler[:block]._call value_parameters, key_parameters
|
68
|
+
@handlers[event].delete name if handler[:only_once]
|
69
|
+
processed = true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
@parent._launch event, value_parameters, key_parameters if @parent && !processed
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
"EventHandler #{id}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def id
|
81
|
+
if @parent
|
82
|
+
"#{@parent.id}.#{self.class.name.split('::').last}-#{@id}"
|
83
|
+
else
|
84
|
+
"#{self.class.name.split('::').last}-#{@id.to_s}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
alias to_s inspect
|
89
|
+
end
|
90
|
+
|
91
|
+
private_constant :EventHandler
|
92
|
+
|
93
|
+
class PlayControl < EventHandler
|
94
|
+
attr_reader :do_after
|
95
|
+
|
96
|
+
def initialize(parent, capture_stdout: nil, after: nil)
|
97
|
+
super parent, capture_stdout: capture_stdout
|
98
|
+
|
99
|
+
@do_after = []
|
100
|
+
|
101
|
+
self.after &after if after
|
102
|
+
end
|
103
|
+
|
104
|
+
def pause
|
105
|
+
@paused = true
|
106
|
+
end
|
107
|
+
|
108
|
+
def store_continuation(sequencer:, serie:, nl_context:, mode:, decoder:, play_eval:, mode_args:)
|
109
|
+
@continuation_sequencer = sequencer
|
110
|
+
@continuation_parameters = {
|
111
|
+
serie: serie,
|
112
|
+
control: self,
|
113
|
+
nl_context: nl_context,
|
114
|
+
mode: mode,
|
115
|
+
decoder: decoder,
|
116
|
+
play_eval: play_eval,
|
117
|
+
mode_args: mode_args
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def continue
|
122
|
+
super
|
123
|
+
@continuation_sequencer.continuation_play(@continuation_parameters) if @continuation_sequencer
|
124
|
+
end
|
125
|
+
|
126
|
+
def after(_bars = nil, &block)
|
127
|
+
# TODO implementar parámetro _bars (?)
|
128
|
+
@do_after << block
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private_constant :PlayControl
|
133
|
+
|
134
|
+
class EveryControl < EventHandler
|
135
|
+
attr_reader :duration_value, :till_value, :condition_block, :do_on_stop, :do_after
|
136
|
+
|
137
|
+
attr_accessor :_start
|
138
|
+
|
139
|
+
def initialize(parent, capture_stdout: nil, duration: nil, till: nil, condition: nil, on_stop: nil, after_bars: nil, after: nil)
|
140
|
+
super parent, capture_stdout: capture_stdout
|
141
|
+
|
142
|
+
@duration_value = duration
|
143
|
+
@till_value = till
|
144
|
+
@condition_block = condition
|
145
|
+
|
146
|
+
@do_on_stop = []
|
147
|
+
@do_after = []
|
148
|
+
|
149
|
+
@do_on_stop << on_stop if on_stop
|
150
|
+
|
151
|
+
self.after after_bars, &after if after
|
152
|
+
end
|
153
|
+
|
154
|
+
def duration(value)
|
155
|
+
@duration_value = value.rationalize
|
156
|
+
end
|
157
|
+
|
158
|
+
def till(value)
|
159
|
+
@till_value = value.rationalize
|
160
|
+
end
|
161
|
+
|
162
|
+
def condition(&block)
|
163
|
+
@condition_block = block
|
164
|
+
end
|
165
|
+
|
166
|
+
def on_stop(&block)
|
167
|
+
@do_on_stop << block
|
168
|
+
end
|
169
|
+
|
170
|
+
def after(bars = nil, &block)
|
171
|
+
bars ||= 0
|
172
|
+
@do_after << { bars: bars.rationalize, block: block }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
private_constant :EveryControl
|
177
|
+
|
178
|
+
class MoveControl
|
179
|
+
extend Forwardable
|
180
|
+
|
181
|
+
def initialize(every_control)
|
182
|
+
@every_control = every_control
|
183
|
+
end
|
184
|
+
|
185
|
+
def_delegators :@every_control, :stdout, :stderr, :on_stop, :after, :on, :launch, :stop
|
186
|
+
end
|
187
|
+
|
188
|
+
private_constant :MoveControl
|
189
|
+
end
|
@@ -0,0 +1,354 @@
|
|
1
|
+
class Musa::BaseSequencer
|
2
|
+
class PlayEval
|
3
|
+
def self.create(mode, block_procedure_binder, decoder, nl_context)
|
4
|
+
case mode
|
5
|
+
when :at
|
6
|
+
AtModePlayEval.new block_procedure_binder
|
7
|
+
when :wait
|
8
|
+
WaitModePlayEval.new block_procedure_binder
|
9
|
+
when :neumalang
|
10
|
+
NeumalangModePlayEval.new block_procedure_binder, decoder, nl_context
|
11
|
+
else
|
12
|
+
raise ArgumentError, "Mode #{mode} not allowed"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :block_procedure_binder
|
17
|
+
|
18
|
+
def subcontext
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def eval_element(_element)
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_operation(_element)
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private_constant :PlayEval
|
32
|
+
|
33
|
+
class AtModePlayEval < PlayEval
|
34
|
+
def initialize(block_procedure_binder)
|
35
|
+
@block_procedure_binder = block_procedure_binder
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_operation(element)
|
39
|
+
value = nil
|
40
|
+
|
41
|
+
if element.is_a? Hash
|
42
|
+
value = {
|
43
|
+
current_operation: :block,
|
44
|
+
current_block: @block_procedure_binder,
|
45
|
+
current_parameter: element,
|
46
|
+
continue_operation: :at,
|
47
|
+
continue_parameter: element[:at]
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
value ||= {
|
52
|
+
current_operation: @block_procedure_binder,
|
53
|
+
current_parameter: element,
|
54
|
+
continue_operation: :at,
|
55
|
+
continue_parameter: position
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private_constant :AtModePlayEval
|
61
|
+
|
62
|
+
class WaitModePlayEval < PlayEval
|
63
|
+
def initialize(block_procedure_binder)
|
64
|
+
@block_procedure_binder = block_procedure_binder
|
65
|
+
end
|
66
|
+
|
67
|
+
def run_operation(element)
|
68
|
+
value = nil
|
69
|
+
|
70
|
+
if element.is_a? Hash
|
71
|
+
if element.key? :duration
|
72
|
+
value = {
|
73
|
+
current_operation: :block,
|
74
|
+
current_block: @block_procedure_binder,
|
75
|
+
current_parameter: element,
|
76
|
+
continue_operation: :wait,
|
77
|
+
continue_parameter: element[:duration]
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
if element.key? :wait_event
|
82
|
+
value = {
|
83
|
+
current_operation: :block,
|
84
|
+
current_block: @block_procedure_binder,
|
85
|
+
current_parameter: element,
|
86
|
+
continue_operation: :on,
|
87
|
+
continue_parameter: element[:wait_event]
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
value ||= {
|
93
|
+
current_operation: :block,
|
94
|
+
current_block: @block_procedure_binder,
|
95
|
+
current_parameter: element,
|
96
|
+
continue_operation: :now
|
97
|
+
}
|
98
|
+
|
99
|
+
value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private_constant :WaitModePlayEval
|
104
|
+
|
105
|
+
class NeumalangModePlayEval < PlayEval
|
106
|
+
module Parallel end
|
107
|
+
|
108
|
+
@@id = 0
|
109
|
+
|
110
|
+
attr_reader :nl_context
|
111
|
+
attr_reader :block_procedure_binder
|
112
|
+
|
113
|
+
def initialize(block_procedure_binder, decoder, nl_context, parent: nil)
|
114
|
+
@id = @@id += 1
|
115
|
+
@parent = parent
|
116
|
+
|
117
|
+
@block_procedure_binder = block_procedure_binder
|
118
|
+
@decoder = decoder
|
119
|
+
@nl_context = nl_context
|
120
|
+
@nl_context ||= Object.new
|
121
|
+
end
|
122
|
+
|
123
|
+
def subcontext
|
124
|
+
NeumalangModePlayEval.new @block_procedure_binder, @decoder.subcontext, @nl_context, parent: self
|
125
|
+
end
|
126
|
+
|
127
|
+
def eval_element(element)
|
128
|
+
if element.is_a? Musa::Neumalang::Dataset
|
129
|
+
element
|
130
|
+
else
|
131
|
+
case element[:kind]
|
132
|
+
when :serie then eval_serie element[:serie]
|
133
|
+
when :parallel then eval_parallel element[:parallel]
|
134
|
+
when :assign_to then eval_assign_to element[:assign_to], element[:assign_value]
|
135
|
+
when :use_variable then eval_use_variable element[:use_variable]
|
136
|
+
when :command then eval_command element[:command], element[:value_parameters], element[:key_parameters]
|
137
|
+
when :value then eval_value element[:value]
|
138
|
+
when :neuma then eval_neuma element[:neuma]
|
139
|
+
when :call_methods then eval_call_methods element[:on], element[:call_methods]
|
140
|
+
when :indirection then eval_indirection element[:indirection]
|
141
|
+
when :reference then eval_reference element[:reference]
|
142
|
+
when :event then element
|
143
|
+
else
|
144
|
+
raise ArgumentError, "eval_element: don't know how to process #{element}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def eval_value(value)
|
150
|
+
value
|
151
|
+
end
|
152
|
+
|
153
|
+
def eval_neuma(neuma)
|
154
|
+
@decoder.decode neuma
|
155
|
+
end
|
156
|
+
|
157
|
+
def eval_serie(serie)
|
158
|
+
context = subcontext
|
159
|
+
serie.instance.eval(on_restart: proc { context = subcontext }) { |e| context.eval_element e }
|
160
|
+
end
|
161
|
+
|
162
|
+
def eval_parallel(series)
|
163
|
+
context = subcontext
|
164
|
+
series.collect { |s| context.eval_serie s[:serie] }.extend Parallel
|
165
|
+
end
|
166
|
+
|
167
|
+
def eval_assign_to(variable_names, value)
|
168
|
+
_value = nil
|
169
|
+
|
170
|
+
variable_names.each do |var_name|
|
171
|
+
@nl_context.instance_variable_set var_name, _value = subcontext.eval_element(value)
|
172
|
+
end
|
173
|
+
|
174
|
+
_value
|
175
|
+
end
|
176
|
+
|
177
|
+
def eval_use_variable(variable_name)
|
178
|
+
if @nl_context.instance_variable_defined? variable_name
|
179
|
+
@nl_context.instance_variable_get(variable_name)
|
180
|
+
else
|
181
|
+
raise NameError, "Variable #{variable_name} is not defined in context #{@nl_context}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def eval_command(block, value_parameters, key_parameters)
|
186
|
+
_value_parameters = value_parameters.collect { |e| subcontext.eval_element(e) } if value_parameters
|
187
|
+
_key_parameters = key_parameters.collect { |k, e| [k, subcontext.eval_element(e)] }.to_h if key_parameters
|
188
|
+
|
189
|
+
@nl_context._as_context_run block, _value_parameters, _key_parameters
|
190
|
+
end
|
191
|
+
|
192
|
+
def eval_call_methods(on, call_methods)
|
193
|
+
play_eval = subcontext
|
194
|
+
|
195
|
+
value = play_eval.eval_element on
|
196
|
+
|
197
|
+
if value.is_a? Parallel
|
198
|
+
value.collect do |_value|
|
199
|
+
call_methods.each do |methd|
|
200
|
+
value_parameters = methd[:value_parameters].collect { |e| play_eval.subcontext.eval_element(e) } if methd[:value_parameters]
|
201
|
+
key_parameters = methd[:key_parameters].collect { |k, e| [k, play_eval.subcontext.eval_element(e)] }.to_h if methd[:key_parameters]
|
202
|
+
|
203
|
+
_value = _value._send_nice methd[:method], value_parameters, key_parameters
|
204
|
+
end
|
205
|
+
|
206
|
+
_value
|
207
|
+
end.extend Parallel
|
208
|
+
else
|
209
|
+
call_methods.each do |methd|
|
210
|
+
value_parameters = methd[:value_parameters].collect { |e| play_eval.subcontext.eval_element(e) } if methd[:value_parameters]
|
211
|
+
key_parameters = methd[:key_parameters].collect { |k, e| [k, play_eval.subcontext.eval_element(e)] }.to_h if methd[:key_parameters]
|
212
|
+
|
213
|
+
value = value._send_nice methd[:method], value_parameters, key_parameters
|
214
|
+
end
|
215
|
+
|
216
|
+
value
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def eval_reference(element)
|
221
|
+
if element.is_a?(Hash) && element.key?(:kind)
|
222
|
+
case element[:kind]
|
223
|
+
when :command
|
224
|
+
element[:command]
|
225
|
+
else
|
226
|
+
raise ArgumentError, "eval_reference(&): don't know how to process element #{element}"
|
227
|
+
end
|
228
|
+
else
|
229
|
+
raise ArgumentError, "eval_reference(&): don't know how to process element #{element}"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def run_operation(element)
|
234
|
+
case element
|
235
|
+
when nil
|
236
|
+
{ current_operation: :none,
|
237
|
+
continue_operation: :now }
|
238
|
+
|
239
|
+
when Musa::Neumalang::Dataset
|
240
|
+
{ current_operation: :block,
|
241
|
+
current_parameter: element,
|
242
|
+
continue_operation: :wait,
|
243
|
+
continue_parameter: element[:duration] }
|
244
|
+
|
245
|
+
when Musa::Serie
|
246
|
+
{ current_operation: :play,
|
247
|
+
current_parameter: element.restart }
|
248
|
+
|
249
|
+
when Parallel
|
250
|
+
{ current_operation: :parallel_play,
|
251
|
+
current_parameter: element.tap { |e| e.each(&:restart) } }
|
252
|
+
|
253
|
+
when Array
|
254
|
+
{ current_operation: :no_eval_play,
|
255
|
+
current_parameter: S(*element) }
|
256
|
+
else
|
257
|
+
case element[:kind]
|
258
|
+
when :value
|
259
|
+
|
260
|
+
_value = eval_value element[:value]
|
261
|
+
|
262
|
+
if _value.is_a?(Hash) && _value.key?(:duration)
|
263
|
+
{ current_operation: :block,
|
264
|
+
current_parameter: _value,
|
265
|
+
continue_operation: :wait,
|
266
|
+
continue_parameter: _value[:duration] }
|
267
|
+
else
|
268
|
+
{ current_operation: :block,
|
269
|
+
current_parameter: _value,
|
270
|
+
continue_operation: :now }
|
271
|
+
end
|
272
|
+
|
273
|
+
when :neuma
|
274
|
+
_value = eval_neuma element[:neuma]
|
275
|
+
|
276
|
+
if _value.is_a?(Array)
|
277
|
+
{ current_operation: :no_eval_play,
|
278
|
+
current_parameter: S(*_value) }
|
279
|
+
else
|
280
|
+
{ current_operation: :block,
|
281
|
+
current_parameter: _value,
|
282
|
+
continue_operation: :wait,
|
283
|
+
continue_parameter: _value[:duration] }
|
284
|
+
end
|
285
|
+
|
286
|
+
when :serie
|
287
|
+
|
288
|
+
{ current_operation: :play,
|
289
|
+
current_parameter: eval_serie(element[:serie]) }
|
290
|
+
|
291
|
+
when :parallel
|
292
|
+
|
293
|
+
{ current_operation: :parallel_play,
|
294
|
+
current_parameter: eval_parallel(element[:parallel]) }
|
295
|
+
|
296
|
+
when :assign_to
|
297
|
+
|
298
|
+
eval_assign_to element[:assign_to], element[:assign_value]
|
299
|
+
|
300
|
+
{ current_operation: :none,
|
301
|
+
continue_operation: :now }
|
302
|
+
|
303
|
+
when :use_variable
|
304
|
+
|
305
|
+
run_operation eval_use_variable(element[:use_variable])
|
306
|
+
|
307
|
+
when :event
|
308
|
+
|
309
|
+
value_parameters = key_parameters = nil
|
310
|
+
|
311
|
+
value_parameters = element[:value_parameters].collect { |e| subcontext.eval_element(e) } if element[:value_parameters]
|
312
|
+
key_parameters = element[:key_parameters].collect { |k, e| [k, subcontext.eval_element(e)] }.to_h if element[:key_parameters]
|
313
|
+
|
314
|
+
{ current_operation: :event,
|
315
|
+
current_event: element[:event],
|
316
|
+
current_value_parameters: value_parameters,
|
317
|
+
current_key_parameters: key_parameters,
|
318
|
+
continue_operation: :now }
|
319
|
+
|
320
|
+
when :command
|
321
|
+
|
322
|
+
run_operation eval_command(element[:command], element[:value_parameters], element[:key_parameters])
|
323
|
+
|
324
|
+
when :call_methods
|
325
|
+
|
326
|
+
run_operation eval_call_methods(element[:on], element[:call_methods])
|
327
|
+
|
328
|
+
when :reference
|
329
|
+
|
330
|
+
run_operation eval_reference(element[:reference])
|
331
|
+
|
332
|
+
else
|
333
|
+
raise ArgumentError, "run_operation: don't know how to process #{element}"
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def inspect
|
339
|
+
"NeumalangModePlayEval #{id} #{@decoder}"
|
340
|
+
end
|
341
|
+
|
342
|
+
def id
|
343
|
+
if @parent
|
344
|
+
"#{@parent.id}.#{@id}"
|
345
|
+
else
|
346
|
+
@id.to_s
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
alias to_s inspect
|
351
|
+
end
|
352
|
+
|
353
|
+
private_constant :NeumalangModePlayEval
|
354
|
+
end
|