musa-dsl 0.14.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +20 -0
  4. data/LICENSE.md +157 -0
  5. data/README.md +8 -0
  6. data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
  7. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
  8. data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
  9. data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
  10. data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
  11. data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
  12. data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
  13. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
  14. data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
  15. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
  16. data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
  17. data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
  18. data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
  19. data/lib/musa-dsl/core-ext.rb +13 -0
  20. data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
  21. data/lib/musa-dsl/datasets/gdv.rb +499 -0
  22. data/lib/musa-dsl/datasets/pdv.rb +44 -0
  23. data/lib/musa-dsl/datasets.rb +5 -0
  24. data/lib/musa-dsl/generative/darwin.rb +145 -0
  25. data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
  26. data/lib/musa-dsl/generative/markov.rb +78 -0
  27. data/lib/musa-dsl/generative/rules.rb +282 -0
  28. data/lib/musa-dsl/generative/variatio.rb +331 -0
  29. data/lib/musa-dsl/generative.rb +5 -0
  30. data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
  31. data/lib/musa-dsl/midi/midi-voices.rb +274 -0
  32. data/lib/musa-dsl/midi.rb +2 -0
  33. data/lib/musa-dsl/music/chord-definition.rb +99 -0
  34. data/lib/musa-dsl/music/chord-definitions.rb +13 -0
  35. data/lib/musa-dsl/music/chords.rb +326 -0
  36. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
  37. data/lib/musa-dsl/music/scales.rb +584 -0
  38. data/lib/musa-dsl/music.rb +6 -0
  39. data/lib/musa-dsl/neuma/neuma.rb +181 -0
  40. data/lib/musa-dsl/neuma.rb +1 -0
  41. data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
  42. data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
  43. data/lib/musa-dsl/neumalang.rb +3 -0
  44. data/lib/musa-dsl/repl/repl.rb +143 -0
  45. data/lib/musa-dsl/repl.rb +1 -0
  46. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
  47. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
  48. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
  49. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
  50. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
  51. data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
  52. data/lib/musa-dsl/sequencer.rb +1 -0
  53. data/lib/musa-dsl/series/base-series.rb +245 -0
  54. data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
  55. data/lib/musa-dsl/series/holder-serie.rb +87 -0
  56. data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
  57. data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
  58. data/lib/musa-dsl/series/proxy-serie.rb +69 -0
  59. data/lib/musa-dsl/series/queue-serie.rb +94 -0
  60. data/lib/musa-dsl/series/series.rb +8 -0
  61. data/lib/musa-dsl/series.rb +1 -0
  62. data/lib/musa-dsl/transport/clock.rb +36 -0
  63. data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
  64. data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
  65. data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
  66. data/lib/musa-dsl/transport/timer-clock.rb +102 -0
  67. data/lib/musa-dsl/transport/timer.rb +40 -0
  68. data/lib/musa-dsl/transport/transport.rb +137 -0
  69. data/lib/musa-dsl/transport.rb +9 -0
  70. data/lib/musa-dsl.rb +17 -0
  71. data/musa-dsl.gemspec +17 -0
  72. metadata +174 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 233adb825ed72badf41723781c9ca578b1ba7a38f01191376207fa44d0bfbe84
