pattern-match 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/BSDL CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2012 Kazuki Tsujimoto, All rights reserved.
1
+ Copyright (C) 2012-2013 Kazuki Tsujimoto, All rights reserved.
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without
4
4
  modification, are permitted provided that the following conditions
data/COPYING CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2012 Kazuki Tsujimoto, All rights reserved.
1
+ Copyright (C) 2012-2013 Kazuki Tsujimoto, All rights reserved.
2
2
 
3
3
  You can redistribute it and/or modify it under either the terms of the
4
4
  2-clause BSDL (see the file BSDL), or the conditions below:
@@ -49,18 +49,6 @@ or
49
49
  }
50
50
  end
51
51
 
52
- # With Refinements
53
- def balance(left, key, right)
54
- match([left, key, right]) {
55
- with(_[R[a, x, b], y, R[c, z, d]]) { R[B[a, x, b], y, B[c, z, d]] }
56
- with(_[R[R[a, x, b], y, c], z, d]) { R[B[a, x, b], y, B[c, z, d]] }
57
- with(_[R[a, x, R[b, y, c]], z, d]) { R[B[a, x, b], y, B[c, z, d]] }
58
- with(_[a, x, R[b, y, R[c, z, d]]]) { R[B[a, x, b], y, B[c, z, d]] }
59
- with(_[a, x, R[R[b, y, c], z, d]]) { R[B[a, x, b], y, B[c, z, d]] }
60
- with(_) { B[left, key, right] }
61
- }
62
- end
63
-
64
52
  ## (D)
65
53
  class EMail
66
54
  def self.deconstruct(value)
@@ -74,13 +62,6 @@ or
74
62
  }
75
63
  }
76
64
 
77
- # With Refinements
78
- match(['foo-bar@example.com', 'baz-bar@example.com']) {
79
- with(_[mail & EMail[name & /(\w+)-(\w+)/[firstname, 'bar'], domain], ___]) {
80
- p [firstname, name, domain, mail] # => [["foo", "baz"], ["foo-bar", "baz-bar"], ["example.com", "example.com"], ["foo-bar@example.com", "baz-bar@example.com"]]
81
- }
82
- }
83
-
84
65
  ## (E)
85
66
  match(10) {
86
67
  with(Object.(:to_i => a, :foobar => b)) { :not_match }
@@ -89,14 +70,6 @@ or
89
70
  }
90
71
  }
91
72
 
92
- # With Refinements
93
- match(10) {
94
- with(:to_i[a] & :foobar[b]) { :not_match }
95
- with(:to_i[a] & :to_s.(16)[b])) {
96
- p [a, b] #=> [10, "a"]
97
- }
98
- }
99
-
100
73
  You can see another example in test/test_pattern-match.rb.
101
74
 
102
75
  == Development
@@ -1,26 +1,10 @@
1
1
  # pattern-match.rb
2
2
  #
3
- # Copyright (C) 2012 Kazuki Tsujimoto, All rights reserved.
3
+ # Copyright (C) 2012-2013 Kazuki Tsujimoto, All rights reserved.
4
4
 
5
5
  require 'pattern-match/version'
6
6
 
7
7
  module PatternMatch
8
- if Module.private_method_defined? :refine
9
- SUPPORT_REFINEMENTS = true
10
- else
11
- SUPPORT_REFINEMENTS = false
12
- Module.module_eval do
13
- private
14
-
15
- def refine(klass, &block)
16
- klass.class_eval(&block)
17
- end
18
-
19
- def using(klass)
20
- end
21
- end
22
- end
23
-
24
8
  module Deconstructable
25
9
  def call(*subpatterns)
26
10
  if Object == self
@@ -33,117 +17,15 @@ module PatternMatch
33
17
  PatternDeconstructor.new(self, *subpatterns)
34
18
  end
35
19
  end
