pattern-match 0.0.2 → 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.
data/README.rdoc CHANGED
@@ -63,7 +63,7 @@ or
63
63
 
64
64
  ## (D)
65
65
  class EMail
66
- def self.extract(value)
66
+ def self.deconstruct(value)
67
67
  value.to_s.split(/@/).tap {|parts| raise PatternNotMatch unless parts.length == 2 }
68
68
  end
69
69
  end
@@ -1,3 +1,3 @@
1
1
  module PatternMatch
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/pattern-match.rb CHANGED
@@ -9,7 +9,7 @@ module PatternMatch
9
9
  SUPPORT_REFINEMENTS = true
10
10
  else
11
11
  SUPPORT_REFINEMENTS = false
12
- Module.module_eval {
12
+ Module.module_eval do
13
13
  private
14
14
 
15
15
  def refine(klass, &block)
@@ -18,10 +18,10 @@ module PatternMatch
18
18
 
19
19
  def using(klass)
20
20
  end
21
- }
21
+ end
22
22
  end
23
23
 
24
- module Extractable
24
+ module Deconstructable
25
25
  def call(*subpatterns)
26
26
  if Object == self
27
27
  raise MalformedPatternError unless subpatterns.length == 1
@@ -38,7 +38,11 @@ module PatternMatch
38
38
 
39
39
  module NameSpace
40
40
  refine Class do
41
- include Extractable
41
+ include Deconstructable
42
+
43
+ def deconstruct(val)
44
+ raise NotImplementedError, "need to define `#{__method__}'"
45
+ end
42
46
 
43
47
  private
44
48
 
@@ -48,35 +52,35 @@ module PatternMatch
48
52
  end
49
53
 
50
54
  refine Array.singleton_class do
51
- def extract(val)
55
+ def deconstruct(val)
52
56
  accept_self_instance_only(val)
53
57
  val
54
58
  end
55
59
  end
56
60
 
57
61
  refine Struct.singleton_class do
58
- def extract(val)
62
+ def deconstruct(val)
59
63
  accept_self_instance_only(val)
60
64
  val.values
61
65
  end
62
66
  end
63
67
 
64
68
  refine Complex.singleton_class do
65
- def extract(val)
69
+ def deconstruct(val)
66
70
  accept_self_instance_only(val)
67
71
  val.rect
68
72
  end
69
73
  end
70
74
 
71
75
  refine Rational.singleton_class do
72
- def extract(val)
76
+ def deconstruct(val)
73
77
  accept_self_instance_only(val)
74
78
  [val.numerator, val.denominator]
75
79
  end
76
80
  end
77
81
 
78
82
  refine MatchData.singleton_class do
79
- def extract(val)
83
+ def deconstruct(val)
80
84
  accept_self_instance_only(val)
81
85
  val.captures.empty? ? [val[0]] : val.captures
82
86
  end
@@ -86,26 +90,26 @@ module PatternMatch
86
90
  def Struct.method_added(name)
87
91
  if name == members[0]
88
92
  this = self
89
- PatternMatch::NameSpace.module_eval {
93
+ PatternMatch::NameSpace.module_eval do
90
94
  refine this.singleton_class do
91
- include Extractable
95
+ include Deconstructable
92
96
  end
93
- }
97
+ end
94
98
  end
95
99
  end
96
100
 
97
101
  refine Proc do
98
- include Extractable
102
+ include Deconstructable
99
103
 
100
- def extract(val)
104
+ def deconstruct(val)
101
105
  [self === val]
102
106
  end
103
107
  end
104
108
 
105
109
  refine Symbol do
106
- include Extractable
110
+ include Deconstructable
107
111
 
108
- def extract(val)
112
+ def deconstruct(val)
109
113
  [self.to_proc === val]
110
114
  end
111
115
  end
@@ -113,14 +117,14 @@ module PatternMatch
113
117
 
114
118
  refine Symbol do
115
119
  def call(*args)
116
- Proc.new {|obj| obj.send(self, *args) }
120
+ Proc.new {|obj| obj.__send__(self, *args) }
117
121
  end
118
122
  end
119
123
 
120
124
  refine Regexp do
121
- include Extractable
125
+ include Deconstructable
122
126
 
123
- def extract(val)
127
+ def deconstruct(val)
124
128
  m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
125
129
  raise PatternNotMatch unless m
126
130
  m.captures.empty? ? [m[0]] : m.captures
@@ -142,7 +146,7 @@ module PatternMatch
142
146
  end
143
147
 
144
148
  def vars
145
- @subpatterns.map(&:vars).inject([], :concat)
149
+ @subpatterns.map(&:vars).flatten
146
150
  end
147
151
 
148
152
  def binding
@@ -230,7 +234,7 @@ module PatternMatch
230
234
  end
231
235
 
232
236
  def match(val)
233
- extracted_vals = pattern_match_env.call_refined_method(@extractor, :extract, val)
237
+ extracted_vals = pattern_match_env.call_refined_method(@extractor, :deconstruct, val)
234
238
  k = extracted_vals.length - (@subpatterns.length - 2)
235
239
  quantifier = @subpatterns.find {|i| i.is_a?(PatternQuantifier) }
236
240
  if quantifier
@@ -329,7 +333,7 @@ module PatternMatch
329
333
  end
330
334
 
331
335
  def match(val)
332
- @val.send(@compare_by, val)
336
+ @val.__send__(@compare_by, val)
333
337
  end
334
338
  end
335
339
 
@@ -357,10 +361,6 @@ module PatternMatch
357
361
  end
358
362
 
