blockenspiel 0.3.3-java → 0.4.0-java
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.
- data/Blockenspiel.rdoc +12 -4
- data/History.rdoc +8 -0
- data/README.rdoc +10 -6
- data/Rakefile +88 -92
- data/lib/blockenspiel/builder.rb +201 -0
- data/lib/blockenspiel/dsl_setup.rb +361 -0
- data/lib/blockenspiel/errors.rb +61 -0
- data/lib/blockenspiel/impl.rb +290 -604
- data/lib/blockenspiel/version.rb +2 -2
- data/lib/blockenspiel/versionomy.rb +1 -1
- data/lib/blockenspiel.rb +22 -4
- data/lib/blockenspiel_unmixer.jar +0 -0
- data/tests/files/file1.rb +2 -0
- data/tests/tc_basic.rb +30 -0
- data/tests/tc_mixins.rb +139 -2
- metadata +60 -51
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
#
|
|
3
|
+
# Blockenspiel DSL definition
|
|
4
|
+
#
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
# Copyright 2008-2010 Daniel Azuma
|
|
7
|
+
#
|
|
8
|
+
# All rights reserved.
|
|
9
|
+
#
|
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
|
12
|
+
#
|
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
|
14
|
+
# this list of conditions and the following disclaimer.
|
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
17
|
+
# and/or other materials provided with the distribution.
|
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
|
20
|
+
# derived from this software without specific prior written permission.
|
|
21
|
+
#
|
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
33
|
+
# -----------------------------------------------------------------------------
|
|
34
|
+
;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
require 'thread'
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
module Blockenspiel
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# === DSL setup methods
|
|
44
|
+
#
|
|
45
|
+
# These class methods are available after you have included the
|
|
46
|
+
# Blockenspiel::DSL module.
|
|
47
|
+
#
|
|
48
|
+
# By default, a class that has DSL capability will automatically make
|
|
49
|
+
# all public methods available to parameterless blocks, except for the
|
|
50
|
+
# +initialize+ method, any methods whose names begin with an underscore,
|
|
51
|
+
# and any methods whose names end with an equals sign.
|
|
52
|
+
#
|
|
53
|
+
# If you want to change this behavior, use the directives defined here to
|
|
54
|
+
# control exactly which methods are available to parameterless blocks.
|
|
55
|
+
|
|
56
|
+
module DSLSetupMethods
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# :stopdoc:
|
|
60
|
+
|
|
61
|
+
# Called when DSLSetupMethods extends a class.
|
|
62
|
+
# This sets up the current class, and adds a hook that causes
|
|
63
|
+
# any subclass of the current class also to be set up.
|
|
64
|
+
|
|
65
|
+
def self.extended(klass_)
|
|
66
|
+
unless klass_.instance_variable_defined?(:@_blockenspiel_module)
|
|
67
|
+
_setup_class(klass_)
|
|
68
|
+
def klass_.inherited(subklass_)
|
|
69
|
+
::Blockenspiel::DSLSetupMethods._setup_class(subklass_)
|
|
70
|
+
super
|
|
71
|
+
end
|
|
72
|
+
class << klass_
|
|
73
|
+
unless private_method_defined?(:_blockenspiel_default_include)
|
|
74
|
+
alias_method :_blockenspiel_default_include, :include
|
|
75
|
+
alias_method :include, :_blockenspiel_custom_include
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# :startdoc:
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Set up a class.
|
|
85
|
+
# Creates a DSL module for this class, optionally delegating to the superclass's module.
|
|
86
|
+
# Also initializes the class's methods hash and active flag.
|
|
87
|
+
|
|
88
|
+
def self._setup_class(klass_) # :nodoc:
|
|
89
|
+
superclass_ = klass_.superclass
|
|
90
|
+
superclass_ = nil unless superclass_.respond_to?(:_get_blockenspiel_module)
|
|
91
|
+
mod_ = ::Module.new
|
|
92
|
+
if superclass_
|
|
93
|
+
mod_.module_eval do
|
|
94
|
+
include superclass_._get_blockenspiel_module
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
klass_.instance_variable_set(:@_blockenspiel_superclass, superclass_)
|
|
98
|
+
klass_.instance_variable_set(:@_blockenspiel_module, mod_)
|
|
99
|
+
klass_.instance_variable_set(:@_blockenspiel_methods, {})
|
|
100
|
+
klass_.instance_variable_set(:@_blockenspiel_active, nil)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Automatically make the given method a DSL method according to the current setting.
|
|
105
|
+
|
|
106
|
+
def _blockenspiel_auto_dsl_method(symbol_) # :nodoc:
|
|
107
|
+
if @_blockenspiel_active
|
|
108
|
+
dsl_method(symbol_)
|
|
109
|
+
elsif @_blockenspiel_active.nil?
|
|
110
|
+
if symbol_ != :initialize && symbol_.to_s !~ /^_/ && symbol_.to_s !~ /=$/
|
|
111
|
+
dsl_method(symbol_)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# Hook called when a method is added.
|
|
118
|
+
# This calls _blockenspiel_auto_dsl_method to auto-handle the method,
|
|
119
|
+
# possibly making it a DSL method according to the current setting.
|
|
120
|
+
|
|
121
|
+
def method_added(symbol_) # :nodoc:
|
|
122
|
+
_blockenspiel_auto_dsl_method(symbol_)
|
|
123
|
+
super
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# Custom include method. Calls the main include implementation, but also
|
|
128
|
+
# goes through the public methods of the included module and calls
|
|
129
|
+
# _blockenspiel_auto_dsl_method on each to make them DSL methods
|
|
130
|
+
# (possibly) according to the current setting.
|
|
131
|
+
|
|
132
|
+
def _blockenspiel_custom_include(*modules_) # :nodoc:
|
|
133
|
+
_blockenspiel_default_include(*modules_)
|
|
134
|
+
modules_.reverse_each do |mod_|
|
|
135
|
+
mod_.public_instance_methods.each do |method_|
|
|
136
|
+
_blockenspiel_auto_dsl_method(method_)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# Get this class's corresponding DSL module
|
|
143
|
+
|
|
144
|
+
def _get_blockenspiel_module # :nodoc:
|
|
145
|
+
@_blockenspiel_module
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# Get information on the given DSL method name.
|
|
150
|
+
# Possible values are the name of the delegate method, false for method disabled,
|
|
151
|
+
# or nil for method never defined.
|
|
152
|
+
|
|
153
|
+
def _get_blockenspiel_delegate(name_) # :nodoc:
|
|
154
|
+
delegate_ = @_blockenspiel_methods[name_]
|
|
155
|
+
if delegate_.nil? && @_blockenspiel_superclass
|
|
156
|
+
@_blockenspiel_superclass._get_blockenspiel_delegate(name_)
|
|
157
|
+
else
|
|
158
|
+
delegate_
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# Make a particular method available to parameterless DSL blocks.
|
|
164
|
+
#
|
|
165
|
+
# To explicitly make a method available to parameterless blocks:
|
|
166
|
+
# dsl_method :my_method
|
|
167
|
+
#
|
|
168
|
+
# To explicitly exclude a method from parameterless blocks:
|
|
169
|
+
# dsl_method :my_method, false
|
|
170
|
+
#
|
|
171
|
+
# To explicitly make a method available to parameterless blocks, but
|
|
172
|
+
# point it to a method of a different name on the target class:
|
|
173
|
+
# dsl_method :my_method, :target_class_method
|
|
174
|
+
|
|
175
|
+
def dsl_method(name_, delegate_=nil)
|
|
176
|
+
name_ = name_.to_sym
|
|
177
|
+
if delegate_
|
|
178
|
+
delegate_ = delegate_.to_sym
|
|
179
|
+
elsif delegate_.nil?
|
|
180
|
+
delegate_ = name_
|
|
181
|
+
end
|
|
182
|
+
@_blockenspiel_methods[name_] = delegate_
|
|
183
|
+
unless @_blockenspiel_module.public_method_defined?(name_)
|
|
184
|
+
@_blockenspiel_module.module_eval("def #{name_}(*params_, &block_); val_ = ::Blockenspiel._target_dispatch(self, :#{name_}, params_, block_); ::Blockenspiel::NO_VALUE.equal?(val_) ? super(*params_, &block_) : val_; end\n")
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# Control the behavior of methods with respect to parameterless blocks,
|
|
190
|
+
# or make a list of methods available to parameterless blocks in bulk.
|
|
191
|
+
#
|
|
192
|
+
# To enable automatic exporting of methods to parameterless blocks.
|
|
193
|
+
# After executing this command, all public methods defined in the class
|
|
194
|
+
# will be available on parameterless blocks, until
|
|
195
|
+
# <tt>dsl_methods false</tt> is called:
|
|
196
|
+
# dsl_methods true
|
|
197
|
+
#
|
|
198
|
+
# To disable automatic exporting of methods to parameterless blocks.
|
|
199
|
+
# After executing this command, methods defined in this class will be
|
|
200
|
+
# excluded from parameterless blocks, until <tt>dsl_methods true</tt>
|
|
201
|
+
# is called:
|
|
202
|
+
# dsl_methods false
|
|
203
|
+
#
|
|
204
|
+
# To make a list of methods available to parameterless blocks in bulk:
|
|
205
|
+
# dsl_methods :my_method1, :my_method2, ...
|
|
206
|
+
#
|
|
207
|
+
# You can also point dsl methods to a method of a different name on the
|
|
208
|
+
# target class, by using a hash syntax, as follows:
|
|
209
|
+
# dsl_methods :my_method1 => :target_class_method1,
|
|
210
|
+
# :my_method2 => :target_class_method2
|
|
211
|
+
#
|
|
212
|
+
# You can mix non-renamed and renamed method declarations as long as
|
|
213
|
+
# the renamed (hash) methods are at the end. e.g.:
|
|
214
|
+
# dsl_methods :my_method1, :my_method2 => :target_class_method2
|
|
215
|
+
|
|
216
|
+
def dsl_methods(*names_)
|
|
217
|
+
if names_.size == 0 || names_ == [true]
|
|
218
|
+
@_blockenspiel_active = true
|
|
219
|
+
elsif names_ == [false]
|
|
220
|
+
@_blockenspiel_active = false
|
|
221
|
+
else
|
|
222
|
+
if names_.last.kind_of?(::Hash)
|
|
223
|
+
names_.pop.each do |name_, delegate_|
|
|
224
|
+
dsl_method(name_, delegate_)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
names_.each do |name_|
|
|
228
|
+
dsl_method(name_, name_)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# A DSL-friendly attr_accessor.
|
|
235
|
+
#
|
|
236
|
+
# This creates the usual "name" and "name=" methods in the current
|
|
237
|
+
# class that can be used in the usual way. However, its implementation
|
|
238
|
+
# of the "name" method (the getter) also takes an optional parameter
|
|
239
|
+
# that causes it to behave as a setter. This is done because the usual
|
|
240
|
+
# setter syntax cannot be used in a parameterless block, since it is
|
|
241
|
+
# syntactically indistinguishable from a local variable assignment.
|
|
242
|
+
# The "name" method is exposed as a dsl_method.
|
|
243
|
+
#
|
|
244
|
+
# For example:
|
|
245
|
+
#
|
|
246
|
+
# dsl_attr_accessor :foo
|
|
247
|
+
#
|
|
248
|
+
# enables the following:
|
|
249
|
+
#
|
|
250
|
+
# my_block do |param|
|
|
251
|
+
# param.foo = 1 # Usual setter syntax works
|
|
252
|
+
# param.foo 2 # Alternate setter syntax also works
|
|
253
|
+
# puts param.foo # Usual getter syntax still works
|
|
254
|
+
# end
|
|
255
|
+
#
|
|
256
|
+
# my_block do
|
|
257
|
+
# # foo = 1 # Usual setter syntax does NOT work since it
|
|
258
|
+
# # looks like a local variable assignment
|
|
259
|
+
# foo 2 # Alternate setter syntax does work
|
|
260
|
+
# puts foo # Usual getter syntax still works
|
|
261
|
+
# end
|
|
262
|
+
|
|
263
|
+
def dsl_attr_accessor(*names_)
|
|
264
|
+
names_.each do |name_|
|
|
265
|
+
unless name_.kind_of?(::String) || name_.kind_of?(::Symbol)
|
|
266
|
+
raise ::TypeError, "#{name_.inspect} is not a symbol"
|
|
267
|
+
end
|
|
268
|
+
unless name_.to_s =~ /^[_a-zA-Z]\w+$/
|
|
269
|
+
raise ::NameError, "invalid attribute name #{name_.inspect}"
|
|
270
|
+
end
|
|
271
|
+
module_eval("def #{name_}(value_=::Blockenspiel::NO_VALUE); ::Blockenspiel::NO_VALUE.equal?(value_) ? @#{name_} : @#{name_} = value_; end\n")
|
|
272
|
+
alias_method("#{name_}=", name_)
|
|
273
|
+
dsl_method(name_)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# A DSL-friendly attr_writer.
|
|
279
|
+
#
|
|
280
|
+
# This creates the usual "name=" method in the current class that can
|
|
281
|
+
# be used in the usual way. However, it also creates the method "name",
|
|
282
|
+
# which also functions as a setter (but not a getter). This is done
|
|
283
|
+
# because the usual setter syntax cannot be used in a parameterless
|
|
284
|
+
# block, since it is syntactically indistinguishable from a local
|
|
285
|
+
# variable assignment. The "name" method is exposed as a dsl_method.
|
|
286
|
+
#
|
|
287
|
+
# For example:
|
|
288
|
+
#
|
|
289
|
+
# dsl_attr_writer :foo
|
|
290
|
+
#
|
|
291
|
+
# is functionally equivalent to:
|
|
292
|
+
#
|
|
293
|
+
# attr_writer :foo
|
|
294
|
+
# alias_method :foo, :foo=
|
|
295
|
+
# dsl_method :foo
|
|
296
|
+
#
|
|
297
|
+
# which enables the following:
|
|
298
|
+
#
|
|
299
|
+
# my_block do |param|
|
|
300
|
+
# param.foo = 1 # Usual setter syntax works
|
|
301
|
+
# param.foo 2 # Alternate setter syntax also works
|
|
302
|
+
# end
|
|
303
|
+
# my_block do
|
|
304
|
+
# # foo = 1 # Usual setter syntax does NOT work since it
|
|
305
|
+
# # looks like a local variable assignment
|
|
306
|
+
# foo(2) # Alternate setter syntax does work
|
|
307
|
+
# end
|
|
308
|
+
|
|
309
|
+
def dsl_attr_writer(*names_)
|
|
310
|
+
names_.each do |name_|
|
|
311
|
+
attr_writer(name_)
|
|
312
|
+
alias_method(name_, "#{name_}=")
|
|
313
|
+
dsl_method(name_)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# === DSL activation module
|
|
322
|
+
#
|
|
323
|
+
# Include this module in a class to mark this class as a DSL class and
|
|
324
|
+
# make it possible for its methods to be called from a block that does not
|
|
325
|
+
# take a parameter.
|
|
326
|
+
#
|
|
327
|
+
# After you include this module, you can use the directives defined in
|
|
328
|
+
# DSLSetupMethods to control what methods are available to DSL blocks
|
|
329
|
+
# that do not take parameters.
|
|
330
|
+
|
|
331
|
+
module DSL
|
|
332
|
+
|
|
333
|
+
def self.included(klass_) # :nodoc:
|
|
334
|
+
unless klass_.kind_of?(::Class)
|
|
335
|
+
raise ::Blockenspiel::BlockenspielError, "You cannot include Blockenspiel::DSL in a module (yet)"
|
|
336
|
+
end
|
|
337
|
+
klass_.extend(::Blockenspiel::DSLSetupMethods)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
# === DSL activation base class
|
|
344
|
+
#
|
|
345
|
+
# Subclasses of this base class are considered DSL classes.
|
|
346
|
+
# Methods of the class can be made available to be called from a block that
|
|
347
|
+
# doesn't take an explicit block parameter.
|
|
348
|
+
# You may use the directives defined in DSLSetupMethods to control how
|
|
349
|
+
# methods of the class are handled in such blocks.
|
|
350
|
+
#
|
|
351
|
+
# Subclassing this base class is functionally equivalent to simply
|
|
352
|
+
# including Blockenspiel::DSL in the class.
|
|
353
|
+
|
|
354
|
+
class Base
|
|
355
|
+
|
|
356
|
+
include ::Blockenspiel::DSL
|
|
357
|
+
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
#
|
|
3
|
+
# Blockenspiel error classes
|
|
4
|
+
#
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
# Copyright 2008-2010 Daniel Azuma
|
|
7
|
+
#
|
|
8
|
+
# All rights reserved.
|
|
9
|
+
#
|
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
|
12
|
+
#
|
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
|
14
|
+
# this list of conditions and the following disclaimer.
|
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
17
|
+
# and/or other materials provided with the distribution.
|
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
|
20
|
+
# derived from this software without specific prior written permission.
|
|
21
|
+
#
|
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
33
|
+
# -----------------------------------------------------------------------------
|
|
34
|
+
;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
module Blockenspiel
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Base exception for all exceptions raised by Blockenspiel
|
|
41
|
+
|
|
42
|
+
class BlockenspielError < ::RuntimeError
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# This exception is rasied when attempting to use the <tt>:proxy</tt> or
|
|
47
|
+
# <tt>:mixin</tt> parameterless behavior with a target that does not have
|
|
48
|
+
# the DSL module included. It is an error made by the DSL implementor.
|
|
49
|
+
|
|
50
|
+
class DSLMissingError < ::Blockenspiel::BlockenspielError
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# This exception is raised when the block provided does not take the
|
|
55
|
+
# expected number of parameters. It is an error made by the caller.
|
|
56
|
+
|
|
57
|
+
class BlockParameterError < ::Blockenspiel::BlockenspielError
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
end
|