36
-
37
- if SUPPORT_REFINEMENTS
38
- alias [] call
39
- end
40
- end
41
-
42
- module NameSpace
43
- refine Class do
44
- include Deconstructable
45
-
46
- def deconstruct(val)
47
- raise NotImplementedError, "need to define `#{__method__}'"
48
- end
49
-
50
- private
51
-
52
- def accept_self_instance_only(val)
53
- raise PatternNotMatch unless val.kind_of?(self)
54
- end
55
- end
56
-
57
- refine Array.singleton_class do
58
- def deconstruct(val)
59
- accept_self_instance_only(val)
60
- val
61
- end
62
- end
63
-
64
- refine Struct.singleton_class do
65
- def deconstruct(val)
66
- accept_self_instance_only(val)
67
- val.values
68
- end
69
- end
70
-
71
- refine Complex.singleton_class do
72
- def deconstruct(val)
73
- accept_self_instance_only(val)
74
- val.rect
75
- end
76
- end
77
-
78
- refine Rational.singleton_class do
79
- def deconstruct(val)
80
- accept_self_instance_only(val)
81
- [val.numerator, val.denominator]
82
- end
83
- end
84
-
85
- refine MatchData.singleton_class do
86
- def deconstruct(val)
87
- accept_self_instance_only(val)
88
- val.captures.empty? ? [val[0]] : val.captures
89
- end
90
- end
91
-
92
- if SUPPORT_REFINEMENTS
93
- def Struct.method_added(name)
94
- if name == members[0]
95
- this = self
96
- PatternMatch::NameSpace.module_eval do
97
- refine this.singleton_class do
98
- include Deconstructable
99
- end
100
- end
101
- end
102
- end
103
-
104
- refine Proc do
105
- include Deconstructable
106
-
107
- def deconstruct(val)
108
- [self === val]
109
- end
110
- end
111
-
112
- refine Symbol do
113
- include Deconstructable
114
-
115
- def deconstruct(val)
116
- [self.to_proc === val]
117
- end
118
- end
119
- end
120
-
121
- refine Symbol do
122
- def call(*args)
123
- Proc.new {|obj| obj.__send__(self, *args) }
124
- end
125
- end
126
-
127
- refine Regexp do
128
- include Deconstructable
129
-
130
- def deconstruct(val)
131
- m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
132
- raise PatternNotMatch unless m
133
- m.captures.empty? ? [m[0]] : m.captures
134
- end
135
- end
136
20
  end
137
21
 
138
22
  class Pattern
139
23
  attr_accessor :parent, :next, :prev
140
- attr_writer :pattern_match_env
141
24
 
142
25
  def initialize(*subpatterns)
143
26
  @parent = nil
144
27
  @next = nil
145
28
  @prev = nil
146
- @pattern_match_env = nil
147
29
  @subpatterns = subpatterns.map {|i| i.kind_of?(Pattern) ? i : PatternValue.new(i) }
148
30
  set_subpatterns_relation
149
31
  end
@@ -189,10 +71,6 @@ module PatternMatch
189
71
  @subpatterns.each(&:validate)
190
72
  end
191
73
 
192
- def pattern_match_env
193
- @pattern_match_env || @parent.pattern_match_env
194
- end
195
-
196
74
  private
197
75
 
198
76
  def set_subpatterns_relation
@@ -243,19 +121,19 @@ module PatternMatch
243
121
  end
244
122
 
245
123
  class PatternDeconstructor < Pattern
246
- def initialize(extractor, *subpatterns)
124
+ def initialize(deconstructor, *subpatterns)
247
125
  super(*subpatterns)
248
- @extractor = extractor
126
+ @deconstructor = deconstructor
249
127
  end
250
128
 
251
129
  def match(val)
252
- extracted_vals = pattern_match_env.call_refined_method(@extractor, :deconstruct, val)
253
- k = extracted_vals.length - (@subpatterns.length - 2)
130
+ deconstructed_vals = @deconstructor.deconstruct(val)
131
+ k = deconstructed_vals.length - (@subpatterns.length - 2)
254
132
  quantifier = @subpatterns.find {|i| i.kind_of?(PatternQuantifier) }
255
133
  if quantifier
256
134
  return false unless quantifier.min_k <= k
257
135
  else
258
- return false unless @subpatterns.length == extracted_vals.length
136
+ return false unless @subpatterns.length == deconstructed_vals.length
259
137
  end
260
138
  @subpatterns.flat_map do |pat|
261
139
  case
@@ -267,7 +145,7 @@ module PatternMatch
267
145
  else
268
146
  [pat]
269
147
  end
270
- end.zip(extracted_vals).all? do |pat, v|
148
+ end.zip(deconstructed_vals).all? do |pat, v|
271
149
  pat.match(v)
272
150
  end
273
151
  end
@@ -399,7 +277,6 @@ module PatternMatch
399
277
  def with(pat_or_val, guard_proc = nil, &block)
400
278
  pat = pat_or_val.kind_of?(Pattern) ? pat_or_val : PatternValue.new(pat_or_val)
401
279
  pat.validate
402
- pat.pattern_match_env = self
403
280
  if pat.match(@val) and (guard_proc ? with_tmpbinding(@ctx, pat.binding, &guard_proc) : true)
404
281
  ret = with_tmpbinding(@ctx, pat.binding, &block)
405
282
  ::Kernel.throw(:exit_match, ret)
