multimethod 0.0.1 → 0.1.0

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.
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