strongtyping 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ ./t/functest.rb
2
+ ./t/timetest.rb
3
+ ./Makefile
4
+ ./README.en
5
+ ./extconf.rb
6
+ ./strongtyping.c
7
+ ./LGPL
8
+ ./MANIFEST
9
+ ./strongtyping.h
@@ -0,0 +1,420 @@
1
+ StrongTyping 2.0
2
+ ================
3
+
4
+ StrongTyping is a little ruby module that provides a convenient way
5
+ for ruby methods to check parameter types, and also dynamically
6
+ query them. In addition to merely checking a single set of types,
7
+ it allows easy overloading based on a number of different templates.
8
+
9
+ Changes
10
+ -------
11
+
12
+ 2.0.6b - Bugfix: Shouldn't get "too many arguments" on gcc
13
+ anymore.
14
+
15
+ 2.0.6a - Bugfix: Portability issues (zero-sized arrays and UNUSED
16
+ for non-GNU platforms fixed).
17
+
18
+ 2.0.6 - Bugfix: Types given after lists of types were not being
19
+ checked, as in the following:
20
+
21
+ expect(a, String, b, [Integer, String], d, String)
22
+
23
+ Before, 'd' could be any type and pass; now this is fixed.
24
+
25
+ 2.0.5 - Bugfix: overload "No matching template" was broken, and
26
+ I didn't notice.
27
+
28
+ Bugfix: get_arg_types fixed for no arguments; now returns []
29
+ in the right places for both overload() and expect().
30
+
31
+ Mod: Should compile without warnings with -W -Wall, at least
32
+ on gcc.
33
+
34
+ Mod: Added unit tests.
35
+
36
+ 2.0.4 - Bugfix: Optional arguments are now handled correctly
37
+ when doing get_arg_types.
38
+
39
+ 2.0.3 - It's a bit of a hack, but overload_default's "No matching
40
+ template" error now displays the given types, which makes
41
+ debugging a lot easier.
42
+
43
+ 2.0.2 - Change Object#type to Object#class for conformance with
44
+ Ruby 1.8
45
+
46
+ Bugfix: overload() range check that caused a segfault on
47
+ some systems
48
+
49
+ Bugfix: verify_args_for() should work now
50
+
51
+ 2.0.1 - Bugfix: overload() blocks with one parameter now receive the
52
+ parameter instead of an array
53
+
54
+ 2.0 - Rewritten in C for speed.
55
+ * As in 1.0.1, expect (and overload, etc) take arrays of
56
+ classes/modules
57
+
58
+ * overload_error is deprecated (but still available) in
59
+ favor of overload_default
60
+
61
+ * overload_exception acts as overload, but acts as an
62
+ "invalid" case; useful for invalid cases where a
63
+ specific exception should be thrown
64
+
65
+ * More on "duck typing" in the FAQ
66
+
67
+ 1.0.1 - [Not officially released] Added support for arrays of types
68
+ to expect(), as in expect(a, [Integer, NilClass])
69
+ 1.0 - First release
70
+
71
+ Requirements
72
+ ------------
73
+
74
+ * ruby 1.6
75
+ * C compiler
76
+
77
+ Install
78
+ -------
79
+
80
+ De-Compress archive and enter its top directory.
81
+ Then type:
82
+
83
+ $ ruby extconf.rb
84
+ $ make
85
+ ($ su)
86
+ # make install
87
+
88
+ Usage
89
+ -----
90
+
91
+ Let's say you have the following function:
92
+
93
+ def foo(a, b)
94
+ ...
95
+ end
96
+
97
+ Now let's say this function wants 'a' to always be a String, and 'b'
98
+ should be Numeric:
99
+
100
+ require 'strongtyping'
101
+ include StrongTyping
102
+
103
+ def foo(a, b)
104
+ expect(a, String, b, Numeric)
105
+ ...
106
+ end
107
+
108
+ If 'a' or 'b' is of the wrong type, an ArgumentTypeError will be
109
+ raised.
110
+
111
+ Overloading is just as easy:
112
+
113
+ require 'strongtyping'
114
+ include StrongTyping
115
+
116
+ def bar(*args)
117
+ overload(args, String, String) {
118
+ | s1, s2 |
119
+ ...
120
+ return
121
+ }
122
+
123
+ overload(args, String, Integer) {
124
+ | s, i |
125
+ ...
126
+ return
127
+ }
128
+
129
+ overload_default args
130
+ end
131
+
132
+ If someone calls 'bar' with two Strings, or a String and an Integer,
133
+ the appropriate block will be called. Otherwise, an OverloadError
134
+ is raised.
135
+
136
+ How about default parameters? Say we have the following function:
137
+
138
+ def baz(a, b = nil)
139
+ action = "You baz #{a}";
140
+ action += " with a #{b}" if b
141
+
142
+ print action, "\n"
143
+ end
144
+
145
+ Now, b can either be nil or a String. We don't want to have two
146
+ full overload cases... that would duplicate code. So, expect()
147
+ allows an array of types:
148
+
149
+ expect(a, String, b, [String, NilClass]);
150
+
151
+ This takes care of the above case nicely.
152
+
153
+ What if your code is curious about which types are allowed? The
154
+ get_arg_types function is provided for just this purpose. Given the
155
+ above definitions for 'foo' and 'bar', consider the following code:
156
+
157
+ p get_arg_types(method(:foo)) # => [[String, Numeric]]
158
+ p get_arg_types(method(:bar)) # => [[String, String], [String, Integer]]
159
+ p get_arg_types(method(:baz)) # => [[String, [String, NilClass]]]
160
+
161
+ This is useful if you're converting user input into a form that the
162
+ method expects. (If you get "1234", should you convert it to an
163
+ integer, or is it best left a string? Now you know.)
164
+
165
+ What if you have an array of arguments, 'arr', and you're worried
166
+ that the method 'bar' won't accept them? You can check ahead of
167
+ time:
168
+
169
+ if not verify_args_for(method(:bar), arr)
170
+ print "I can't let you do that, Dave\n"
171
+ end
172
+
173
+ Reference
174
+ ---------
175
+ Module: StrongTyping
176
+
177
+ Methods:
178
+
179
+ expect(obj0, Module0[, obj1, Module1[,...objN, ModuleN]])
180
+
181
+ Verify the parameters obj0..objN are of the given class (or
182
+ module) Module0..ModuleN
183
+
184
+ overload(args, [Module0[, Module1[,...ModuleN]]]) { | o0, o1,..oN | }
185
+
186
+ Call the block with 'args' if they match the pattern
187
+ Module0..ModuleN. The block should _always_ call return at the
188
+ end.
189
+
190
+ overload_exception(args, [Module0[,...ModuleN]]]) { | o0, o1,..oN | }
191
+
192
+ This acts identically to overload(), except the case specified
193
+ is considered invalid, and thus not returned by get_arg_types().
194
+ It is expected that the specified block will throw an exception.
195
+
196
+ overload_default(args)
197
+ overload_error(args)
198
+
199
+ Raise OverloadError. This should _always_ be called after the
200
+ last overload() block. In addition to raising the exception,
201
+ it aids in checking parameters. As of 2.0, the overload_error
202
+ name is deprecated; use overload_default.
203
+
204
+ get_arg_types(Method)
205
+
206
+ Return an array of parameter templates. This is an array of
207
+ arrays, and will have multiple indices for functions using
208
+ multiple overload() blocks.
209
+
210
+ verify_args_for(method, args)
211
+
212
+ Verify the method 'method' will accept the arguments in array
213
+ 'args', returning a boolean result.
214
+
215
+ Exceptions:
216
+
217
+ ArgumentTypeError < ArgumentError
218
+
219
+ This exception is raised by expect() if the arguments do not
220
+ match the expected types.
221
+
222
+ OverloadError < ArgumentTypeError
223
+
224
+ This exception is raised by overload_default() if no overload()
225
+ template matches the given arguments.
226
+
227
+ FAQ
228
+ ---
229
+ These aren't actually FAQs (yet), but some issues that _have_ been
230
+ brought up.
231
+
232
+ Q: Why?
233
+ A: Because I need it for Mephle. :-)
234
+
235
+
236
+ Q: No really, why bother with static typing? Isn't ruby dynamic?
237
+ A: This is not 'static typing'. This is 'strong typing'. Static
238
+ typing is what you get when a variable can only be of a certain
239
+ type, as in C or C++. Strong typing is enforcing types. These may
240
+ seem similar, but they are actually not directly related.
241
+
242
+ Some other languages, such as Common Lisp, allow for dynamic,
243
+ strong typing. Strong typing and dynamic typing are not mutually
244
+ exclusive.
245
+
246
+
247
+ Q: Yeah, but really, why bother? Why not just let ruby sort out the
248
+ errors as they occur?
249
+ A: This is incorrect thinking. Allowing errors to just occur when
250
+ they happen is naive programming. Consider the following:
251
+
252
+ # Wait N seconds, then open the bridge for M seconds
253
+ def sendMsg(bridge, n, m)
254
+ sleep(n)
255
+ bridge.open
256
+ sleep(m)
257
+ bridge.close
258
+ end
259
+
260
+ Now say 'm' is pased in as a string. Oops! A TypeError is
261
+ raised. Now the bridge is open, and somewhere (hopefully!) someone
262
+ caught the exception so the program didn't crash, but the bridge
263
+ opening wasn't reversed, so it's going to stay open and back up
264
+ traffic until someone fixes the problem.
265
+
266
+ This is an academic example, but there are many cases when just
267
+ letting an error happen will lead to an inconsistent system state.
268
+ Ruby (and most systems) are not transactional, and inconsistent
269
+ states are unacceptable.
270
+
271
+ In addition, it is desireable to know _programmatically_ why
272
+ something failed, as specific action can be taken if desired.
273
+
274
+ "Wait," someone in the audience says, "you could just check to see
275
+ if 'm' and 'n' are of the correct type!"
276
+
277
+ Yes, yes you could.
278
+
279
+ That's what this module is for. ;-)
280
+
281
+
282
+ Q: Isn't it up to the caller to call my function correctly?
283
+ A: The caller cannot know and deal with errors that may occur in your
284
+ code. That's your job. Checking for errors ahead of time and
285
+ informing the caller about problems is also your job. This module
286
+ just makes it easy.
287
+
288
+ In addition, it's nice for the caller to be able to ask and check
289
+ what your method expects ahead of time to guard against error.
290
+ The StrongTyping module also provides functionality for this.
291
+
292
+
293
+ Q: OK, but strong typing is baaad. What if I want to pass something
294
+ that acts like something else, or responds to a given symbol?
295
+ Doesn't ruby have "duck" typing?
296
+ A: First, what you're suggesting is evil. If you want that, go
297
+ write C++. :-)
298
+
299
+ Second, you should never depend on a function's implementation. If
300
+ the documentation says "pass me a hash" and you pass it anything
301
+ that responds to :[], your code may break when the next version
302
+ comes out.
303
+
304
+ Third, if you pass something that responds accurately to the
305
+ _interface_ (methods provided by class or module) specified, then
306
+ that should be _of_ that class or module. This may not be the case
307
+ with all ruby objects yet; for instance, anything responding to :[]
308
+ being something like a Mappable. You can make this the case in
309
+ your code, or urge developers to create a standard set of interface
310
+ mixins for just this purpose.
311
+
312
+ "Duck" typing just a term for this sort of "maybe" behavior, much
313
+ like what C++ STL templates use. However, the problem is that even
314
+ if an object responds to a method, there is no guarantee that the
315
+ method acts in an expected manner---and the interface may still
316
+ change without notice. "Duck" typing sounds much like 'duct
317
+ taping' depending on your accent, and I think duct-taping is a good
318
+ description of this is in practice. :-)
319
+
320
+ Another argument is that ruby allows one to change the behavior of
321
+ methods at any time:
322
+
323
+ a = String.new;
324
+ def a.split
325
+ print "hello world\n"
326
+ end
327
+
328
+ For this, I have two responses: first, if a method is deprecated
329
+ or changed dramatically, StrongTyping can aid in letting the code
330
+ know:
331
+
332
+ a = String.new;
333
+ def a.split(*args)
334
+ overload(args) { print "hello world\n" }
335
+ overload_default args
336
+ end
337
+
338
+ This case will drop any normal calls through to overload_default,
339
+ raising an exception, which can be caught and analyzed. You can
340
+ even provide another case that calls the superclass.
341
+
342
+ Second, either you're changing the method in a subtle manner (it
343
+ does what it used to, with added effect), or an outrageous manner
344
+ (it acts nothing like it did before). In the former case, code
345
+ should work fine anyway. In the latter case, as in the above
346
+ example, you should ask yourself why you're changing it. The
347
+ function no longer splits, why is it called split? This is not
348
+ good design; the StrongTyping module is here to aid in good design,
349
+ not prevent poor design.
350
+
351
+ A more realistic example would be the academic "Shape" class
352
+ example of inheritance, with "Ellipse" and "Circle". Ruby properly
353
+ allows one to make Circle a subclass of Ellipse, and redefine
354
+ "setSize" to the constrained definition of a circle. This change
355
+ is visible to code---an ArgumentError will be raised (2 arguments
356
+ for 1), or setSize can throw a ConstraintError. StrongTyping
357
+ provides a useful function, overload_exception, for just this case:
358
+
359
+ class Circle < Ellipse
360
+ :
361
+ def setSize(*args)
362
+ overload(args, Integer) {
363
+ | r |
364
+ @radius = r
365
+ return
366
+ }
367
+
368
+ overload_exception(args, Integer, Integer) {
369
+ | a, b |
370
+ raise ConstraintError
371
+ }
372
+
373
+ overload_default args
374
+ end
375
+ :
376
+ end
377
+
378
+ Of course, there are a number of good choices for handling
379
+ this... you may still allow #setSize(a, b) if a == b. The
380
+ important part is that the change in behavior can now be determined
381
+ by code.
382
+
383
+
384
+ Q: But I always write perfect code. I know what my functions do, and
385
+ what they take, and what I'm passing them.
386
+ A: No one writes perfect code. Additionally, not all environments are
387
+ as controlled as yours may be. Especially in a networked
388
+ environment when someone may be invoking a method remotely, you
389
+ can't depend on calling code not to be malicious.
390
+
391
+
392
+ Q: OK, OK. But, uh... what is Mephle?
393
+ A: Mephle is a soon-to-be-released network-transparent persistant
394
+ object system written in ruby. It uses many of the Unity concepts
395
+ (http://unity-project.sf.net/). It will be on the RAA when
396
+ released.
397
+
398
+
399
+ License
400
+ -------
401
+
402
+ StrongTyping - Method parameter checking for Ruby
403
+ Copyright (C) 2003 Ryan Pavlik
404
+
405
+ This library is free software; you can redistribute it and/or
406
+ modify it under the terms of the GNU Lesser General Public
407
+ License as published by the Free Software Foundation; either
408
+ version 2.1 of the License, or (at your option) any later version.
409
+
410
+ This library is distributed in the hope that it will be useful,
411
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
412
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
413
+ Lesser General Public License for more details.
414
+
415
+ You should have received a copy of the GNU Lesser General Public
416
+ License along with this library; if not, write to the Free Software
417
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
418
+
419
+
420
+ Ryan Pavlik <rpav@mephle.com>
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile "strongtyping"
@@ -0,0 +1,247 @@
1
+ /*
2
+ StrongTyping - Method parameter checking for Ruby
3
+ Copyright (C) 2003 Ryan Pavlik
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ This library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with this library; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ */
19
+
20
+ #include "ruby.h"
21
+ #include "strongtyping.h"
22
+
23
+ static int check_args(int argc, VALUE *obj, VALUE *mod);
24
+
25
+ static VALUE
26
+ strongtyping_expect(int argc, VALUE *argv, VALUE self UNUSED) {
27
+ int i = 0;
28
+ VALUE obj[MAXARGS], mod[MAXARGS];
29
+ VALUE typestr;
30
+
31
+ if(!argc) return Qnil;
32
+ if(argc % 2)
33
+ rb_raise(rb_eSyntaxError, "expect() requires argument pairs");
34
+
35
+ #ifndef __GNUC__
36
+ if(argc*2 > MAXARGS*2)
37
+ rb_raise(rb_eSyntaxError, "too many arguments to expect()");
38
+ #endif
39
+
40
+ for(i = 0; i < argc; i += 2) {
41
+ obj[i/2] = argv[i];
42
+ mod[(i+1)/2] = argv[i+1];
43
+ }
44
+
45
+ if(rb_funcall(obj[0], id_isa, 1, cQueryParams)) {
46
+ rb_funcall(obj[0], rb_intern("<<"), 1, rb_ary_new4(argc/2, mod));
47
+ rb_raise(eArgList, "");
48
+ }
49
+
50
+ i = check_args(argc / 2, obj, mod);
51
+
52
+ if(i < 0) return Qnil;
53
+
54
+ typestr = rb_funcall(mod[i], id_inspect, 0);
55
+ rb_raise(eArgumentTypeError, "Expecting %s as argument %d, got %s",
56
+ RSTRING(typestr)->ptr, i + 1,
57
+ rb_class2name(rb_funcall(obj[i], id_class, 0)));
58
+ }
59
+
60
+ static VALUE
61
+ strongtyping_overload(int argc, VALUE *argv, VALUE self UNUSED) {
62
+ struct RArray *q;
63
+
64
+ if(argc < 1)
65
+ rb_raise(rb_eArgError, "At least one parameter required");
66
+
67
+ Check_Type(argv[0], T_ARRAY);
68
+ q = RARRAY(argv[0]);
69
+
70
+ if(q->len && rb_funcall(q->ptr[0], id_isa, 1, cQueryParams)) {
71
+ rb_funcall(q->ptr[0], rb_intern("<<"), 1,
72
+ rb_ary_new4(argc - 1, argv + 1));
73
+ return Qnil;
74
+ }
75
+
76
+ if(q->len != (argc - 1))
77
+ return Qnil;
78
+
79
+ if(check_args(argc - 1, q->ptr, argv + 1) < 0) {
80
+ if(argc == 2) rb_yield(*RARRAY(*argv)->ptr);
81
+ else rb_yield(*argv);
82
+ }
83
+
84
+ return Qnil;
85
+ }
86
+
87
+ static VALUE
88
+ strongtyping_overload_exception(int argc, VALUE *argv, VALUE self UNUSED) {
89
+ struct RArray *q;
90
+
91
+ if(argc < 1)
92
+ rb_raise(rb_eArgError, "At least one parameters required");
93
+
94
+ Check_Type(argv[0], T_ARRAY);
95
+ q = RARRAY(argv[0]);
96
+
97
+ if(q->len && (argc - 1) == 0)
98
+ return Qnil;
99
+
100
+ if(check_args(argc - 1, q->ptr, argv + 1) < 0)
101
+ rb_yield(argv[0]);
102
+
103
+ return Qnil;
104
+ }
105
+
106
+ static VALUE
107
+ strongtyping_overload_error(VALUE self UNUSED, VALUE args) {
108
+ struct RArray *q;
109
+ VALUE classlist;
110
+ char *name = 0;
111
+ int i = 0;
112
+
113
+ Check_Type(args, T_ARRAY);
114
+ q = RARRAY(args);
115
+
116
+ if(q->len && rb_funcall(q->ptr[0], id_isa, 1, cQueryParams))
117
+ rb_raise(eArgList, "");
118
+
119
+ classlist = rb_str_new2("");
120
+ for(i = 0; i < q->len; i++) {
121
+ if(i > 0) rb_str_cat(classlist, ", ", 2);
122
+ name = rb_class2name(rb_funcall(q->ptr[i], id_class, 0));
123
+ rb_str_cat(classlist, name, strlen(name));
124
+ }
125
+ rb_raise(eOverloadError, "No matching template for arguments: [%s]",
126
+ RSTRING(classlist)->ptr);
127
+ }
128
+
129
+ static int
130
+ check_args(int argc, VALUE *obj, VALUE *mod) {
131
+ int i = 0;
132
+ VALUE ret;
133
+
134
+ for(i = 0; i < argc; i++) {
135
+ if(TYPE(mod[i]) == T_ARRAY) {
136
+ int j = 0, ok = 0;
137
+ for(j = 0; j < RARRAY(mod[i])->len; j++)
138
+ if(rb_funcall(obj[i], id_isa, 1, RARRAY(mod[i])->ptr[j]) == Qtrue)
139
+ ok = 1;
140
+
141
+ if(ok) continue;
142
+ else return i;
143
+ } else {
144
+ ret = rb_funcall(obj[i], id_isa, 1, mod[i]);
145
+ if(ret == Qfalse) return i;
146
+ }
147
+ }
148
+
149
+ return -1;
150
+ }
151
+
152
+ static VALUE
153
+ call_method(VALUE ary) {
154
+ VALUE method = RARRAY(ary)->ptr[0],
155
+ query = RARRAY(ary)->ptr[1];
156
+ VALUE *argv = NULL;
157
+ VALUE ret;
158
+ int argc = 0,
159
+ i = 0;
160
+
161
+ argc = FIX2INT(rb_funcall(method, rb_intern("arity"), 0));
162
+ if(argc == 0) {
163
+ rb_funcall(query, rb_intern("<<"), 1, rb_ary_new());
164
+ rb_raise(eArgList, "");
165
+ } else if(argc < 0) argc = -argc;
166
+
167
+ argv = malloc(sizeof(VALUE) * argc);
168
+ argv[0] = query;
169
+ for(i = 1; i < argc - 1; i++) argv[i] = Qnil;
170
+
171
+ ret = rb_funcall2(method, rb_intern("call"), argc, argv);
172
+ free(argv);
173
+
174
+ return ret;
175
+ }
176
+
177
+ static VALUE
178
+ grab_types(VALUE query) {
179
+ return query;
180
+ }
181
+
182
+ static VALUE
183
+ strongtyping_get_arg_types(VALUE obj UNUSED, VALUE method) {
184
+ VALUE query, ary;
185
+ query = rb_funcall(cQueryParams, rb_intern("new"), 0);
186
+ ary = rb_ary_new3(2, method, query);
187
+
188
+ return rb_rescue2(call_method, ary, grab_types, query, eArgList, 0);
189
+ }
190
+
191
+
192
+ static VALUE
193
+ strongtyping_verify_args_for(VALUE self, VALUE method, VALUE args) {
194
+ struct RArray *list = NULL,
195
+ *t = NULL,
196
+ *a = NULL;
197
+ int i = 0;
198
+ VALUE template = strongtyping_get_arg_types(self, method);
199
+
200
+ list = RARRAY(template);
201
+ a = RARRAY(args);
202
+
203
+ for(i = 0; i < list->len; i++) {
204
+ t = RARRAY(list->ptr[i]);
205
+
206
+ if(a->len != t->len) continue;
207
+ if(check_args(a->len, a->ptr, t->ptr) < 0) return Qtrue;
208
+ }
209
+
210
+ return Qfalse;
211
+ }
212
+
213
+ void Init_strongtyping() {
214
+ mStrongTyping = rb_define_module("StrongTyping");
215
+ id_isa = rb_intern("is_a?");
216
+ id_class = rb_intern("class");
217
+ id_inspect = rb_intern("inspect");
218
+
219
+ cQueryParams = rb_define_class_under(mStrongTyping,
220
+ "%QueryParams",
221
+ rb_cArray);
222
+
223
+ eArgumentTypeError = rb_define_class_under(mStrongTyping,
224
+ "ArgumentTypeError",
225
+ rb_eArgError);
226
+ eOverloadError = rb_define_class_under(mStrongTyping,
227
+ "OverloadError",
228
+ eArgumentTypeError);
229
+ eArgList = rb_define_class_under(mStrongTyping,
230
+ "%ArgList",
231
+ rb_eException);
232
+
233
+ rb_define_module_function(mStrongTyping, "expect",
234
+ strongtyping_expect, -1);
235
+ rb_define_module_function(mStrongTyping, "overload",
236
+ strongtyping_overload, -1);
237
+ rb_define_module_function(mStrongTyping, "overload_exception",
238
+ strongtyping_overload_exception, -1);
239
+ rb_define_module_function(mStrongTyping, "overload_default",
240
+ strongtyping_overload_error, 1);
241
+ rb_define_module_function(mStrongTyping, "overload_error",
242
+ strongtyping_overload_error, 1);
243
+ rb_define_module_function(mStrongTyping, "get_arg_types",
244
+ strongtyping_get_arg_types, 1);
245
+ rb_define_module_function(mStrongTyping, "verify_args_for",
246
+ strongtyping_verify_args_for, 2);
247
+ }