@@ -428,10 +305,9 @@ module PatternMatch
428
305
  case vals.length
429
306
  when 0
430
307
  uscore = PatternVariable.new(:_)
431
- uscore.pattern_match_env = self
432
308
  class << uscore
433
309
  def [](*args)
434
- pattern_match_env.call_refined_method(::Array, :call, *args)
310
+ Array.call(*args)
435
311
  end
436
312
 
437
313
  def match(val)
@@ -509,7 +385,7 @@ module PatternMatch
509
385
  constants.each do |c|
510
386
  klass = const_get(c)
511
387
  next unless klass.kind_of?(Class)
512
- if klass.ancestors.find {|i| i == Pattern }
388
+ if klass <= Pattern
513
389
  private_constant c
514
390
  end
515
391
  end
@@ -523,13 +399,6 @@ module Kernel
523
399
  def match(*vals, &block)
524
400
  do_match = Proc.new do |val|
525
401
  env = PatternMatch.const_get(:Env).new(self, val)
526
- class << env
527
- using ::PatternMatch::NameSpace
528
-
529
- def call_refined_method(obj, name, *args)
530
- obj.__send__(name, *args)
531
- end
532
- end
533
402
  catch(:exit_match) do
534
403
  env.instance_eval(&block)
535
404
  raise ::PatternMatch::NoMatchingPatternError
@@ -545,3 +414,68 @@ module Kernel
545
414
  end
546
415
  end
547
416
  end
417
+
418
+ class Class
419
+ include PatternMatch::Deconstructable
420
+
421
+ def deconstruct(val)
422
+ raise NotImplementedError, "need to define `#{__method__}'"
423
+ end
424
+
425
+ private
426
+
427
+ def accept_self_instance_only(val)
428
+ raise PatternMatch::PatternNotMatch unless val.kind_of?(self)
429
+ end
430
+ end
431
+
432
+ class << Array
433
+ def deconstruct(val)
434
+ accept_self_instance_only(val)
435
+ val
436
+ end
437
+ end
438
+
439
+ class << Struct
440
+ def deconstruct(val)
441
+ accept_self_instance_only(val)
442
+ val.values
443
+ end
444
+ end
445
+
446
+ class << Complex
447
+ def deconstruct(val)
448
+ accept_self_instance_only(val)
449
+ val.rect
450
+ end
451
+ end
452
+
453
+ class << Rational
454
+ def deconstruct(val)
455
+ accept_self_instance_only(val)
456
+ [val.numerator, val.denominator]
457
+ end
458
+ end
459
+
460
+ class << MatchData
461
+ def deconstruct(val)
462
+ accept_self_instance_only(val)
463
+ val.captures.empty? ? [val[0]] : val.captures
464
+ end
465
+ end
466
+
467
+ class Regexp
468
+ include PatternMatch::Deconstructable
469
+
470
+ def deconstruct(val)
471
+ m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
472
+ raise PatternMatch::PatternNotMatch unless m
473
+ m.captures.empty? ? [m[0]] : m.captures
474
+ end
475
+ end
476
+
477
+ class Symbol
478
+ def call(*args)
479
+ Proc.new {|obj| obj.__send__(self, *args) }
480
+ end
481
+ end
@@ -1,3 +1,3 @@
1
1
  module PatternMatch
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -312,7 +312,7 @@ class TestPatternMatch < Test::Unit::TestCase
312
312
  assert_equal(1, 2.times.find(&match { with(1) { true }; with(_) { false } }))
313
313
  end
314
314
 
