pattern-match 0.1.1 → 0.1.2

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