strongtyping 2.0.6 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/MANIFEST CHANGED
@@ -1,9 +1,11 @@
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
1
+ CHANGES
2
+ LGPL
3
+ MANIFEST
4
+ README
5
+ Rakefile
6
+ strongtyping.gemspec
7
+ ext/extconf.rb
8
+ ext/strongtyping.c
9
+ ext/strongtyping.h
10
+ test/functest.rb
11
+ test/timetest.rb
data/README ADDED
@@ -0,0 +1,330 @@
1
+ = Description
2
+ The strongtyping library is a provides a convenient way for Ruby methods
3
+ to check parameter types, and also dynamically query them. In addition to
4
+ merely checking a single set of types, it allows easy overloading based on
5
+ a number of different templates.
6
+
7
+ = Installation
8
+ gem install strongtyping
9
+
10
+ = Synopsis
11
+ Let's say you have the following function:
12
+
13
+ def foo(a, b)
14
+ ...
15
+ end
16
+
17
+ Now let's say this function wants 'a' to always be a String, and 'b'
18
+ should be Numeric:
19
+
20
+ require 'strongtyping'
21
+ include strongtyping
22
+
23
+ def foo(a, b)
24
+ expect(a, String, b, Numeric)
25
+ ...
26
+ end
27
+
28
+ If 'a' or 'b' is of the wrong type, an ArgumentTypeError will be raised.
29
+
30
+ Overloading is just as easy:
31
+
32
+ require 'strongtyping'
33
+ include strongtyping
34
+
35
+ def bar(*args)
36
+ overload(args, String, String){ |s1,s2|
37
+ ...
38
+ return
39
+ }
40
+
41
+ overload(args, String, Integer){ |s,i|
42
+ ...
43
+ return
44
+ }
45
+
46
+ overload_default args
47
+ end
48
+
49
+ If someone calls 'bar' with two Strings, or a String and an Integer,
50
+ the appropriate block will be called. Otherwise, an OverloadError
51
+ is raised.
52
+
53
+ How about default parameters? Say we have the following function:
54
+
55
+ def baz(a, b = nil)
56
+ action = "You baz #{a}";
57
+ action += " with a #{b}" if b
58
+
59
+ print action, "\n"
60
+ end
61
+
62
+ Now, b can either be nil or a String. We don't want to have two
63
+ full overload cases... that would duplicate code. So, expect()
64
+ allows an array of types:
65
+
66
+ expect(a, String, b, [String, NilClass]);
67
+
68
+ This takes care of the above case nicely.
69
+
70
+ What if your code is curious about which types are allowed? The
71
+ get_arg_types function is provided for just this purpose. Given the
72
+ above definitions for 'foo' and 'bar', consider the following code:
73
+
74
+ p get_arg_types(method(:foo)) # => [[String, Numeric]]
75
+ p get_arg_types(method(:bar)) # => [[String, String], [String, Integer]]
76
+ p get_arg_types(method(:baz)) # => [[String, [String, NilClass]]]
77
+
78
+ This is useful if you're converting user input into a form that the
79
+ method expects. (If you get "1234", should you convert it to an
80
+ integer, or is it best left a string? Now you know.)
81
+
82
+ What if you have an array of arguments, 'arr', and you're worried
83
+ that the method 'bar' won't accept them? You can check ahead of
84
+ time:
85
+
86
+ if not verify_args_for(method(:bar), arr)
87
+ print "I can't let you do that, Dave\n"
88
+ end
89
+
90
+ = Reference
91
+ Module: strongtyping
92
+
93
+ Methods:
94
+
95
+ expect(obj0, Module0[, obj1, Module1[,...objN, ModuleN]])
96
+
97
+ Verify the parameters obj0..objN are of the given class (or
98
+ module) Module0..ModuleN
99
+
100
+ overload(args, [Module0[, Module1[,...ModuleN]]]) { | o0, o1,..oN | }
101
+
102
+ Call the block with 'args' if they match the pattern
103
+ Module0..ModuleN. The block should _always_ call return at the
104
+ end.
105
+
106
+ overload_exception(args, [Module0[,...ModuleN]]]) { | o0, o1,..oN | }
107
+
108
+ This acts identically to overload(), except the case specified
109
+ is considered invalid, and thus not returned by get_arg_types().
110
+ It is expected that the specified block will throw an exception.
111
+
112
+ overload_default(args)
113
+ overload_error(args)
114
+
115
+ Raise OverloadError. This should _always_ be called after the
116
+ last overload() block. In addition to raising the exception,
117
+ it aids in checking parameters. As of 2.0, the overload_error
118
+ name is deprecated; use overload_default.
119
+
120
+ get_arg_types(Method)
121
+
122
+ Return an array of parameter templates. This is an array of
123
+ arrays, and will have multiple indices for functions using
124
+ multiple overload() blocks.
125
+
126
+ verify_args_for(method, args)
127
+
128
+ Verify the method 'method' will accept the arguments in array
129
+ 'args', returning a boolean result.
130
+
131
+ Exceptions:
132
+
133
+ ArgumentTypeError < ArgumentError
134
+
135
+ This exception is raised by expect() if the arguments do not
136
+ match the expected types.
137
+
138
+ OverloadError < ArgumentTypeError
139
+
140
+ This exception is raised by overload_default() if no overload()
141
+ template matches the given arguments.
142
+
143
+ = Q & A
144
+ This section written by Ryan Pavlik.
145
+
146
+ Q: Why?
147
+ A: Because it was originally needed for the Mephle library.
148
+
149
+ Q: No really, why bother with static typing? Isn't ruby dynamic?
150
+ A: This is not 'static typing'. This is 'strong typing'. Static
151
+ typing is what you get when a variable can only be of a certain
152
+ type, as in C or C++. Strong typing is enforcing types. These may
153
+ seem similar, but they are actually not directly related.
154
+
155
+ Some other languages, such as Common Lisp, allow for dynamic,
156
+ strong typing. Strong typing and dynamic typing are not mutually
157
+ exclusive.
158
+
159
+ Q: Yeah, but really, why bother? Why not just let ruby sort out the
160
+ errors as they occur?
161
+ A: This is incorrect thinking. Allowing errors to just occur when
162
+ they happen is naive programming. Consider the following:
163
+
164
+ # Wait N seconds, then open the bridge for M seconds
165
+ def sendMsg(bridge, n, m)
166
+ sleep(n)
167
+ bridge.open
168
+ sleep(m)
169
+ bridge.close
170
+ end
171
+
172
+ Now say 'm' is pased in as a string. Oops! A TypeError is
173
+ raised. Now the bridge is open, and somewhere (hopefully!) someone
174
+ caught the exception so the program didn't crash, but the bridge
175
+ opening wasn't reversed, so it's going to stay open and back up
176
+ traffic until someone fixes the problem.
177
+
178
+ This is an academic example, but there are many cases when just
179
+ letting an error happen will lead to an inconsistent system state.
180
+ Ruby (and most systems) are not transactional, and inconsistent
181
+ states are unacceptable.
182
+
183
+ In addition, it is desireable to know _programmatically_ why
184
+ something failed, as specific action can be taken if desired.
185
+
186
+ "Wait," someone in the audience says, "you could just check to see
187
+ if 'm' and 'n' are of the correct type!"
188
+
189
+ Yes, yes you could.
190
+
191
+ That's what this module is for. ;-)
192
+
193
+ Q: Isn't it up to the caller to call my function correctly?
194
+ A: The caller cannot know and deal with errors that may occur in your
195
+ code. That's your job. Checking for errors ahead of time and
196
+ informing the caller about problems is also your job. This module
197
+ just makes it easy.
198
+
199
+ In addition, it's nice for the caller to be able to ask and check
200
+ what your method expects ahead of time to guard against error.
201
+ The strongtyping module also provides functionality for this.
202
+
203
+ Q: OK, but strong typing is baaad. What if I want to pass something
204
+ that acts like something else, or responds to a given symbol?
205
+ Doesn't ruby have "duck" typing?
206
+ A: First, what you're suggesting is evil. If you want that, go
207
+ write C++. :-)
208
+
209
+ Second, you should never depend on a function's implementation. If
210
+ the documentation says "pass me a hash" and you pass it anything
211
+ that responds to :[], your code may break when the next version
212
+ comes out.
213
+
214
+ Third, if you pass something that responds accurately to the
215
+ _interface_ (methods provided by class or module) specified, then
216
+ that should be _of_ that class or module. This may not be the case
217
+ with all ruby objects yet; for instance, anything responding to :[]
218
+ being something like a Mappable. You can make this the case in
219
+ your code, or urge developers to create a standard set of interface
220
+ mixins for just this purpose.
221
+
222
+ "Duck" typing just a term for this sort of "maybe" behavior, much
223
+ like what C++ STL templates use. However, the problem is that even
224
+ if an object responds to a method, there is no guarantee that the
225
+ method acts in an expected manner---and the interface may still
226
+ change without notice. "Duck" typing sounds much like 'duct
227
+ taping' depending on your accent, and I think duct-taping is a good
228
+ description of this is in practice. :-)
229
+
230
+ Another argument is that ruby allows one to change the behavior of
231
+ methods at any time:
232
+
233
+ a = String.new;
234
+ def a.split
235
+ print "hello world\n"
236
+ end
237
+
238
+ For this, I have two responses: first, if a method is deprecated
239
+ or changed dramatically, strongtyping can aid in letting the code
240
+ know:
241
+
242
+ a = String.new;
243
+ def a.split(*args)
244
+ overload(args) { print "hello world\n" }
245
+ overload_default args
246
+ end
247
+
248
+ This case will drop any normal calls through to overload_default,
249
+ raising an exception, which can be caught and analyzed. You can
250
+ even provide another case that calls the superclass.
251
+
252
+ Second, either you're changing the method in a subtle manner (it
253
+ does what it used to, with added effect), or an outrageous manner
254
+ (it acts nothing like it did before). In the former case, code
255
+ should work fine anyway. In the latter case, as in the above
256
+ example, you should ask yourself why you're changing it. The
257
+ function no longer splits, why is it called split? This is not
258
+ good design; the strongtyping module is here to aid in good design,
259
+ not prevent poor design.
260
+
261
+ A more realistic example would be the academic "Shape" class
262
+ example of inheritance, with "Ellipse" and "Circle". Ruby properly
263
+ allows one to make Circle a subclass of Ellipse, and redefine
264
+ "setSize" to the constrained definition of a circle. This change
265
+ is visible to code---an ArgumentError will be raised (2 arguments
266
+ for 1), or setSize can throw a ConstraintError. strongtyping
267
+ provides a useful function, overload_exception, for just this case:
268
+
269
+ class Circle < Ellipse
270
+ :
271
+ def setSize(*args)
272
+ overload(args, Integer) {
273
+ | r |
274
+ @radius = r
275
+ return
276
+ }
277
+
278
+ overload_exception(args, Integer, Integer) {
279
+ | a, b |
280
+ raise ConstraintError
281
+ }
282
+
283
+ overload_default args
284
+ end
285
+ :
286
+ end
287
+
288
+ Of course, there are a number of good choices for handling
289
+ this... you may still allow #setSize(a, b) if a == b. The
290
+ important part is that the change in behavior can now be determined
291
+ by code.
292
+
293
+ Q: But I always write perfect code. I know what my functions do, and
294
+ what they take, and what I'm passing them.
295
+ A: No one writes perfect code. Additionally, not all environments are
296
+ as controlled as yours may be. Especially in a networked
297
+ environment when someone may be invoking a method remotely, you
298
+ can't depend on calling code not to be malicious.
299
+
300
+ Q: OK, OK. But, uh... what is Mephle?
301
+ A: Mephle is a soon-to-be-released network-transparent persistant
302
+ object system written in ruby. It uses many of the Unity concepts
303
+ (http://unity-project.sf.net/). It will be on the RAA when
304
+ released.
305
+
306
+ = License
307
+ strongtyping - Method parameter checking for Ruby
308
+ Copyright (C) 2003-2011 Ryan Pavlik
309
+
310
+ This library is free software; you can redistribute it and/or
311
+ modify it under the terms of the GNU Lesser General Public
312
+ License as published by the Free Software Foundation; either
313
+ version 2.1 of the License, or (at your option) any later version.
314
+
315
+ This library is distributed in the hope that it will be useful,
316
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
317
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
318
+ Lesser General Public License for more details.
319
+
320
+ You should have received a copy of the GNU Lesser General Public
321
+ License along with this library; if not, write to the Free Software
322
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
323
+
324
+ = Future Plans
325
+ There's some odd C code that is causing a couple of warnings, but it
326
+ does not appear to be harmful. I want to clean this code up eventually.
327
+
328
+ = Authors
329
+ * Ryan Pavlik (original author)
330
+ * Daniel Berger (maintenance)
@@ -0,0 +1,48 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/testtask'
4
+ require 'rbconfig'
5
+ include Config
6
+
7
+ CLEAN.include(
8
+ '**/*.gem', # Gem files
9
+ '**/*.rbc', # Rubinius
10
+ '**/*.o', # C object file
11
+ '**/*.log', # Ruby extension build log
12
+ '**/Makefile', # C Makefile
13
+ '**/conftest.dSYM', # OS X build directory
14
+ "**/*.#{CONFIG['DLEXT']}" # C shared object
15
+ )
16
+
17
+ desc "Build the strongtyping source"
18
+ task :build => [:clean] do
19
+ make = File::ALT_SEPARATOR ? "nmake" : "make"
20
+ Dir.chdir('ext') do
21
+ ruby 'extconf.rb'
22
+ sh "#{make}"
23
+ end
24
+ end
25
+
26
+ namespace 'gem' do
27
+ desc 'Create the strongtyping gem'
28
+ task :create => [:clean] do
29
+ Dir["*.gem"].each{ |f| File.delete(f) } # Clean first
30
+ spec = eval(IO.read('strongtyping.gemspec'))
31
+ Gem::Builder.new(spec).build
32
+ end
33
+
34
+ desc 'Install the strongtyping gem'
35
+ task :install => [:create] do
36
+ file = Dir["*.gem"].first
37
+ sh "gem install #{file}"
38
+ end
39
+ end
40
+
41
+ Rake::TestTask.new do |t|
42
+ task :test => :build
43
+ t.libs << 'ext'
44
+ t.verbose = true
45
+ t.warning = true
46
+ end
47
+
48
+ task :default => :test
@@ -1,3 +1,3 @@
1
- require 'mkmf'
2
-
3
- create_makefile "strongtyping"
1
+ require 'mkmf'
2
+
3
+ create_makefile "strongtyping"
@@ -0,0 +1,283 @@
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
+ /* Ruby 1.9.x */
24
+ #ifndef RSTRING_PTR
25
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
26
+ #endif
27
+ #ifndef RSTRING_LEN
28
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
29
+ #endif
30
+
31
+ #ifndef RARRAY_PTR
32
+ #define RARRAY_PTR(a) (RARRAY(a)->ptr)
33
+ #endif
34
+ #ifndef RARRAY_LEN
35
+ #define RARRAY_LEN(a) (RARRAY(a)->len)
36
+ #endif
37
+
38
+ static int check_args(int argc, VALUE *obj, VALUE *mod);
39
+
40
+ static VALUE strongtyping_expect(int argc, VALUE *argv, VALUE self UNUSED) {
41
+ int i = 0;
42
+ VALUE obj[MAXARGS], mod[MAXARGS];
43
+ VALUE typestr;
44
+
45
+ if(!argc)
46
+ return Qnil;
47
+
48
+ if(argc % 2)
49
+ rb_raise(rb_eSyntaxError, "expect() requires argument pairs");
50
+
51
+ #ifndef __GNUC__
52
+ if(argc*2 > MAXARGS*2)
53
+ rb_raise(rb_eSyntaxError, "too many arguments to expect()");
54
+ #endif
55
+
56
+ for(i = 0; i < argc; i += 2) {
57
+ obj[i/2] = argv[i];
58
+ mod[(i+1)/2] = argv[i+1];
59
+ }
60
+
61
+ if(rb_funcall(obj[0], id_isa, 1, cQueryParams)) {
62
+ rb_funcall(obj[0], rb_intern("<<"), 1, rb_ary_new4(argc/2, mod));
63
+ rb_raise(eArgList, ""); // TODO: Why an empty string? Causes a warning in 1.9.x.
64
+ }
65
+
66
+ i = check_args(argc / 2, obj, mod);
67
+
68
+ if(i < 0)
69
+ return Qnil;
70
+
71
+ typestr = rb_funcall(mod[i], id_inspect, 0);
72
+
73
+ rb_raise(
74
+ eArgumentTypeError,
75
+ "Expecting %s as argument %d, got %s",
76
+ RSTRING_PTR(typestr), i + 1,
77
+ rb_class2name(rb_funcall(obj[i], id_class, 0))
78
+ );
79
+ }
80
+
81
+ static VALUE strongtyping_overload(int argc, VALUE *argv, VALUE self UNUSED) {
82
+ struct RArray *q;
83
+
84
+ if(argc < 1)
85
+ rb_raise(rb_eArgError, "At least one parameter required");
86
+
87
+ Check_Type(argv[0], T_ARRAY);
88
+ q = RARRAY(argv[0]);
89
+
90
+ if(RARRAY_LEN(q) && rb_funcall(RARRAY_PTR(q)[0], id_isa, 1, cQueryParams)) {
91
+ rb_funcall(RARRAY_PTR(q)[0], rb_intern("<<"), 1, rb_ary_new4(argc - 1, argv + 1));
92
+ return Qnil;
93
+ }
94
+
95
+ if(RARRAY_LEN(q) != (argc - 1))
96
+ return Qnil;
97
+
98
+ if(check_args(argc - 1, RARRAY_PTR(q), argv + 1) < 0){
99
+ if(argc == 2)
100
+ rb_yield(*RARRAY_PTR(*argv));
101
+ else
102
+ rb_yield(*argv);
103
+ }
104
+
105
+ return Qnil;
106
+ }
107
+
108
+ static VALUE strongtyping_overload_exception(int argc, VALUE *argv, VALUE self UNUSED) {
109
+ struct RArray *q;
110
+
111
+ if(argc < 1)
112
+ rb_raise(rb_eArgError, "At least one parameters required");
113
+
114
+ Check_Type(argv[0], T_ARRAY);
115
+ q = RARRAY(argv[0]);
116
+
117
+ if(RARRAY_LEN(q) && (argc - 1) == 0)
118
+ return Qnil;
119
+
120
+ if(check_args(argc - 1, RARRAY_PTR(q), argv + 1) < 0)
121
+ rb_yield(argv[0]);
122
+
123
+ return Qnil;
124
+ }
125
+
126
+ static VALUE strongtyping_overload_error(VALUE self UNUSED, VALUE args) {
127
+ struct RArray *q;
128
+ VALUE classlist;
129
+ const char *name = 0;
130
+ int i = 0;
131
+
132
+ Check_Type(args, T_ARRAY);
133
+ q = RARRAY(args);
134
+
135
+ if(RARRAY_LEN(q) && rb_funcall(RARRAY_PTR(q)[0], id_isa, 1, cQueryParams))
136
+ rb_raise(eArgList, "");
137
+
138
+ classlist = rb_str_new2("");
139
+
140
+ for(i = 0; i < RARRAY_LEN(q); i++) {
141
+ if(i > 0)
142
+ rb_str_cat(classlist, ", ", 2);
143
+
144
+ name = rb_class2name(rb_funcall(RARRAY_PTR(q)[i], id_class, 0));
145
+ rb_str_cat(classlist, name, strlen(name));
146
+ }
147
+
148
+ rb_raise(
149
+ eOverloadError,
150
+ "No matching template for arguments: [%s]",
151
+ RSTRING_PTR(classlist)
152
+ );
153
+ }
154
+
155
+ static int check_args(int argc, VALUE *obj, VALUE *mod) {
156
+ int i = 0;
157
+ VALUE ret;
158
+
159
+ for(i = 0; i < argc; i++){
160
+ if(TYPE(mod[i]) == T_ARRAY){
161
+ int j = 0, ok = 0;
162
+
163
+ for(j = 0; j < RARRAY_LEN(mod[i]); j++){
164
+ if(rb_funcall(obj[i], id_isa, 1, RARRAY_PTR(mod[i])[j]) == Qtrue)
165
+ ok = 1;
166
+ }
167
+
168
+ if(ok)
169
+ continue;
170
+ else
171
+ return i;
172
+ }
173
+ else{
174
+ ret = rb_funcall(obj[i], id_isa, 1, mod[i]);
175
+ if(ret == Qfalse) return i;
176
+ }
177
+ }
178
+
179
+ return -1;
180
+ }
181
+
182
+ static VALUE call_method(VALUE ary) {
183
+ VALUE method = RARRAY_PTR(ary)[0],
184
+ query = RARRAY_PTR(ary)[1];
185
+ VALUE *argv = NULL;
186
+ VALUE ret;
187
+ int argc = 0,
188
+ i = 0;
189
+
190
+ argc = FIX2INT(rb_funcall(method, rb_intern("arity"), 0));
191
+
192
+ if(argc == 0) {
193
+ rb_funcall(query, rb_intern("<<"), 1, rb_ary_new());
194
+ rb_raise(eArgList, "");
195
+ }
196
+ else if(argc < 0)
197
+ argc = -argc;
198
+
199
+ argv = malloc(sizeof(VALUE) * argc);
200
+ argv[0] = query;
201
+
202
+ for(i = 1; i < argc - 1; i++)
203
+ argv[i] = Qnil;
204
+
205
+ ret = rb_funcall2(method, rb_intern("call"), argc, argv);
206
+ free(argv);
207
+
208
+ return ret;
209
+ }
210
+
211
+ static VALUE grab_types(VALUE query) {
212
+ return query;
213
+ }
214
+
215
+ static VALUE strongtyping_get_arg_types(VALUE obj UNUSED, VALUE method) {
216
+ VALUE query, ary;
217
+ query = rb_funcall(cQueryParams, rb_intern("new"), 0);
218
+ ary = rb_ary_new3(2, method, query);
219
+
220
+ return rb_rescue2(call_method, ary, grab_types, query, eArgList, 0);
221
+ }
222
+
223
+ static VALUE strongtyping_verify_args_for(VALUE self, VALUE method, VALUE args) {
224
+ struct RArray *list = NULL;
225
+ struct RArray *t = NULL;
226
+ struct RArray *a = NULL;
227
+ int i = 0;
228
+ VALUE template = strongtyping_get_arg_types(self, method);
229
+
230
+ list = RARRAY(template);
231
+ a = RARRAY(args);
232
+
233
+ for(i = 0; i < RARRAY_LEN(list); i++){
234
+ t = RARRAY_PTR(list)[i];
235
+
236
+ if(RARRAY_LEN(a) != RARRAY_LEN(t))
237
+ continue;
238
+
239
+ if(check_args(RARRAY_LEN(a), RARRAY_PTR(a), RARRAY_PTR(t)) < 0)
240
+ return Qtrue;
241
+ }
242
+
243
+ return Qfalse;
244
+ }
245
+
246
+ void Init_strongtyping() {
247
+ mStrongTyping = rb_define_module("StrongTyping");
248
+ id_isa = rb_intern("is_a?");
249
+ id_class = rb_intern("class");
250
+ id_inspect = rb_intern("inspect");
251
+
252
+ /* 2.0.7: The version of the strongtyping library */
253
+ rb_define_const(mStrongTyping, "VERSION", rb_str_new2("2.0.7"));
254
+
255
+ cQueryParams = rb_define_class_under(mStrongTyping,
256
+ "%QueryParams",
257
+ rb_cArray);
258
+
259
+ eArgumentTypeError = rb_define_class_under(mStrongTyping,
260
+ "ArgumentTypeError",
261
+ rb_eArgError);
262
+ eOverloadError = rb_define_class_under(mStrongTyping,
263
+ "OverloadError",
264
+ eArgumentTypeError);
265
+ eArgList = rb_define_class_under(mStrongTyping,
266
+ "%ArgList",
267
+ rb_eException);
268
+
269
+ rb_define_module_function(mStrongTyping, "expect",
270
+ strongtyping_expect, -1);
271
+ rb_define_module_function(mStrongTyping, "overload",
272
+ strongtyping_overload, -1);
273
+ rb_define_module_function(mStrongTyping, "overload_exception",
274
+ strongtyping_overload_exception, -1);
275
+ rb_define_module_function(mStrongTyping, "overload_default",
276
+ strongtyping_overload_error, 1);
277
+ rb_define_module_function(mStrongTyping, "overload_error",
278
+ strongtyping_overload_error, 1);
279
+ rb_define_module_function(mStrongTyping, "get_arg_types",
280
+ strongtyping_get_arg_types, 1);
281
+ rb_define_module_function(mStrongTyping, "verify_args_for",
282
+ strongtyping_verify_args_for, 2);
283
+ }