multimethod 0.0.1
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/.svn/README.txt +2 -0
- data/.svn/empty-file +0 -0
- data/.svn/entries +68 -0
- data/.svn/format +1 -0
- data/.svn/text-base/ChangeLog.svn-base +3 -0
- data/.svn/text-base/Manifest.txt.svn-base +54 -0
- data/.svn/text-base/README.txt.svn-base +40 -0
- data/.svn/text-base/Rakefile.svn-base +132 -0
- data/.svn/text-base/Releases.txt.svn-base +7 -0
- data/ChangeLog +3 -0
- data/Manifest.txt +54 -0
- data/README.txt +40 -0
- data/Rakefile +132 -0
- data/Releases.txt +7 -0
- data/examples/.svn/README.txt +2 -0
- data/examples/.svn/empty-file +0 -0
- data/examples/.svn/entries +22 -0
- data/examples/.svn/format +1 -0
- data/examples/.svn/props/ex1.rb.svn-work +5 -0
- data/examples/ex1.rb +26 -0
- data/lib/.svn/README.txt +2 -0
- data/lib/.svn/empty-file +0 -0
- data/lib/.svn/entries +24 -0
- data/lib/.svn/format +1 -0
- data/lib/.svn/text-base/multimethod.rb.svn-base +8 -0
- data/lib/multimethod.rb +8 -0
- data/lib/multimethod/.svn/README.txt +2 -0
- data/lib/multimethod/.svn/empty-file +0 -0
- data/lib/multimethod/.svn/entries +53 -0
- data/lib/multimethod/.svn/format +1 -0
- data/lib/multimethod/.svn/text-base/core_extensions.rb.svn-base +38 -0
- data/lib/multimethod/.svn/text-base/method.rb.svn-base +232 -0
- data/lib/multimethod/.svn/text-base/multimethod.rb.svn-base +171 -0
- data/lib/multimethod/.svn/text-base/parameter.rb.svn-base +64 -0
- data/lib/multimethod/.svn/text-base/table.rb.svn-base +99 -0
- data/lib/multimethod/core_extensions.rb +38 -0
- data/lib/multimethod/method.rb +232 -0
- data/lib/multimethod/multimethod.rb +171 -0
- data/lib/multimethod/parameter.rb +64 -0
- data/lib/multimethod/table.rb +99 -0
- data/test/.svn/README.txt +2 -0
- data/test/.svn/empty-file +0 -0
- data/test/.svn/entries +53 -0
- data/test/.svn/format +1 -0
- data/test/.svn/text-base/method_test.rb.svn-base +89 -0
- data/test/.svn/text-base/multimethod_test.rb.svn-base +92 -0
- data/test/.svn/text-base/parameter_test.rb.svn-base +31 -0
- data/test/.svn/text-base/test_base.rb.svn-base +25 -0
- data/test/.svn/text-base/usage_test.rb.svn-base +146 -0
- data/test/method_test.rb +89 -0
- data/test/multimethod_test.rb +92 -0
- data/test/parameter_test.rb +31 -0
- data/test/test_base.rb +25 -0
- data/test/usage_test.rb +146 -0
- metadata +108 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test_base'
|
2
|
+
|
3
|
+
module Multimethod
|
4
|
+
|
5
|
+
class MethodTest < TestBase
|
6
|
+
|
7
|
+
class A < Object; end
|
8
|
+
class B < A; end
|
9
|
+
class C < Object; end
|
10
|
+
class D < B; end
|
11
|
+
class E < A; end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_score
|
18
|
+
# Make some argument lists.
|
19
|
+
types = [ A, B, C, D, E ]
|
20
|
+
a = { }
|
21
|
+
c = { }
|
22
|
+
types.each do |t1|
|
23
|
+
n1 = t1.name.clone
|
24
|
+
n1.sub!(/^.*::/, '')
|
25
|
+
n1 = n1[0..0]
|
26
|
+
types.each do |t2|
|
27
|
+
n2 = t2.name.clone
|
28
|
+
n2.sub!(/^.*::/, '')
|
29
|
+
n2 = n2[0..0]
|
30
|
+
|
31
|
+
symbol = "#{n1.downcase}_#{n2.downcase}".intern
|
32
|
+
a[symbol] = [ 1, t1.new, t2.new ]
|
33
|
+
c[symbol] = a[symbol].collect{|x| x.class}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rs = Parameter::RESTARG_SCORE
|
38
|
+
|
39
|
+
assert_not_nil m1 = Method.new(Object, :m, [ A, :x, A, :y ])
|
40
|
+
assert_equal 3, m1.min_args
|
41
|
+
assert_equal 3, m1.max_args
|
42
|
+
|
43
|
+
assert_not_nil m2 = Method.new(Object, :m, [ B, :x, A, :y ])
|
44
|
+
assert_equal 3, m2.min_args
|
45
|
+
assert_equal 3, m2.max_args
|
46
|
+
|
47
|
+
assert_not_nil m3 = Method.new(Object, :m, [ C, :x, '*rest' ])
|
48
|
+
assert_equal 2, m3.min_args
|
49
|
+
assert_equal nil, m3.max_args
|
50
|
+
assert_not_nil m3.restarg
|
51
|
+
|
52
|
+
assert_not_nil m4 = Method.new(Object, :m, [ D, :x, :y ])
|
53
|
+
assert_equal 3, m4.min_args
|
54
|
+
assert_equal 3, m4.max_args
|
55
|
+
|
56
|
+
assert_not_nil m5 = Method.new(Object, :m, [ E, :y, :y ])
|
57
|
+
assert_equal 3, m4.min_args
|
58
|
+
assert_equal 3, m4.max_args
|
59
|
+
|
60
|
+
# 5 == 1.class.ancestors.index(Object)
|
61
|
+
assert_equal [ 5, 0, 0 ] , m1.score(c[:a_a])
|
62
|
+
assert_equal [ 5, 0, 1 ] , m1.score(c[:a_b])
|
63
|
+
assert_equal nil , m1.score(c[:a_c])
|
64
|
+
assert_equal [ 5, 1, 1 ] , m1.score(c[:b_b])
|
65
|
+
assert_equal nil , m1.score(c[:c_a])
|
66
|
+
assert_equal [ 5, 1, 2 ] , m1.score(c[:b_d])
|
67
|
+
|
68
|
+
assert_equal nil , m3.score(c[:a_a])
|
69
|
+
assert_equal nil , m3.score(c[:a_b])
|
70
|
+
assert_equal nil , m3.score(c[:b_b])
|
71
|
+
assert_equal [ 5, 0, rs ] , m3.score(c[:c_a])
|
72
|
+
assert_equal [ 5, 0, rs ] , m3.score(c[:c_c])
|
73
|
+
|
74
|
+
# Create a multimethod for later.
|
75
|
+
assert_not_nil mm = Multimethod.new(:test)
|
76
|
+
mm.add_method(m1)
|
77
|
+
mm.add_method(m2)
|
78
|
+
mm.add_method(m3)
|
79
|
+
mm.add_method(m4)
|
80
|
+
|
81
|
+
# Check method lookup.
|
82
|
+
assert_equal m1 , mm.lookup_method_(c[:a_a])
|
83
|
+
assert_equal m2 , mm.lookup_method_(c[:b_a])
|
84
|
+
assert_equal m2 , mm.lookup_method_(c[:b_b])
|
85
|
+
|
86
|
+
mm
|
87
|
+
end
|
88
|
+
|
89
|
+
end # class
|
90
|
+
|
91
|
+
end # module
|
92
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_base'
|
2
|
+
|
3
|
+
module Multimethod
|
4
|
+
|
5
|
+
class ParameterTest < TestBase
|
6
|
+
|
7
|
+
class A < Object; end
|
8
|
+
class B < A; end
|
9
|
+
class C < Object; end
|
10
|
+
class D < B; end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_score
|
17
|
+
pA = Parameter.new(:a, A)
|
18
|
+
assert_equal 0, pA.score(A)
|
19
|
+
assert_equal 1, pA.score(B)
|
20
|
+
assert_equal nil, pA.score(C)
|
21
|
+
assert_equal 2, pA.score(D)
|
22
|
+
|
23
|
+
pB = Parameter.new(:b, B)
|
24
|
+
assert_equal nil, pB.score(A)
|
25
|
+
assert_equal 0, pB.score(B)
|
26
|
+
assert_equal nil, pB.score(C)
|
27
|
+
assert_equal 1, pB.score(D)
|
28
|
+
end
|
29
|
+
end # class
|
30
|
+
|
31
|
+
end # module
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'multimethod'
|
3
|
+
|
4
|
+
module Multimethod
|
5
|
+
|
6
|
+
class TestBase < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
# Avoid "No test were specified" error.
|
12
|
+
def test_foo
|
13
|
+
assert true
|
14
|
+
end
|
15
|
+
|
16
|
+
# Helpers.
|
17
|
+
def assert_equal_float(x, y, eps = 1.0e-8)
|
18
|
+
d = (x * eps).abs
|
19
|
+
assert (x - d) <= y
|
20
|
+
assert y <= (x + d)
|
21
|
+
end
|
22
|
+
|
23
|
+
end # class
|
24
|
+
|
25
|
+
end # module
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'test_base'
|
2
|
+
|
3
|
+
|
4
|
+
class A < Object
|
5
|
+
multimethod %q{
|
6
|
+
def foo(x)
|
7
|
+
x = "A#foo(x) : (#{x.class.name})"
|
8
|
+
x
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
multimethod %q{
|
13
|
+
def foo(A x)
|
14
|
+
x = "A#foo(A x) : (#{x.class.name})"
|
15
|
+
x
|
16
|
+
end
|
17
|
+
}
|
18
|
+
|
19
|
+
multimethod %q{
|
20
|
+
def foo(B x)
|
21
|
+
x = "A#foo(B x) : (#{x.class.name})"
|
22
|
+
x
|
23
|
+
end
|
24
|
+
}
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class B < A
|
29
|
+
multimethod %q{
|
30
|
+
def foo(B x)
|
31
|
+
x = "B#foo(B x) : (#{x.class.name})"
|
32
|
+
x
|
33
|
+
end
|
34
|
+
}
|
35
|
+
|
36
|
+
multimethod %q{
|
37
|
+
def foo(Comparable x)
|
38
|
+
x = "B#foo(Comparable x) : (#{x.class.name})"
|
39
|
+
x
|
40
|
+
end
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class C < Object
|
47
|
+
include Comparable
|
48
|
+
end
|
49
|
+
|
50
|
+
class D < B
|
51
|
+
# Variadic
|
52
|
+
multimethod %q{
|
53
|
+
def bar(x)
|
54
|
+
x = "D#bar(x) : (#{x.class.name})"
|
55
|
+
x
|
56
|
+
end
|
57
|
+
}
|
58
|
+
|
59
|
+
multimethod %q{
|
60
|
+
def bar(*rest)
|
61
|
+
x = "D#bar(*rest) : (#{rest.inspect})"
|
62
|
+
x
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
multimethod %q{
|
67
|
+
def bar(x, y)
|
68
|
+
x = "D#bar(x, y) : (#{x.class.name}, #{y.class.name})"
|
69
|
+
x
|
70
|
+
end
|
71
|
+
}
|
72
|
+
|
73
|
+
multimethod %q{
|
74
|
+
def bar(x, y, A a)
|
75
|
+
x = "D#bar(x, y, A a) : (#{x.class.name}, #{y.class.name}, #{a.class.name})"
|
76
|
+
x
|
77
|
+
end
|
78
|
+
}
|
79
|
+
|
80
|
+
multimethod %q{
|
81
|
+
def bar(x, y, *rest)
|
82
|
+
x = "D#bar(x, y, *rest) : (#{x.class.name}, #{y.class.name}, #{rest.inspect})"
|
83
|
+
x
|
84
|
+
end
|
85
|
+
}
|
86
|
+
|
87
|
+
end # class D
|
88
|
+
|
89
|
+
class E < A
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
module Multimethod
|
94
|
+
|
95
|
+
class UsageTest < TestBase
|
96
|
+
|
97
|
+
def setup
|
98
|
+
super
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_call
|
102
|
+
a = A.new
|
103
|
+
b = B.new
|
104
|
+
c = C.new
|
105
|
+
d = D.new
|
106
|
+
e = E.new
|
107
|
+
|
108
|
+
assert_equal 'A#foo(x) : (Fixnum)' , a.foo(1)
|
109
|
+
assert_equal 'A#foo(A x) : (A)' , a.foo(a)
|
110
|
+
assert_equal 'A#foo(B x) : (B)' , a.foo(b)
|
111
|
+
assert_equal 'A#foo(x) : (C)' , a.foo(c)
|
112
|
+
assert_equal 'A#foo(B x) : (D)' , a.foo(d)
|
113
|
+
assert_equal 'A#foo(A x) : (E)' , a.foo(e)
|
114
|
+
|
115
|
+
assert_equal 'A#foo(x) : (Symbol)' , b.foo(:x)
|
116
|
+
assert_equal 'B#foo(Comparable x) : (Fixnum)' , b.foo(1)
|
117
|
+
assert_equal 'A#foo(A x) : (A)' , b.foo(a)
|
118
|
+
assert_equal 'B#foo(B x) : (B)' , b.foo(b)
|
119
|
+
assert_equal 'B#foo(Comparable x) : (C)' , b.foo(c)
|
120
|
+
assert_equal 'B#foo(B x) : (D)' , b.foo(d)
|
121
|
+
assert_equal 'A#foo(A x) : (E)' , b.foo(e)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_variadic
|
125
|
+
a = A.new
|
126
|
+
d = D.new
|
127
|
+
|
128
|
+
assert_equal 'D#bar(*rest) : ([])',
|
129
|
+
d.bar()
|
130
|
+
|
131
|
+
assert_equal 'D#bar(x) : (Fixnum)',
|
132
|
+
d.bar(1)
|
133
|
+
|
134
|
+
assert_equal 'D#bar(x, y) : (Fixnum, String)' ,
|
135
|
+
d.bar(1, 'a')
|
136
|
+
|
137
|
+
assert_equal 'D#bar(x, y, A a) : (Fixnum, String, A)' ,
|
138
|
+
d.bar(1, 'a', a)
|
139
|
+
|
140
|
+
assert_equal 'D#bar(x, y, *rest) : (Fixnum, String, [3])' ,
|
141
|
+
d.bar(1, 'a', 3)
|
142
|
+
end
|
143
|
+
|
144
|
+
end # class
|
145
|
+
|
146
|
+
end # module
|
data/test/method_test.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test_base'
|
2
|
+
|
3
|
+
module Multimethod
|
4
|
+
|
5
|
+
class MethodTest < TestBase
|
6
|
+
|
7
|
+
class A < Object; end
|
8
|
+
class B < A; end
|
9
|
+
class C < Object; end
|
10
|
+
class D < B; end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_scan_parameter
|
17
|
+
assert_not_nil m1 = Method.new(Object, :m, [ A, :a, B, :b, :c, '*d' ])
|
18
|
+
|
19
|
+
assert_equal 5, m1.parameter.size
|
20
|
+
|
21
|
+
i = -1
|
22
|
+
|
23
|
+
i = i + 1
|
24
|
+
assert_equal :self, m1.parameter[i].name
|
25
|
+
assert_equal Object, m1.parameter[i].type
|
26
|
+
assert ! m1.parameter[i].restarg
|
27
|
+
|
28
|
+
i = i + 1
|
29
|
+
assert_equal :a, m1.parameter[i].name
|
30
|
+
assert_equal A, m1.parameter[i].type
|
31
|
+
assert ! m1.parameter[i].restarg
|
32
|
+
|
33
|
+
i = i + 1
|
34
|
+
assert_equal :b, m1.parameter[i].name
|
35
|
+
assert_equal B, m1.parameter[i].type
|
36
|
+
assert ! m1.parameter[i].restarg
|
37
|
+
|
38
|
+
i = i + 1
|
39
|
+
assert_equal :c, m1.parameter[i].name
|
40
|
+
assert_equal Kernel, m1.parameter[i].type
|
41
|
+
assert ! m1.parameter[i].restarg
|
42
|
+
|
43
|
+
i = i + 1
|
44
|
+
assert_equal :d, m1.parameter[i].name
|
45
|
+
assert_equal Kernel, m1.parameter[i].type
|
46
|
+
assert m1.parameter[i].restarg
|
47
|
+
|
48
|
+
m1
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_scan_parameter_string
|
52
|
+
assert_not_nil m1 = Method.new(Object, :m, 'A a, B b, c = nil, *d')
|
53
|
+
|
54
|
+
assert_equal 5, m1.parameter.size
|
55
|
+
|
56
|
+
i = -1
|
57
|
+
|
58
|
+
i = i + 1
|
59
|
+
assert_equal :self, m1.parameter[i].name
|
60
|
+
assert_equal Object, m1.parameter[i].type
|
61
|
+
assert ! m1.parameter[i].restarg
|
62
|
+
|
63
|
+
i = i + 1
|
64
|
+
assert_equal :a, m1.parameter[i].name
|
65
|
+
assert_equal 'A', m1.parameter[i].type
|
66
|
+
assert ! m1.parameter[i].restarg
|
67
|
+
|
68
|
+
i = i + 1
|
69
|
+
assert_equal :b, m1.parameter[i].name
|
70
|
+
assert_equal 'B', m1.parameter[i].type
|
71
|
+
assert ! m1.parameter[i].restarg
|
72
|
+
|
73
|
+
i = i + 1
|
74
|
+
assert_equal :c, m1.parameter[i].name
|
75
|
+
assert_equal Kernel, m1.parameter[i].type
|
76
|
+
assert ! m1.parameter[i].restarg
|
77
|
+
|
78
|
+
i = i + 1
|
79
|
+
assert_equal :d, m1.parameter[i].name
|
80
|
+
assert_equal Kernel, m1.parameter[i].type
|
81
|
+
assert m1.parameter[i].restarg
|
82
|
+
|
83
|
+
m1
|
84
|
+
end
|
85
|
+
|
86
|
+
end # class
|
87
|
+
|
88
|
+
end # module
|
89
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test_base'
|
2
|
+
|
3
|
+
module Multimethod
|
4
|
+
|
5
|
+
class MethodTest < TestBase
|
6
|
+
|
7
|
+
class A < Object; end
|
8
|
+
class B < A; end
|
9
|
+
class C < Object; end
|
10
|
+
class D < B; end
|
11
|
+
class E < A; end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_score
|
18
|
+
# Make some argument lists.
|
19
|
+
types = [ A, B, C, D, E ]
|
20
|
+
a = { }
|
21
|
+
c = { }
|
22
|
+
types.each do |t1|
|
23
|
+
n1 = t1.name.clone
|
24
|
+
n1.sub!(/^.*::/, '')
|
25
|
+
n1 = n1[0..0]
|
26
|
+
types.each do |t2|
|
27
|
+
n2 = t2.name.clone
|
28
|
+
n2.sub!(/^.*::/, '')
|
29
|
+
n2 = n2[0..0]
|
30
|
+
|
31
|
+
symbol = "#{n1.downcase}_#{n2.downcase}".intern
|
32
|
+
a[symbol] = [ 1, t1.new, t2.new ]
|
33
|
+
c[symbol] = a[symbol].collect{|x| x.class}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rs = Parameter::RESTARG_SCORE
|
38
|
+
|
39
|
+
assert_not_nil m1 = Method.new(Object, :m, [ A, :x, A, :y ])
|
40
|
+
assert_equal 3, m1.min_args
|
41
|
+
assert_equal 3, m1.max_args
|
42
|
+
|
43
|
+
assert_not_nil m2 = Method.new(Object, :m, [ B, :x, A, :y ])
|
44
|
+
assert_equal 3, m2.min_args
|
45
|
+
assert_equal 3, m2.max_args
|
46
|
+
|
47
|
+
assert_not_nil m3 = Method.new(Object, :m, [ C, :x, '*rest' ])
|
48
|
+
assert_equal 2, m3.min_args
|
49
|
+
assert_equal nil, m3.max_args
|
50
|
+
assert_not_nil m3.restarg
|
51
|
+
|
52
|
+
assert_not_nil m4 = Method.new(Object, :m, [ D, :x, :y ])
|
53
|
+
assert_equal 3, m4.min_args
|
54
|
+
assert_equal 3, m4.max_args
|
55
|
+
|
56
|
+
assert_not_nil m5 = Method.new(Object, :m, [ E, :y, :y ])
|
57
|
+
assert_equal 3, m4.min_args
|
58
|
+
assert_equal 3, m4.max_args
|
59
|
+
|
60
|
+
# 5 == 1.class.ancestors.index(Object)
|
61
|
+
assert_equal [ 5, 0, 0 ] , m1.score(c[:a_a])
|
62
|
+
assert_equal [ 5, 0, 1 ] , m1.score(c[:a_b])
|
63
|
+
assert_equal nil , m1.score(c[:a_c])
|
64
|
+
assert_equal [ 5, 1, 1 ] , m1.score(c[:b_b])
|
65
|
+
assert_equal nil , m1.score(c[:c_a])
|
66
|
+
assert_equal [ 5, 1, 2 ] , m1.score(c[:b_d])
|
67
|
+
|
68
|
+
assert_equal nil , m3.score(c[:a_a])
|
69
|
+
assert_equal nil , m3.score(c[:a_b])
|
70
|
+
assert_equal nil , m3.score(c[:b_b])
|
71
|
+
assert_equal [ 5, 0, rs ] , m3.score(c[:c_a])
|
72
|
+
assert_equal [ 5, 0, rs ] , m3.score(c[:c_c])
|
73
|
+
|
74
|
+
# Create a multimethod for later.
|
75
|
+
assert_not_nil mm = Multimethod.new(:test)
|
76
|
+
mm.add_method(m1)
|
77
|
+
mm.add_method(m2)
|
78
|
+
mm.add_method(m3)
|
79
|
+
mm.add_method(m4)
|
80
|
+
|
81
|
+
# Check method lookup.
|
82
|
+
assert_equal m1 , mm.lookup_method_(c[:a_a])
|
83
|
+
assert_equal m2 , mm.lookup_method_(c[:b_a])
|
84
|
+
assert_equal m2 , mm.lookup_method_(c[:b_b])
|
85
|
+
|
86
|
+
mm
|
87
|
+
end
|
88
|
+
|
89
|
+
end # class
|
90
|
+
|
91
|
+
end # module
|
92
|
+
|