multimethod 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/Manifest.txt +21 -54
  2. data/Rakefile +19 -2
  3. data/Releases.txt +7 -0
  4. data/lib/multimethod.rb +1 -0
  5. data/lib/multimethod/core_extensions.rb +6 -1
  6. data/lib/multimethod/method.rb +43 -185
  7. data/lib/multimethod/multimethod.rb +58 -3
  8. data/lib/multimethod/multimethod_version.rb +6 -0
  9. data/lib/multimethod/parameter.rb +124 -17
  10. data/lib/multimethod/signature.rb +322 -0
  11. data/lib/multimethod/table.rb +75 -30
  12. data/test/add_remove_test.rb +99 -0
  13. data/test/method_test.rb +2 -67
  14. data/test/multimethod_test.rb +18 -16
  15. data/test/signature_test.rb +190 -0
  16. metadata +23 -56
  17. data/.svn/README.txt +0 -2
  18. data/.svn/empty-file +0 -0
  19. data/.svn/entries +0 -68
  20. data/.svn/format +0 -1
  21. data/.svn/text-base/ChangeLog.svn-base +0 -3
  22. data/.svn/text-base/Manifest.txt.svn-base +0 -54
  23. data/.svn/text-base/README.txt.svn-base +0 -40
  24. data/.svn/text-base/Rakefile.svn-base +0 -132
  25. data/.svn/text-base/Releases.txt.svn-base +0 -7
  26. data/examples/.svn/README.txt +0 -2
  27. data/examples/.svn/empty-file +0 -0
  28. data/examples/.svn/entries +0 -22
  29. data/examples/.svn/format +0 -1
  30. data/examples/.svn/props/ex1.rb.svn-work +0 -5
  31. data/lib/.svn/README.txt +0 -2
  32. data/lib/.svn/empty-file +0 -0
  33. data/lib/.svn/entries +0 -24
  34. data/lib/.svn/format +0 -1
  35. data/lib/.svn/text-base/multimethod.rb.svn-base +0 -8
  36. data/lib/multimethod/.svn/README.txt +0 -2
  37. data/lib/multimethod/.svn/empty-file +0 -0
  38. data/lib/multimethod/.svn/entries +0 -53
  39. data/lib/multimethod/.svn/format +0 -1
  40. data/lib/multimethod/.svn/text-base/core_extensions.rb.svn-base +0 -38
  41. data/lib/multimethod/.svn/text-base/method.rb.svn-base +0 -232
  42. data/lib/multimethod/.svn/text-base/multimethod.rb.svn-base +0 -171
  43. data/lib/multimethod/.svn/text-base/parameter.rb.svn-base +0 -64
  44. data/lib/multimethod/.svn/text-base/table.rb.svn-base +0 -99
  45. data/test/.svn/README.txt +0 -2
  46. data/test/.svn/empty-file +0 -0
  47. data/test/.svn/entries +0 -53
  48. data/test/.svn/format +0 -1
  49. data/test/.svn/text-base/method_test.rb.svn-base +0 -89
  50. data/test/.svn/text-base/multimethod_test.rb.svn-base +0 -92
  51. data/test/.svn/text-base/parameter_test.rb.svn-base +0 -31
  52. data/test/.svn/text-base/test_base.rb.svn-base +0 -25
  53. data/test/.svn/text-base/usage_test.rb.svn-base +0 -146
