pattern-match 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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