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
data/Releases.txt
ADDED
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<wc-entries
|
3
|
+
xmlns="svn:">
|
4
|
+
<entry
|
5
|
+
committed-rev="4"
|
6
|
+
name=""
|
7
|
+
committed-date="2006-11-21T16:23:41.780783Z"
|
8
|
+
url="svn+ssh://rubyforge.org/var/svn/multimethod/multimethod/trunk/examples"
|
9
|
+
last-author="kstephens"
|
10
|
+
kind="dir"
|
11
|
+
repos="svn+ssh://rubyforge.org/var/svn/multimethod"
|
12
|
+
revision="4"/>
|
13
|
+
<entry
|
14
|
+
committed-rev="4"
|
15
|
+
name="ex1.rb"
|
16
|
+
text-time="2006-11-21T16:20:01.000000Z"
|
17
|
+
committed-date="2006-11-21T16:23:41.780783Z"
|
18
|
+
checksum="f101c5d90dab219e7170b1f5dc373a65"
|
19
|
+
last-author="kstephens"
|
20
|
+
kind="file"
|
21
|
+
prop-time="2006-11-21T16:20:23.000000Z"/>
|
22
|
+
</wc-entries>
|
@@ -0,0 +1 @@
|
|
1
|
+
4
|
data/examples/ex1.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'multimethod'
|
2
|
+
|
3
|
+
class A
|
4
|
+
multimethod %q{
|
5
|
+
def foo(x) # matches any argument type
|
6
|
+
"#{x.inspect}"
|
7
|
+
end
|
8
|
+
}
|
9
|
+
|
10
|
+
multimethod %q{
|
11
|
+
def foo(Fixnum x) # matches any Fixnum
|
12
|
+
"Fixnum #{x.inspect}"
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
multimethod %q{
|
17
|
+
def foo(Numeric x) # matches any Numeric
|
18
|
+
"Numeric #{x.inspect}"
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
a = A.new
|
24
|
+
puts a.foo(:symbol) # ==> ":symbol"
|
25
|
+
puts a.foo(45) # ==> "Fixnum 45"
|
26
|
+
puts a.foo(12.34) # ==> "Numeric 12.34"
|
data/lib/.svn/README.txt
ADDED
data/lib/.svn/empty-file
ADDED
File without changes
|
data/lib/.svn/entries
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<wc-entries
|
3
|
+
xmlns="svn:">
|
4
|
+
<entry
|
5
|
+
committed-rev="3"
|
6
|
+
name=""
|
7
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
8
|
+
url="svn+ssh://rubyforge.org/var/svn/multimethod/multimethod/trunk/lib"
|
9
|
+
last-author="kstephens"
|
10
|
+
kind="dir"
|
11
|
+
repos="svn+ssh://rubyforge.org/var/svn/multimethod"
|
12
|
+
revision="3"/>
|
13
|
+
<entry
|
14
|
+
name="multimethod"
|
15
|
+
kind="dir"/>
|
16
|
+
<entry
|
17
|
+
committed-rev="3"
|
18
|
+
name="multimethod.rb"
|
19
|
+
text-time="2006-11-21T01:47:12.000000Z"
|
20
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
21
|
+
checksum="2c65a931e6bd7e177e8996701aca212e"
|
22
|
+
last-author="kstephens"
|
23
|
+
kind="file"/>
|
24
|
+
</wc-entries>
|
data/lib/.svn/format
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
4
|
@@ -0,0 +1,8 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'multimethod/table'
|
5
|
+
require 'multimethod/multimethod'
|
6
|
+
require 'multimethod/method'
|
7
|
+
require 'multimethod/parameter'
|
8
|
+
require 'multimethod/core_extensions'
|
data/lib/multimethod.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'multimethod/table'
|
5
|
+
require 'multimethod/multimethod'
|
6
|
+
require 'multimethod/method'
|
7
|
+
require 'multimethod/parameter'
|
8
|
+
require 'multimethod/core_extensions'
|
File without changes
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<wc-entries
|
3
|
+
xmlns="svn:">
|
4
|
+
<entry
|
5
|
+
committed-rev="3"
|
6
|
+
name=""
|
7
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
8
|
+
url="svn+ssh://rubyforge.org/var/svn/multimethod/multimethod/trunk/lib/multimethod"
|
9
|
+
last-author="kstephens"
|
10
|
+
kind="dir"
|
11
|
+
repos="svn+ssh://rubyforge.org/var/svn/multimethod"
|
12
|
+
revision="3"/>
|
13
|
+
<entry
|
14
|
+
committed-rev="3"
|
15
|
+
name="method.rb"
|
16
|
+
text-time="2006-11-21T07:19:37.000000Z"
|
17
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
18
|
+
checksum="5135e392406babb4d5ffcca1a811af25"
|
19
|
+
last-author="kstephens"
|
20
|
+
kind="file"/>
|
21
|
+
<entry
|
22
|
+
committed-rev="3"
|
23
|
+
name="parameter.rb"
|
24
|
+
text-time="2006-11-21T07:10:23.000000Z"
|
25
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
26
|
+
checksum="60480a946dd2a2fab636bf4c58cb4573"
|
27
|
+
last-author="kstephens"
|
28
|
+
kind="file"/>
|
29
|
+
<entry
|
30
|
+
committed-rev="3"
|
31
|
+
name="core_extensions.rb"
|
32
|
+
text-time="2006-11-21T05:31:07.000000Z"
|
33
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
34
|
+
checksum="ef874d003a994297723e0f07542f168a"
|
35
|
+
last-author="kstephens"
|
36
|
+
kind="file"/>
|
37
|
+
<entry
|
38
|
+
committed-rev="3"
|
39
|
+
name="table.rb"
|
40
|
+
text-time="2006-11-21T06:52:05.000000Z"
|
41
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
42
|
+
checksum="899e5b9f61261a2e9b2da3d00a34d8db"
|
43
|
+
last-author="kstephens"
|
44
|
+
kind="file"/>
|
45
|
+
<entry
|
46
|
+
committed-rev="3"
|
47
|
+
name="multimethod.rb"
|
48
|
+
text-time="2006-11-21T07:30:13.000000Z"
|
49
|
+
committed-date="2006-11-21T15:59:22.761488Z"
|
50
|
+
checksum="32769979f54ce8f8d23f99f098150e1e"
|
51
|
+
last-author="kstephens"
|
52
|
+
kind="file"/>
|
53
|
+
</wc-entries>
|
@@ -0,0 +1 @@
|
|
1
|
+
4
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Multimethod
|
2
|
+
|
3
|
+
module ObjectExtension
|
4
|
+
def self.append_features(base) # :nodoc:
|
5
|
+
# puts "append_features{#{base}}"
|
6
|
+
super
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def multimethod(body, file = nil, line = nil)
|
12
|
+
unless file && line
|
13
|
+
fileline = caller(1)[0]
|
14
|
+
if fileline && md = /^(.*):(\d+)$/.match(fileline)
|
15
|
+
file, line = md[1], md[2].to_i
|
16
|
+
|
17
|
+
newlines = 0
|
18
|
+
body.gsub(/\n/s){|x| newlines = newlines + 1}
|
19
|
+
line -= newlines
|
20
|
+
end
|
21
|
+
|
22
|
+
# $stderr.puts "file = #{file.inspect}, line = #{line.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
::Multimethod::Table.instance.install_method(self, body, file, line)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end # class
|
29
|
+
end # module
|
30
|
+
|
31
|
+
|
32
|
+
# Add to Module
|
33
|
+
Object.class_eval do
|
34
|
+
include Multimethod::ObjectExtension
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,232 @@
|
|
1
|
+
module Multimethod
|
2
|
+
|
3
|
+
class Method
|
4
|
+
attr_accessor :mod
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :parameter
|
7
|
+
|
8
|
+
attr_accessor :min_args
|
9
|
+
attr_accessor :max_args
|
10
|
+
attr_accessor :restarg
|
11
|
+
attr_accessor :default
|
12
|
+
|
13
|
+
attr_accessor :multimethod
|
14
|
+
attr_accessor :file
|
15
|
+
attr_accessor :line
|
16
|
+
|
17
|
+
def initialize(mod, name, params)
|
18
|
+
raise NameError, "multimethod method name not specified" unless name && name.to_s.size > 0
|
19
|
+
|
20
|
+
name = Multimethod.normalize_name(name)
|
21
|
+
|
22
|
+
@mod = mod
|
23
|
+
@name = name
|
24
|
+
@parameter = [ ]
|
25
|
+
@min_args = 0
|
26
|
+
@max_args = 0
|
27
|
+
@restarg = nil
|
28
|
+
@default = nil
|
29
|
+
|
30
|
+
@score = { }
|
31
|
+
|
32
|
+
# Add self parameter at front.
|
33
|
+
add_parameter(Parameter.new('self', mod))
|
34
|
+
|
35
|
+
# Handle other parameters.
|
36
|
+
case params
|
37
|
+
when Array
|
38
|
+
scan_parameters(params)
|
39
|
+
when String
|
40
|
+
scan_parameters_string(params)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# For sort
|
46
|
+
def <=>(x)
|
47
|
+
0
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def scan_parameters_string(params)
|
52
|
+
|
53
|
+
#$stderr.puts "scan_parameters_string(#{params.inspect})"
|
54
|
+
|
55
|
+
str = params.clone
|
56
|
+
|
57
|
+
until str.empty?
|
58
|
+
name = nil
|
59
|
+
type = nil
|
60
|
+
default = nil
|
61
|
+
|
62
|
+
str.sub!(/^\s+/, '')
|
63
|
+
|
64
|
+
# $stderr.puts " str=#{str.inspect}"
|
65
|
+
|
66
|
+
if md = /^(\w+(::\w+)*)\s+(\w+)/i.match(str)
|
67
|
+
str = md.post_match
|
68
|
+
type = md[1]
|
69
|
+
name = md[3]
|
70
|
+
elsif md = /^(\*?\w+)/i.match(str)
|
71
|
+
str = md.post_match
|
72
|
+
type = nil
|
73
|
+
name = md[1]
|
74
|
+
else
|
75
|
+
raise NameError, "Syntax error in multimethod parameters: #{params.inspect} before #{str.inspect}"
|
76
|
+
end
|
77
|
+
|
78
|
+
if md = /^\s*=\s*([^,]+)/.match(str)
|
79
|
+
str = md.post_match
|
80
|
+
default = md[1]
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
str.sub!(/^\s+/, '')
|
85
|
+
if ! str.empty?
|
86
|
+
if md = /^,/.match(str)
|
87
|
+
str = md.post_match
|
88
|
+
else
|
89
|
+
raise NameError, "Syntax error in multimethod parameters: expected ',' before #{str.inspect}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
p = Parameter.new(name, type, default)
|
94
|
+
add_parameter(p)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def scan_parameters(params)
|
100
|
+
until params.empty?
|
101
|
+
name = nil
|
102
|
+
type = nil
|
103
|
+
restarg = false
|
104
|
+
default = nil
|
105
|
+
|
106
|
+
if x = params.shift
|
107
|
+
case x
|
108
|
+
when Class
|
109
|
+
type = x
|
110
|
+
else
|
111
|
+
name = x
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
if ! name && (x = params.shift)
|
116
|
+
name = x
|
117
|
+
end
|
118
|
+
|
119
|
+
raise("Parameter name expected, found #{name.inspect}") unless name.kind_of?(String) || name.kind_of?(Symbol)
|
120
|
+
raise("Parameter type expected, found #{type.inspect}") unless type.kind_of?(Module) || type.nil?
|
121
|
+
|
122
|
+
p = Parameter.new(name, type, default)
|
123
|
+
add_parameter(p)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_parameter(p)
|
129
|
+
if p.restarg
|
130
|
+
raise("Too many restargs") if @restarg
|
131
|
+
@restarg = p
|
132
|
+
@max_args = nil
|
133
|
+
end
|
134
|
+
if p.default
|
135
|
+
(@default ||= [ ]).push(p)
|
136
|
+
end
|
137
|
+
|
138
|
+
p.i = @parameter.size
|
139
|
+
@parameter.push(p)
|
140
|
+
p.method = self
|
141
|
+
|
142
|
+
unless p.default || p.restarg
|
143
|
+
@min_args = @parameter.size
|
144
|
+
end
|
145
|
+
|
146
|
+
unless @restarg
|
147
|
+
@max_args = @parameter.size
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
def score_cached(args)
|
153
|
+
unless x = @score[args]
|
154
|
+
x = @score[args] =
|
155
|
+
score(args)
|
156
|
+
end
|
157
|
+
x
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def score(args)
|
162
|
+
|
163
|
+
if @min_args > args.size
|
164
|
+
# Not enough args
|
165
|
+
score = nil
|
166
|
+
elsif @max_args && @max_args < args.size
|
167
|
+
# Too many args?
|
168
|
+
# $stderr.puts "max_args = #{@max_args}, args.size = #{args.size}"
|
169
|
+
score = nil
|
170
|
+
else
|
171
|
+
# Interpret how close the argument type is to the parameter's type.
|
172
|
+
i = -1
|
173
|
+
score = args.collect{|a| parameter_at(i = i + 1).score(a)}
|
174
|
+
|
175
|
+
# Handle score for trailing restargs.
|
176
|
+
if @restarg || @default
|
177
|
+
while (i = i + 1) < @parameter.size
|
178
|
+
# $stderr.puts " Adding score i=#{i}"
|
179
|
+
score << parameter_at(i).score(NilClass)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# If any argument cannot match, avoid this method.
|
184
|
+
score = nil if score.index(nil)
|
185
|
+
end
|
186
|
+
|
187
|
+
# if true || @name =~ /_bar$/
|
188
|
+
# $stderr.puts " Method: score #{self.to_s} #{args.inspect} => #{score.inspect}"
|
189
|
+
# end
|
190
|
+
|
191
|
+
score
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def parameter_at(i)
|
196
|
+
if i >= @parameter.size && @restarg
|
197
|
+
@restarg
|
198
|
+
else
|
199
|
+
@parameter[i]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def parameter_to_s(p = nil)
|
205
|
+
p ||= @parameter
|
206
|
+
p.collect{|x| x.to_s_long}.join(', ')
|
207
|
+
end
|
208
|
+
|
209
|
+
def to_s(name = nil)
|
210
|
+
name ||= @name
|
211
|
+
p = @parameter.clone
|
212
|
+
rcvr = p.shift
|
213
|
+
"#{rcvr.type.name}##{name}(#{parameter_to_s(p)})"
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_ruby
|
217
|
+
"def #{name}(#{to_s_arg})"
|
218
|
+
end
|
219
|
+
|
220
|
+
def to_s_arg
|
221
|
+
x = @parameter.clone
|
222
|
+
x.shift
|
223
|
+
x.collect{|x| x.to_ruby}.join(', ')
|
224
|
+
end
|
225
|
+
|
226
|
+
def inspect
|
227
|
+
to_s
|
228
|
+
end
|
229
|
+
end # class
|
230
|
+
end # module
|
231
|
+
|
232
|
+
|