4
+ data.tar.gz: cb6e9d1557645c9cef7bc1e963438c54c7d9c0ffb3b8dac8cc6f45619fdd1616
5
+ SHA512:
6
+ metadata.gz: dc451b441bfdf0a9814f2a4cdd88fb3a991ec1d5edd35eeed09fbe72735d8615da33645995d35a842c392d0810db8b9d166d1c8eae43c0c000687bff0824a989
7
+ data.tar.gz: d094f68c240f775035cbe4dc2aeed3086368826e99af91cbe9e68a3ef9f19c3dd95f328f71d63e97b457ff7f647b1c02d750793dc8bbcf3c1dfef842cb59cc01
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ **/.DS_Store
2
+ *.gem
3
+ .bundle
4
+ .rspec
5
+ .idea
6
+ Gemfile.lock
7
+ bin
8
+ *.mindnode
9
+
10
+
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :neuma do
4
+ gem 'citrus', '~> 3.0.0'
5
+
6
+ end
7
+
8
+ group :transport do
9
+ gem 'midi-message', '~> 0.4', '>= 0.4.9'
10
+ gem 'midi-nibbler', '~> 0.2', '>= 0.2.4'
11
+ end
12
+
13
+ group :test do
14
+ gem 'rspec', '~> 3.0'
15
+ gem 'descriptive-statistics'
16
+ end
17
+
18
+ group :documentation do
19
+ gem 'rdoc'
20
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,157 @@
1
+ ### GNU LESSER GENERAL PUBLIC LICENSE
2
+
3
+ Version 3, 29 June 2007
4
+
5
+ Copyright (C) 2007 Free Software Foundation, Inc.
6
+ <https://fsf.org/>
7
+
8
+ Everyone is permitted to copy and distribute verbatim copies of this
9
+ license document, but changing it is not allowed.
10
+
11
+ This version of the GNU Lesser General Public License incorporates the
12
+ terms and conditions of version 3 of the GNU General Public License,
13
+ supplemented by the additional permissions listed below.
14
+
15
+ #### 0. Additional Definitions.
16
+
17
+ As used herein, "this License" refers to version 3 of the GNU Lesser
18
+ General Public License, and the "GNU GPL" refers to version 3 of the
19
+ GNU General Public License.
20
+
21
+ "The Library" refers to a covered work governed by this License, other
22
+ than an Application or a Combined Work as defined below.
23
+
24
+ An "Application" is any work that makes use of an interface provided
25
+ by the Library, but which is not otherwise based on the Library.
26
+ Defining a subclass of a class defined by the Library is deemed a mode
27
+ of using an interface provided by the Library.
28
+
29
+ A "Combined Work" is a work produced by combining or linking an
30
+ Application with the Library. The particular version of the Library
31
+ with which the Combined Work was made is also called the "Linked
32
+ Version".
33
+
34
+ The "Minimal Corresponding Source" for a Combined Work means the
35
+ Corresponding Source for the Combined Work, excluding any source code
36
+ for portions of the Combined Work that, considered in isolation, are
37
+ based on the Application, and not on the Linked Version.
38
+
39
+ The "Corresponding Application Code" for a Combined Work means the
40
+ object code and/or source code for the Application, including any data
41
+ and utility programs needed for reproducing the Combined Work from the
42
+ Application, but excluding the System Libraries of the Combined Work.
43
+
44
+ #### 1. Exception to Section 3 of the GNU GPL.
45
+
46
+ You may convey a covered work under sections 3 and 4 of this License
47
+ without being bound by section 3 of the GNU GPL.
48
+
49
+ #### 2. Conveying Modified Versions.
50
+
51
+ If you modify a copy of the Library, and, in your modifications, a
52
+ facility refers to a function or data to be supplied by an Application
53
+ that uses the facility (other than as an argument passed when the
54
+ facility is invoked), then you may convey a copy of the modified
55
+ version:
56
+
57
+ - a) under this License, provided that you make a good faith effort
58
+ to ensure that, in the event an Application does not supply the
59
+ function or data, the facility still operates, and performs
60
+ whatever part of its purpose remains meaningful, or
61
+ - b) under the GNU GPL, with none of the additional permissions of
62
+ this License applicable to that copy.
63
+
64
+ #### 3. Object Code Incorporating Material from Library Header Files.
65
+
66
+ The object code form of an Application may incorporate material from a
67
+ header file that is part of the Library. You may convey such object
68
+ code under terms of your choice, provided that, if the incorporated
69
+ material is not limited to numerical parameters, data structure
70
+ layouts and accessors, or small macros, inline functions and templates
71
+ (ten or fewer lines in length), you do both of the following:
72
+
73
+ - a) Give prominent notice with each copy of the object code that
74
+ the Library is used in it and that the Library and its use are
75
+ covered by this License.
76
+ - b) Accompany the object code with a copy of the GNU GPL and this
77
+ license document.
78
+
79
+ #### 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that, taken
82
+ together, effectively do not restrict modification of the portions of
83
+ the Library contained in the Combined Work and reverse engineering for
84
+ debugging such modifications, if you also do each of the following:
85
+
86
+ - a) Give prominent notice with each copy of the Combined Work that
87
+ the Library is used in it and that the Library and its use are
88
+ covered by this License.
89
+ - b) Accompany the Combined Work with a copy of the GNU GPL and this
90
+ license document.
91
+ - c) For a Combined Work that displays copyright notices during
92
+ execution, include the copyright notice for the Library among
93
+ these notices, as well as a reference directing the user to the
94
+ copies of the GNU GPL and this license document.
95
+ - d) Do one of the following:
96
+ - 0) Convey the Minimal Corresponding Source under the terms of
97
+ this License, and the Corresponding Application Code in a form
98
+ suitable for, and under terms that permit, the user to
99
+ recombine or relink the Application with a modified version of
100
+ the Linked Version to produce a modified Combined Work, in the
101
+ manner specified by section 6 of the GNU GPL for conveying
102
+ Corresponding Source.
103
+ - 1) Use a suitable shared library mechanism for linking with
104
+ the Library. A suitable mechanism is one that (a) uses at run
105
+ time a copy of the Library already present on the user's
106
+ computer system, and (b) will operate properly with a modified
107
+ version of the Library that is interface-compatible with the
108
+ Linked Version.
109
+ - e) Provide Installation Information, but only if you would
110
+ otherwise be required to provide such information under section 6
111
+ of the GNU GPL, and only to the extent that such information is
112
+ necessary to install and execute a modified version of the
113
+ Combined Work produced by recombining or relinking the Application
114
+ with a modified version of the Linked Version. (If you use option
115
+ 4d0, the Installation Information must accompany the Minimal
116
+ Corresponding Source and Corresponding Application Code. If you
117
+ use option 4d1, you must provide the Installation Information in
118
+ the manner specified by section 6 of the GNU GPL for conveying
119
+ Corresponding Source.)
120
+
121
+ #### 5. Combined Libraries.
122
+
123
+ You may place library facilities that are a work based on the Library
124
+ side by side in a single library together with other library
125
+ facilities that are not Applications and are not covered by this
126
+ License, and convey such a combined library under terms of your
127
+ choice, if you do both of the following:
128
+
129
+ - a) Accompany the combined library with a copy of the same work
130
+ based on the Library, uncombined with any other library
131
+ facilities, conveyed under the terms of this License.
132
+ - b) Give prominent notice with the combined library that part of it
133
+ is a work based on the Library, and explaining where to find the
134
+ accompanying uncombined form of the same work.
135
+
136
+ #### 6. Revised Versions of the GNU Lesser General Public License.
137
+
138
+ The Free Software Foundation may publish revised and/or new versions
139
+ of the GNU Lesser General Public License from time to time. Such new
140
+ versions will be similar in spirit to the present version, but may
141
+ differ in detail to address new problems or concerns.
142
+
143
+ Each version is given a distinguishing version number. If the Library
144
+ as you received it specifies that a certain numbered version of the
145
+ GNU Lesser General Public License "or any later version" applies to
146
+ it, you have the option of following the terms and conditions either
147
+ of that published version or of any later version published by the
148
+ Free Software Foundation. If the Library as you received it does not
149
+ specify a version number of the GNU Lesser General Public License, you
150
+ may choose any version of the GNU Lesser General Public License ever
151
+ published by the Free Software Foundation.
152
+
153
+ If the Library as you received it specifies that a proxy can decide
154
+ whether future versions of the GNU Lesser General Public License shall
155
+ apply, that proxy's public statement of acceptance of any version is
156
+ permanent authorization for you to choose that version for the
157
+ Library.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Musa-DSL
2
+
3
+ Work in progress.
4
+
5
+ A programming language DSL based on Ruby for musical composition.
6
+ Emphasizes the creation of complex temporal structures independently of the audio rendering engine.
7
+
8
+ Some works can be listened on [yeste.studio](https://soundcloud.com/yeste-studio) Soundcloud.
@@ -0,0 +1,18 @@
1
+ # TODO hacer que *_nice permitar recibir atributos para indicar cómo se quieren procesar los parámetros (haciendo *, **, o sin hacer nada)
2
+
3
+ class Array
4
+ def apply method_name, source
5
+
6
+ source = [source] unless source.is_a? Array
7
+
8
+ self.each_with_index do |o, i|
9
+ o.send method_name, source[i % source.length]
10
+ end
11
+ end
12
+
13
+ def get method_name
14
+ self.collect { |o| o.send method_name }
15
+ end
16
+ end
17
+
18
+
@@ -0,0 +1,29 @@
1
+ class Array
2
+ def arrayfy
3
+ self
4
+ end
5
+
6
+ def repeat_to_size(new_size)
7
+ pos = -1
8
+ new_size -= 1
9
+
10
+ new_array = clone
11
+ new_array << self[(pos += 1) % size] while (pos + size) < new_size
12
+
13
+ new_array
14
+ end
15
+
16
+ def explode_ranges
17
+ array = []
18
+
19
+ each do |element|
20
+ if element.is_a? Range
21
+ element.to_a.each { |element| array << element }
22
+ else
23
+ array << element
24
+ end
25
+ end
26
+
27
+ array
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ require 'musa-dsl/series'
2
+ require 'musa-dsl/neumalang'
3
+
4
+ class Array
5
+ def to_neumas
6
+ if length > 1
7
+ MERGE(*collect { |e| convert_to_neumas(e) })
8
+ else
9
+ convert_to_neumas(first)
10
+ end
11
+ end
12
+
13
+ alias_method :neumas, :to_neumas
14
+ alias_method :n, :to_neumas
15
+
16
+ private
17
+
18
+ def convert_to_neumas(e)
19
+ case e
20
+ when Musa::Neumalang::Neumas then e
21
+ when Musa::Neumalang::Neuma::Parallel then _SE([e], extends: Musa::Neumalang::Neumas)
22
+ when String then e.to_neumas
23
+ else
24
+ raise ArgumentError, "Don't know how to convert to neumas #{e}"
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,20 @@
1
+ require 'musa-dsl/series'
2
+
3
+ class Array
4
+ def to_serie(of_series: nil, recursive: nil)
5
+ of_series ||= false
6
+ recursive ||= false
7
+
8
+ raise ArgumentError, 'Cannot convert to serie of_series and recursive simultaneously' if recursive && of_series
9
+
10
+ if recursive
11
+ S(*(collect { |_| _.is_a?(Array) ? _.to_serie(recursive: true) : _ }))
12
+ elsif of_series
13
+ S(*(collect { |_| S(*_) }))
14
+ else
15
+ S(*self)
16
+ end
17
+ end
18
+
19
+ alias_method :s, :to_serie
20
+ end
@@ -0,0 +1,15 @@
1
+ class Object
2
+ def arrayfy
3
+ if nil?
4
+ []
5
+ else
6
+ [self]
7
+ end
8
+ end
9
+ end
10
+
11
+ class Array
12
+ def arrayfy
13
+ self
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ # TODO: hacer que *_nice permitar recibir atributos para indicar cómo se quieren procesar los parámetros (haciendo *, **, o sin hacer nada)
2
+
3
+ class Object
4
+ def as_context_run(procedure, *list_or_key_args, **key_args)
5
+ _as_context_run procedure, list_or_key_args, key_args
6
+ end
7
+
8
+ def _as_context_run(procedure, list_or_key_args = nil, key_args = nil)
9
+ if !list_or_key_args.nil? && list_or_key_args.is_a?(Hash)
10
+ key_args = list_or_key_args
11
+ list_or_key_args = nil
12
+ end
13
+
14
+ if procedure.lambda?
15
+ if !list_or_key_args.nil? && !list_or_key_args.empty?
16
+ if !key_args.nil? && !key_args.empty?
17
+ procedure.call *list_or_key_args, **key_args
18
+ else
19
+ procedure.call *list_or_key_args
20
+ end
21
+ else
22
+ if !key_args.nil? && !key_args.empty?
23
+ procedure.call **key_args
24
+ else
25
+ procedure.call
26
+ end
27
+ end
28
+ else
29
+ if !list_or_key_args.nil? && !list_or_key_args.empty?
30
+ if !key_args.nil? && !key_args.empty?
31
+ instance_exec *list_or_key_args, **key_args, &procedure
32
+ else
33
+ instance_exec *list_or_key_args, &procedure
34
+ end
35
+ else
36
+ if !key_args.nil? && !key_args.empty?
37
+ instance_exec **key_args, &procedure
38
+ else
39
+ instance_eval &procedure
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,134 @@
1
+ # Based on https://github.com/adamluzsi/duplicate.rb/blob/master/lib/duplicate.rb
2
+ # Modifications by JSY
3
+
4
+ module Duplicate
5
+ extend self
6
+
7
+ def duplicate(object)
8
+ register = {}
9
+
10
+ _dup(register, object)
11
+ end
12
+
13
+ protected
14
+
15
+ def registered(object, register)
16
+ register[object.__id__]
17
+ end
18
+
19
+ def register_duplication(register, object, duplicate)
20
+ register[object.__id__] = duplicate
21
+ duplicate
22
+ end
23
+
24
+ def _dup(register, object)
25
+ return registered(object, register) if registered(object, register)
26
+ return register_duplication(register, object, object) unless identifiable?(object)
27
+
28
+ case object
29
+
30
+ when Array
31
+ dup_array(register, object)
32
+
33
+ when Hash
34
+ dup_hash(register, object)
35
+
36
+ when Range
37
+ dup_range(register, object)
38
+
39
+ when Struct
40
+ dup_struct(register, object)
41
+
42
+ when NilClass, Symbol, Numeric, TrueClass, FalseClass, Method
43
+ register_duplication(register, object, object)
44
+
45
+ else
46
+ dup_object(register, object)
47
+
48
+ end
49
+ end
50
+
51
+ def identifiable?(object)
52
+ object.class && object.respond_to?(:is_a?)
53
+ rescue NoMethodError
54
+ false
55
+ end
56
+
57
+ def dup_array(register, object)
58
+ duplication = dup_object(register, object)
59
+ duplication.map! { |e| _dup(register, e) }
60
+ end
61
+
62
+ def dup_hash(register, object)
63
+ duplication = dup_object(register, object)
64
+ object.reduce(duplication) { |hash, (k, v)| hash.merge!(_dup(register, k) => _dup(register, v)) }
65
+ end
66
+
67
+ def dup_range(register, range)
68
+ register_duplication(register, range, range.class.new(_dup(register, range.first), _dup(register, range.last)))
69
+ rescue StandardError
70
+ register_duplication(register, range, range.dup)
71
+ end
72
+
73
+ def dup_struct(register, struct)
74
+ duplication = register_duplication(register, struct, struct.dup)
75
+
76
+ struct.each_pair do |attr, value|
77
+ duplication.__send__("#{attr}=", _dup(register, value))
78
+ end
79
+
80
+ duplication
81
+ end
82
+
83
+ def dup_object(register, object)
84
+ dup_instance_variables(register, object, register_duplication(register, object, try_dup(object)))
85
+ end
86
+
87
+ def dup_instance_variables(register, object, duplication)
88
+ return duplication unless respond_to_instance_variables?(object)
89
+
90
+ object.instance_variables.each do |instance_variable|
91
+ value = get_instance_variable(object, instance_variable)
92
+
93
+ set_instance_variable(duplication, instance_variable, _dup(register, value))
94
+ end
95
+
96
+ duplication
97
+ end
98
+
99
+ def get_instance_variable(object, instance_variable_name)
100
+ object.instance_variable_get(instance_variable_name)
101
+ rescue NoMethodError
102
+ object.instance_eval(instance_variable_name.to_s)
103
+ end
104
+
105
+ def set_instance_variable(duplicate, instance_variable_name, value_to_set)
106
+ duplicate.instance_variable_set(instance_variable_name, value_to_set)
107
+ rescue NoMethodError
108
+ duplicate.instance_eval("#{instance_variable_name} = Marshal.load(#{Marshal.dump(value_to_set).inspect})")
109
+ end
110
+
111
+ def try_dup(object)
112
+ o = object.dup
113
+
114
+ o.tap do
115
+ object.singleton_class.included_modules.each do |m|
116
+ o.extend m unless o.is_a? m
117
+ end
118
+ end
119
+ rescue NoMethodError, TypeError
120
+ object
121
+ end
122
+
123
+ def respond_to_instance_variables?(object)
124
+ object.respond_to?(:instance_variables) && object.instance_variables.is_a?(Array)
125
+ rescue NoMethodError
126
+ false
127
+ end
128
+ end
129
+
130
+ class Object
131
+ def duplicate
132
+ Duplicate.duplicate(self)
133
+ end
134
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'send-nice'
2
+
3
+ module DynamicProxyModule
4
+ def method_missing(method_name, *args, **key_args, &block)
5
+ if @receiver.respond_to? method_name
6
+ @receiver._send_nice method_name, args, key_args, &block
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ def respond_to_missing?(method_name, include_private)
13
+ @receiver.respond_to?(method_name, include_private) || super
14
+ end
15
+
16
+ alias _is_a? is_a?
17
+
18
+ def is_a?(klass)
19
+ _is_a?(klass) || @receiver.is_a?(klass)
20
+ end
21
+
22
+ alias _kind_of? kind_of?
23
+
24
+ def kind_of?(klass)
25
+ _kind_of?(klass) || @receiver.is_a?(klass)
26
+ end
27
+
28
+ alias _instance_of? instance_of?
29
+
30
+ def instance_of?(klass)
31
+ _instance_of?(klass) || @receiver.instance_of?(klass)
32
+ end
33
+
34
+ alias _equalequal ==
35
+
36
+ def ==(object)
37
+ _equalequal(object) || @receiver.==(object)
38
+ end
39
+
40
+ alias _eql? eql?
41
+
42
+ def eql?(object)
43
+ _eql?(object) || @receiver.eql?(object)
44
+ end
45
+ end
46
+
47
+ class DynamicProxy
48
+ include DynamicProxyModule
49
+
50
+ def initialize(receiver = nil)
51
+ @receiver = receiver
52
+ end
53
+
54
+ attr_accessor :receiver
55
+ end
@@ -0,0 +1,28 @@
1
+ class Hash
2
+ def inspect
3
+ all = collect { |key, value| [', ', key.is_a?(Symbol) ? key.to_s + ': ' : key.to_s + ' => ', value.inspect] }.flatten
4
+ all.shift
5
+ '{ ' + all.join + ' }'
6
+ end
7
+ end
8
+
9
+ class Rational
10
+ def inspect
11
+ d = self - to_i
12
+ if d != 0
13
+ "#{to_i}(#{d.numerator}/#{d.denominator})"
14
+ else
15
+ to_i.to_s
16
+ end
17
+ end
18
+
19
+ alias _to_s to_s
20
+
21
+ def to_s
22
+ if to_i == self
23
+ to_i.to_s
24
+ else
25
+ _to_s
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,85 @@
1
+ class KeyParametersProcedureBinder
2
+ attr_reader :procedure
3
+
4
+ def initialize(procedure, on_rescue: nil)
5
+ @procedure = procedure
6
+ @on_rescue = on_rescue
7
+
8
+ @parameters = {}
9
+ @has_rest = false
10
+ @value_parameters_count = 0
11
+
12
+ procedure.parameters.each do |parameter|
13
+ @parameters[parameter[1]] = nil if parameter[0] == :key || parameter[0] == :keyreq
14
+ @has_rest = true if parameter[0] == :keyrest
15
+
16
+ @value_parameters_count += 1 if parameter[0] == :req || parameter[0] == :opt
17
+ end
18
+ end
19
+
20
+ def call(*value_parameters, **key_parameters)
21
+ _call value_parameters, key_parameters
22
+ end
23
+
24
+ def _call(value_parameters, key_parameters)
25
+ if @on_rescue
26
+ begin
27
+ __call value_parameters, key_parameters
28
+ rescue StandardError, ScriptError => e
29
+ @on_rescue.call e
30
+ end
31
+ else
32
+ __call value_parameters, key_parameters
33
+ end
34
+ end
35
+
36
+ def __call(value_parameters, key_parameters)
37
+ effective_key_parameters = apply(key_parameters)
38
+
39
+ if effective_key_parameters.empty?
40
+ if value_parameters.nil? || value_parameters.empty? || @value_parameters_count == 0
41
+ @procedure.call
42
+ else
43
+ @procedure.call *value_parameters.first(@value_parameters_count)
44
+ end
45
+ else
46
+ if value_parameters.nil? || value_parameters.empty?
47
+ @procedure.call **effective_key_parameters
48
+ else
49
+ @procedure.call *value_parameters, **effective_key_parameters
50
+ end
51
+ end
52
+ end
53
+
54
+ private :__call
55
+
56
+ def key?(key)
57
+ @has_rest || @parameters.include?(key)
58
+ end
59
+
60
+ alias_method :has_key?, :key?
61
+
62
+ def apply(hsh)
63
+ hsh ||= {}
64
+
65
+ result = @parameters.clone
66
+
67
+ @parameters.each_key do |parameter_name|
68
+ result[parameter_name] = hsh[parameter_name]
69
+ end
70
+
71
+ if @has_rest
72
+ hsh.each do |key, value|
73
+ result[key] = value unless result.key?(key)
74
+ end
75
+ end
76
+
77
+ result
78
+ end
79
+
80
+ def inspect
81
+ "KeyParametersProcedureBinder: parameters = #{@parameters} has_rest = #{@has_rest}"
82
+ end
83
+
84
+ alias to_s inspect
85
+ end
@@ -0,0 +1,13 @@
1
+ class Proc
2
+ def _call(value_args, key_value_args)
3
+ if value_args && key_value_args
4
+ call(*value_args, **key_value_args)
5
+ elsif value_args
6
+ call(*value_args)
7
+ elsif key_value_args
8
+ call(**key_value_args)
9
+ else
10
+ call
11
+ end
12
+ end
13
+ end