359
363
  class PatternNot < Pattern
360
- def initialize(subpattern)
361
- super
362
- end
363
-
364
364
  def match(val)
365
365
  ! @subpatterns[0].match(val)
366
366
  rescue PatternNotMatch
@@ -446,13 +446,19 @@ module PatternMatch
446
446
  tmpbinding_module(obj).instance_eval do
447
447
  begin
448
448
  binding.each do |name, val|
449
- define_method(name) { val }
450
- private name
449
+ stack = @stacks[name]
450
+ if stack.empty?
451
+ define_method(name) { stack[-1] }
452
+ private name
453
+ end
454
+ stack.push(val)
451
455
  end
452
456
  obj.instance_eval(&block)
453
457
  ensure
454
458
  binding.each do |name, _|
455
- remove_method(name) if private_method_defined? name
459
+ if @stacks[name].tap(&:pop).empty?
460
+ remove_method(name)
461
+ end
456
462
  end
457
463
  end
458
464
  end
@@ -465,6 +471,9 @@ module PatternMatch
465
471
  m = obj.singleton_class.ancestors.find {|i| i.is_a? TmpBindingModule }
466
472
  unless m
467
473
  m = TmpBindingModule.new
474
+ m.instance_eval do
475
+ @stacks = ::Hash.new {|h, k| h[k] = [] }
476
+ end
468
477
  obj.extend(m)
469
478
  end
470
479
  m
@@ -486,7 +495,7 @@ module Kernel
486
495
  using ::PatternMatch::NameSpace
487
496
 
488
497
  def call_refined_method(obj, name, *args)
489
- obj.send(name, *args)
498
+ obj.__send__(name, *args)
490
499
  end
491
500
  end
492
501
  env.instance_eval(&block)
@@ -38,17 +38,61 @@ class TestPatternMatch < Test::Unit::TestCase
38
38
  end
39
39
 
40
40
  def test_variable_shadowing
41
- skip 'not implemented yet'
42
41
  match(0) {
43
42
  with(a) {
44
- match(1) {
45
- with(a) {
43
+ assert_equal(0, a)
44
+ match([1, 2]) {
45
+ with(_[a, b]) {
46
+ assert_equal(1, a)
47
+ assert_equal(2, b)
48
+ match([3, 4, 5]) {
49
+ with(_[a, b, c]) {
50
+ assert_equal(3, a)
51
+ assert_equal(4, b)
52
+ assert_equal(5, c)
53
+ }
54
+ }
46
55
  assert_equal(1, a)
56
+ assert_equal(2, b)
57
+ assert_raise(NameError) { c }
47
58
  }
48
59
  }
49
60
  assert_equal(0, a)
61
+ assert_raise(NameError) { b }
62
+ assert_raise(NameError) { c }
50
63
  }
51
64
  }
65
+ assert_raise(NameError) { a }
66
+ assert_raise(NameError) { b }
67
+ assert_raise(NameError) { c }
68
+ end
69
+
70
+ def test_lexical_scoping(rec_call = false, f = nil)
71
+ skip 'not supported'
72
+ unless rec_call
73
+ match(0) {
74
+ with(a) {
75
+ assert_equal(0, a)
76
+ test_lexical_scoping(true, ->{ a }) {|g|
77
+ assert_equal(0, a)
78
+ assert_equal(1, g.())
79
+ }
80
+ assert_equal(0, a)
81
+ }
82
+ }
83
+ else
84
+ assert_raise(NameError) { a }
85
+ assert_equal(0, f.())
86
+ match(1) {
87
+ with(a) {
88
+ assert_equal(1, a)
89
+ assert_equal(0, f.())
90
+ yield ->{ a }
91
+ assert_equal(1, a)
92
+ assert_equal(0, f.())
93
+ }
94
+ }
95
+ end
52
96
  end
53
97
 
54
98
  def test_uscore
@@ -254,6 +298,16 @@ class TestPatternMatch < Test::Unit::TestCase
254
298
  assert_equal(1, 2.times.find(&match { with(1) { true } }))
255
299
  end
256
300
 
301
+ def test_extractor_class
302
+ assert_raise(NotImplementedError) {
303
+ c = Class.new
304
+ match(0) {
305
+ with(c.(a)) {
306
+ }
307
+ }
308
+ }
309
+ end
310
+
257
311
  def test_extractor_class_struct
258
312
  s = Struct.new(:a, :b, :c)
259
313
  match(s[0, 1, 2]) {
@@ -403,7 +457,7 @@ class TestPatternMatch < Test::Unit::TestCase
403
457
  c = Class.new
404
458
  ::PatternMatch::NameSpace.module_eval {
405
459
  refine c.singleton_class do
406
- def extract(*)
460
+ def deconstruct(*)
407
461
  [:c]
408
462
  end
409
463
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pattern-match
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-04 00:00:00.000000000 Z
12
+ date: 2012-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &6408560 !ruby/object:Gem::Requirement
16
+ requirement: &8625920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *6408560
24
+ version_requirements: *8625920
25
25
  description: A pattern matching library.
26
26
  email:
27
27
  - kazuki@callcc.net
@@ -57,7 +57,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
57
  version: '0'
58
58
  segments:
59
59
  - 0
60
- hash: 2122497246809249036
60
+ hash: -900071050850383955
61
61
  required_rubygems_version: !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
66
  version: '0'
67
67
  segments:
68
68
  - 0
69
- hash: 2122497246809249036
69
+ hash: -900071050850383955
70
70
  requirements: []
71
71
  rubyforge_project:
72
72
  rubygems_version: 1.8.11