315
- def test_extractor_class
315
+ def test_deconstructor_class
316
316
  assert_raise(NotImplementedError) {
317
317
  c = Class.new
318
318
  match(0) {
@@ -322,7 +322,7 @@ class TestPatternMatch < Test::Unit::TestCase
322
322
  }
323
323
  end
324
324
 
325
- def test_extractor_class_struct
325
+ def test_deconstructor_class_struct
326
326
  s = Struct.new(:a, :b, :c)
327
327
  match(s[0, 1, 2]) {
328
328
  with(s.(a, b, c)) {
@@ -334,20 +334,7 @@ class TestPatternMatch < Test::Unit::TestCase
334
334
  }
335
335
  end
336
336
 
337
- def test_extractor_struct_with_refinements
338
- skip 'refinements not supported' unless PatternMatch::SUPPORT_REFINEMENTS
339
- s = Struct.new(:a, :b, :c)
340
- match(s[0, 1, 2]) {
341
- with(s[a, b, c]) {
342
- assert_equal(0, a)
343
- assert_equal(1, b)
344
- assert_equal(2, c)
345
- }
346
- with(_) { flunk }
347
- }
348
- end
349
-
350
- def test_extractor_class_complex
337
+ def test_deconstructor_class_complex
351
338
  match(Complex(0, 1)) {
352
339
  with(Complex.(a, b)) {
353
340
  assert_equal(0, a)
@@ -357,7 +344,7 @@ class TestPatternMatch < Test::Unit::TestCase
357
344
  }
358
345
  end
359
346
 
360
- def test_extractor_class_rational
347
+ def test_deconstructor_class_rational
361
348
  match(Rational(0, 1)) {
362
349
  with(Rational.(a, b)) {
363
350
  assert_equal(0, a)
@@ -367,7 +354,7 @@ class TestPatternMatch < Test::Unit::TestCase
367
354
  }
368
355
  end
369
356
 
370
- def test_extractor_class_matchdata
357
+ def test_deconstructor_class_matchdata
371
358
  m = /.../.match('abc')
372
359
  match(m) {
373
360
  with(MatchData.(a)) {
@@ -387,7 +374,7 @@ class TestPatternMatch < Test::Unit::TestCase
387
374
  }
388
375
  end
389
376
 
390
- def test_extractor_obj_regexp
377
+ def test_deconstructor_obj_regexp
391
378
  match('abc') {
392
379
  with(/./.(a)) { flunk }
393
380
  with(a & /.../.(b)) {
@@ -408,48 +395,6 @@ class TestPatternMatch < Test::Unit::TestCase
408
395
  }
409
396
  end
410
397
 
411
- def test_extractor_obj_regexp_with_refinements
412
- skip 'refinements not supported' unless PatternMatch::SUPPORT_REFINEMENTS
413
- match('abc') {
414
- with(/./[a]) { flunk }
415
- with(a & /.../[b]) {
416
- assert_equal('abc', a)
417
- assert_equal('abc', b)
418
- }
419
- with(_) { flunk }
420
- }
421
-
422
- match('abc') {
423
- with(a & /(.)(.)(.)/[b, c ,d]) {
424
- assert_equal('abc', a)
425
- assert_equal('a', b)
426
- assert_equal('b', c)
427
- assert_equal('c', d)
428
- }
429
- with(_) { flunk }
430
- }
431
- end
432
-
433
- def test_extractor_obj_proc_with_refinements
434
- skip 'refinements not supported' unless PatternMatch::SUPPORT_REFINEMENTS
435
- match(0) {
436
- with((Proc.new {|i| i + 1 })[a]) {
437
- assert_equal(1, a)
438
- }
439
- with(_) { flunk }
440
- }
441
- end
442
-
443
- def test_extractor_obj_symbol_with_refinements
444
- skip 'refinements not supported' unless PatternMatch::SUPPORT_REFINEMENTS
445
- match(0) {
446
- with(:to_s[a]) {
447
- assert_equal('0', a)
448
- }
449
- with(_) { flunk }
450
- }
451
- end
452
-
453
398
  def test_object
454
399
  match(10) {
455
400
  with(Object.(:to_i => a, :to_s.(16) => b, :no_method => c)) { flunk }
@@ -484,19 +429,4 @@ class TestPatternMatch < Test::Unit::TestCase
484
429
  with(_) { flunk }
485
430
  }
486
431
  end
487
-
488
- def test_refine_after_requiring_library
489
- c = Class.new
490
- ::PatternMatch::NameSpace.module_eval {
491
- refine c.singleton_class do
492
- def deconstruct(*)
493
- [:c]
494
- end
495
- end
496
- }
497
- match(:c) {
498
- with(c.(a)) { assert_equal(:c, a) }
499
- with(_) { flunk }
500
- }
501
- end
502
432
  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.1.1
4
+ version: 0.1.2
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-09-11 00:00:00.000000000 Z
12
+ date: 2013-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &8646440 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *8646440
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  description: A pattern matching library.
26
31
  email:
27
32
  - kazuki@callcc.net
@@ -57,7 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
62
  version: '0'
58
63
  segments:
59
64
  - 0
60
- hash: 1580258758057961953
65
+ hash: -3372255759969491054
61
66
  required_rubygems_version: !ruby/object:Gem::Requirement
62
67
  none: false
63
68
  requirements:
@@ -66,10 +71,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
71
  version: '0'
67
72
  segments:
68
73
  - 0
69
- hash: 1580258758057961953
74
+ hash: -3372255759969491054
70
75
  requirements: []
71
76
  rubyforge_project:
72
- rubygems_version: 1.8.11
77
+ rubygems_version: 1.8.23
73
78
  signing_key:
74
79
  specification_version: 3
75
80
  summary: A pattern matching library