@@ -1,64 +0,0 @@
1
- module Multimethod
2
- class Parameter
3
- RESTARG_SCORE = 9999
4
-
5
- attr_accessor :name
6
- attr_accessor :i
7
- attr_accessor :type
8
- attr_accessor :default
9
- attr_accessor :restarg
10
-
11
- attr_accessor :method
12
-
13
- def initialize(name, type = nil, default = nil, restarg = false)
14
- # $stderr.puts "initialize(#{name.inspect}, #{type}, #{restarg.inspect})"
15
- name = name.to_s
16
- if name.sub!(/^\*/, '')
17
- restarg = true
18
- end
19
-
20
- name = name.intern unless name.kind_of?(Symbol)
21
- @name = name
22
- @i = nil
23
- @type = type || Kernel
24
- @default = default
25
- @restarg = restarg
26
- end
27
-
28
-
29
- def score(arg)
30
- return RESTARG_SCORE if @restarg
31
- score = all_types(arg).index(type_object)
32
- end
33
-
34
-
35
- def all_types(arg)
36
- arg.ancestors
37
- end
38
-
39
-
40
- def type_object
41
- if @type.kind_of?(String)
42
- @type = @method.multimethod.table.name_to_object(@type, @method.mod, @method)
43
- end
44
- @type
45
- end
46
-
47
-
48
- def to_s
49
- @restarg ? "*#{@name}" : @name
50
- end
51
-
52
-
53
- def to_s_long
54
- "#{@type} #{to_ruby}"
55
- end
56
-
57
-
58
- def to_ruby
59
- "#{to_s}#{@default ? ' = ' + @default : ''}"
60
- end
61
-
62
- end # class
63
- end # module
64
-
@@ -1,99 +0,0 @@
1
- module Multimethod
2
- class Table
3
-
4
- @@instance = nil
5
- def self.instance
6
- # THREAD CRITICAL BEGIN
7
- @@instance ||= self.new
8
- # TRREAD CRITICAL END
9
- end
10
-
11
- @@hook_var = :@@__multimethods
12
-
13
- def initialize(*opts)
14
- @method = { }
15
-
16
- # Type name lookup cache
17
- @name_to_object = { }
18
- end
19
-
20
-
21
- @@match_def = /^\s*def\s+(\w+)([(](.*)[)])?/
22
- # Interface to Multimethod::Module mixin multimethod
23
- def install_method(mod, body, file = nil, line = nil)
24
- name = nil
25
- params = nil
26
-
27
- # Parse first line.
28
- if md = body.match(@@match_def)
29
- name = md[1]
30
- params = md[3] || ''
31
- else
32
- raise("Cannot determine name(params) from body")
33
- end
34
-
35
- # Get our Multimethod for this
36
- mm = lookup_multimethod(name)
37
- mm.install_dispatch(mod)
38
- m = mm.new_method(mod, params)
39
-
40
- # Evaluate our method.
41
- new_body = body.clone
42
- new_body.sub!(@@match_def, m.to_ruby)
43
-
44
- # if m.restarg
45
- # $stderr.puts "install_method(#{mod}) => #{m.to_ruby}:\n#{new_body}"
46
- # end
47
-
48
- file ||= __FILE__; line ||= __LINE__
49
- m.file = file; m.line = line
50
- mod.module_eval(new_body, file || __FILE__, line || __LINE__)
51
- end
52
-
53
-
54
- def lookup_multimethod(name)
55
- name = name.to_s
56
-
57
- # THREAD CRITICAL BEGIN
58
- unless mm = @method[name]
59
- mm = Multimethod.new(name)
60
- mm.table = self
61
- @method[name] = mm
62
- end
63
- # THREAD CRITICAL END
64
-
65
- mm
66
- end
67
-
68
-
69
- # Interface to code generated by #install_dispatch.
70
- def dispatch(name, rcvr, args)
71
- unless mm = @method[name]
72
- raise NameError, 'No method for multmethod #{name}' unless mm
73
- end
74
- mm.dispatch(rcvr, args)
75
- end
76
-
77
-
78
- #################################################
79
- # Support
80
- #
81
-
82
- def name_to_object(name, scope = nil, method = nil)
83
- scope ||= Kernel
84
- # THREAD CRITICAL
85
- unless x = (@name_to_object[scope] ||= { })[name]
86
- # $stderr.puts " name_to_object(#{name.inspect}) in #{scope}"
87
- x =
88
- @name_to_object[scope][name] =
89
- scope.module_eval(name, method ? method.file : __FILE__, method ? method.line : __LINE__)
90
- end
91
-
92
- x
93
- end
94
-
95
- end # class
96
-
97
- end # module
98
-
99
-
@@ -1,2 +0,0 @@
1
- This is a Subversion working copy administrative directory.
2
- Visit http://subversion.tigris.org/ for more information.
File without changes
@@ -1,53 +0,0 @@
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/test"
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_test.rb"
16
- text-time="2006-11-21T05:04:48.000000Z"
17
- committed-date="2006-11-21T15:59:22.761488Z"
18
- checksum="40b4ca1c1c328339e7380b23522998e5"
19
- last-author="kstephens"
20
- kind="file"/>
21
- <entry
22
- committed-rev="3"
23
- name="parameter_test.rb"
24
- text-time="2006-11-21T07:25:08.000000Z"
25
- committed-date="2006-11-21T15:59:22.761488Z"
26
- checksum="6893f4ec384c8ed8b5bede4642783d13"
27
- last-author="kstephens"
28
- kind="file"/>
29
- <entry
30
- committed-rev="3"
31
- name="usage_test.rb"
32
- text-time="2006-11-21T06:51:40.000000Z"
33
- committed-date="2006-11-21T15:59:22.761488Z"
34
- checksum="c3b86cfd548e87f6a3abfba9b6e64c54"
35
- last-author="kstephens"
36
- kind="file"/>
37
- <entry
38
- committed-rev="3"
39
- name="test_base.rb"
40
- text-time="2006-11-20T21:58:18.000000Z"
41
- committed-date="2006-11-21T15:59:22.761488Z"
42
- checksum="52aa7dfea864715aede8ab3e5aba1ca0"
43
- last-author="kstephens"
44
- kind="file"/>
45
- <entry
46
- committed-rev="3"
47
- name="multimethod_test.rb"
48
- text-time="2006-11-21T07:23:21.000000Z"
49
- committed-date="2006-11-21T15:59:22.761488Z"
50
- checksum="4de3fbfd3e551eaecc1b9a550b08a80a"
51
- last-author="kstephens"
52
- kind="file"/>
53
- </wc-entries>
@@ -1 +0,0 @@
1
- 4
@@ -1,89 +0,0 @@
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
-
@@ -1,92 +0,0 @@
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
-
@@ -1,31 +0,0 @@
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
@@ -1,25 +0,0 @@
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