pattern-match 1.0.1 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7472cd3f781f3de13a150b3f7451f1b6c7acbebc
4
- data.tar.gz: a400bedeed0e8e87ec9a0c56e283184083f34988
2
+ SHA256:
3
+ metadata.gz: 2cd3ccf69d626d2302494e2393796dfb571b06aace34f29def21dde39021e852
4
+ data.tar.gz: 8cfb00569ac023f7e76d1ae165a4f0ca2c43fa3afb82eb1e17dce30012d8ca4a
5
5
  SHA512:
6
- metadata.gz: c94fa67c645a45c2e67d3c02a2e86e0612a61749ccbc9098469d784e5afa65891d9dc88311f3ae4b73a27c1fa252d0db31789ad4739f96840100a3633a95f98d
7
- data.tar.gz: 3822c0b6c0d94237c589e1f15aa93818c399ffb677bdfce95c6e8ae5082ddd4fb51e5d00b35222e044b2bd9b3041319bbae5ad10f085d36bcf61e09e553932e9
6
+ metadata.gz: 575702a7996ba07a2a0b8bf3cbc5fd83035298f9ecec13fffb51652b8b6f92742df823d59bcfdd53cba8ebcb8e7861876215ea413573416c2aa167987b4257f2
7
+ data.tar.gz: 40218d0fbd2c075b6b2a0660febd458d04d5e379b0fdc06ca6c7588207091297fb2952eb7a2683ba686e154777a9fd6baf005feda34b8d2e303544764699f92f
@@ -0,0 +1,35 @@
1
+ on: [ push, pull_request ]
2
+
3
+ jobs:
4
+ ruby-versions:
5
+ uses: ruby/actions/.github/workflows/ruby_versions.yml@master
6
+ with:
7
+ engine: cruby
8
+ min_version: 2.4
9
+ test:
10
+ needs: ruby-versions
11
+ name: >-
12
+ Test (${{ matrix.ruby-version }} / ${{ matrix.os }} / DISABLE_REFINEMENTS: ${{ matrix.DISABLE_REFINEMENTS }})
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby-version: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
17
+ os: [ ubuntu-latest, macos-latest ]
18
+ exclude:
19
+ - { os: macos-latest, ruby-version: 2.4 }
20
+ - { os: macos-latest, ruby-version: 2.5 }
21
+ DISABLE_REFINEMENTS: [ 1, 0 ]
22
+ runs-on: ${{ matrix.os }}
23
+ env:
24
+ DISABLE_REFINEMENTS: ${{ matrix.DISABLE_REFINEMENTS }}
25
+ continue-on-error: ${{ matrix.ruby-version == 'head' }}
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+ - name: Set up Ruby
29
+ uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: ${{ matrix.ruby-version }}
32
+ bundler-cache: true
33
+ - name: Run the test suite
34
+ run: |
35
+ bundle exec rake
data/BSDL CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2012-2015 Kazuki Tsujimoto, All rights reserved.
1
+ Copyright (C) 2012 Kazuki Tsujimoto
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-2015 Kazuki Tsujimoto, All rights reserved.
1
+ Copyright (C) 2012 Kazuki Tsujimoto
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:
data/README.rdoc CHANGED
@@ -48,14 +48,14 @@ An ordinary object is a value pattern.
48
48
  The pattern matches an object such that <code>pattern === object</code>.
49
49
 
50
50
  match(0) do
51
- with(Fixnum) { :match } #=> :match
51
+ with(Integer) { :match } #=> :match
52
52
  end
53
53
 
54
54
  If you want to use an another method of matching,
55
55
  you have to use <code>_</code> as follows.
56
56
 
57
57
  match(0) do
58
- with(_(Fixnum, :==)) { :match }
58
+ with(_(Integer, :==)) { :match }
59
59
  end #=> NoMatchingPatternError
60
60
 
61
61
  === Deconstructor
@@ -112,7 +112,7 @@ all objects bound to variable must be equal.
112
112
  <code>And</code>, <code>Or</code>, <code>Not</code> return and/or/not pattern.
113
113
 
114
114
  match([0, [1]]) do
115
- with(_[a & Fixnum, ! (_[2] | _[3])]) { a } #=> 0
115
+ with(_[a & Integer, ! (_[2] | _[3])]) { a } #=> 0
116
116
  end
117
117
 
118
118
  match(0) do
@@ -129,7 +129,7 @@ They are equivalent to <code>*</code>, <code>*?</code>,
129
129
  You can write as <code>*pattern</code> instead of <code>pattern, \___</code>.
130
130
 
131
131
  match([:a, 0, :b, :c]) do
132
- with(_[a & Symbol, ___, b & Fixnum, c & Symbol, ___]) do
132
+ with(_[a & Symbol, ___, b & Integer, c & Symbol, ___]) do
133
133
  a #=> [:a]
134
134
  b #=> 0
135
135
  c #=> [:b, :c]
@@ -142,7 +142,7 @@ You can write as <code>*pattern</code> instead of <code>pattern, \___</code>.
142
142
  It is equivalent to <code>()</code> in regular expression.
143
143
 
144
144
  match([:a, 0, :b, 1]) do
145
- with(_[Seq(a & Symbol, b & Fixnum), ___]) do
145
+ with(_[Seq(a & Symbol, b & Integer), ___]) do
146
146
  a #=> [:a, :b]
147
147
  b #=> [0, 1]
148
148
  end
@@ -154,6 +154,7 @@ It is equivalent to <code>()</code> in regular expression.
154
154
  * KeyMatcher
155
155
  * Hash.()
156
156
  * AttributeMatcher
157
+ * fallthrough (requires binding_of_caller gem)
157
158
 
158
159
  To use experimental features, you must also require 'pattern-match/experimental'.
159
160
  See source code for more details.
@@ -251,8 +252,19 @@ Pattern guard can be specified as a second argument to <code>with</code>.
251
252
  end
252
253
  end
253
254
 
254
- * {RubyTextProcessing}[https://code.google.com/p/tokland/wiki/RubyTextProcessing]
255
+ match([]) do
256
+ with(_[]) do
257
+ opts = {}
258
+ fallthrough
259
+ end
260
+ with(_[opts & Hash]) do
261
+ opts #=> {}
262
+ end
263
+ end
264
+
265
+ * {tokland/RubyTextProcessing}[https://github.com/tokland/tokland/wiki/RubyTextProcessing]
255
266
  * {yhara/tapl-ruby}[https://github.com/yhara/tapl-ruby]
267
+ * {k-tsj/power_assert}[https://github.com/k-tsj/power_assert/blob/8e9e0399a032936e3e3f3c1f06e0d038565f8044/lib/power_assert.rb]
256
268
 
257
269
  == Reference
258
270
  * {Pattern Matching in Ruby (at Sapporo RubyKaigi 2012) // Speaker Deck}[https://speakerdeck.com/k_tsj/patternmatchinginruby]
@@ -264,5 +276,3 @@ Pattern guard can be specified as a second argument to <code>with</code>.
264
276
  $ bundle install --path vendor/bundle
265
277
  $ bundle exec rake test (or "bundle exec rake")
266
278
  $ bundle exec rake build
267
-
268
- == Travis Build Status {<img src="https://secure.travis-ci.org/k-tsj/pattern-match.png"/>}[http://travis-ci.org/k-tsj/pattern-match]
@@ -473,10 +473,17 @@ module PatternMatch
473
473
  end
474
474
  end
475
475
 
476
+ FALLTHROUGH_TAG = Object.new
477
+
476
478
  class Env < BasicObject
477
479
  def initialize(ctx, val)
478
480
  @ctx = ctx
479
481
  @val = val
482
+ @fallthrough_quasibinding = nil
483
+ end
484
+
485
+ def fallthrough_called?
486
+ !! @fallthrough_quasibinding
480
487
  end
481
488
 
482
489
  private
@@ -489,9 +496,22 @@ module PatternMatch
489
496
  pat.append(PatternCondition.new { with_quasibinding(ctx, pat.quasibinding, &guard_proc) })
490
497
  end
491
498
  pat.validate
492
- if pat.match([@val])
493
- ret = with_quasibinding(ctx, pat.quasibinding, &block)
499
+ if fallthrough_called?
500
+ ret = with_quasibinding(ctx, pat.quasibinding.merge(@fallthrough_quasibinding), &block)
494
501
  ::Kernel.throw(self, ret)
502
+ end
503
+ if pat.match([@val])
504
+ ret = nil
505
+ fallthrough_called = true
506
+ block_quasibinding = ::Kernel.catch(::PatternMatch::FALLTHROUGH_TAG) do
507
+ ret = with_quasibinding(ctx, pat.quasibinding, &block)
508
+ fallthrough_called = false
509
+ end
510
+ if fallthrough_called
511
+ @fallthrough_quasibinding = pat.quasibinding.merge(block_quasibinding)
512
+ else
513
+ ::Kernel.throw(self, ret)
514
+ end
495
515
  else
496
516
  nil
497
517
  end
@@ -638,6 +658,9 @@ module PatternMatch
638
658
  env = Env.new(self, val)
639
659
  catch(env) do
640
660
  env.instance_eval(&block)
661
+ if env.fallthrough_called?
662
+ raise PatternMatchError, 'cannot fallthrough final case in match'
663
+ end
641
664
  raise NoMatchingPatternError
642
665
  end
643
666
  end
@@ -20,7 +20,11 @@ module PatternMatch
20
20
  end
21
21
 
22
22
  refine Class do
23
- include PatternMatch::Deconstructable
23
+ if respond_to?(:import_methods, true)
24
+ import_methods PatternMatch::Deconstructable
25
+ else
26
+ include PatternMatch::Deconstructable
27
+ end
24
28
 
25
29
  def deconstruct(val)
26
30
  raise NotImplementedError, "need to define `#{__method__}'"
@@ -69,7 +73,11 @@ module PatternMatch
69
73
  end
70
74
 
71
75
  refine Regexp do
72
- include PatternMatch::Deconstructable
76
+ if respond_to?(:import_methods, true)
77
+ import_methods PatternMatch::Deconstructable
78
+ else
79
+ include PatternMatch::Deconstructable
80
+ end
73
81
 
74
82
  def deconstruct(val)
75
83
  m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
@@ -62,6 +62,12 @@ module PatternMatch
62
62
  end
63
63
  end
64
64
 
65
+ refine Class do
66
+ if respond_to?(:import_methods, true)
67
+ import_methods PatternMatch::Deconstructable
68
+ end
69
+ end
70
+
65
71
  module AttributeMatcher
66
72
  def self.included(klass)
67
73
  class << klass
@@ -185,4 +191,18 @@ class Object
185
191
  Kernel.eval("with(#{pattern}) { self }", Kernel.binding)
186
192
  end
187
193
  end
194
+
195
+ begin
196
+ require 'binding_of_caller'
197
+
198
+ private
199
+
200
+ def fallthrough
201
+ b = binding.of_caller(1)
202
+ vars = b.eval('local_variables')
203
+ quasibinding = Hash[*vars.map {|i| [i, b.local_variable_get(i)] }.flatten(1)]
204
+ throw PatternMatch::FALLTHROUGH_TAG, quasibinding
205
+ end
206
+ rescue LoadError
207
+ end
188
208
  end
@@ -1,3 +1,3 @@
1
1
  module PatternMatch
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/pattern-match.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # pattern-match.rb
2
2
  #
3
- # Copyright (C) 2012-2015 Kazuki Tsujimoto, All rights reserved.
3
+ # Copyright (C) 2012 Kazuki Tsujimoto
4
4
 
5
5
  require 'pattern-match/version'
6
6
  require 'pattern-match/deconstructor'
@@ -22,5 +22,4 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency 'test-unit'
24
24
  s.add_development_dependency 'rake'
25
- s.add_development_dependency 'simplecov'
26
25
  end
@@ -1,11 +1,11 @@
1
1
  require_relative 'helper'
2
2
  require 'test-unit'
3
- if ENV['DISABLE_REFINEMENTS']
4
- require 'pattern-match/disable_refinements'
3
+ if ENV['DISABLE_REFINEMENTS'].to_i.zero?
5
4
  require 'pattern-match'
5
+ using PatternMatch
6
6
  else
7
+ require 'pattern-match/disable_refinements'
7
8
  require 'pattern-match'
8
- using PatternMatch
9
9
  end
10
10
  begin
11
11
  require 'pattern-match/experimental'
@@ -102,10 +102,10 @@ class TestExperimental < Test::Unit::TestCase
102
102
  end
103
103
 
104
104
  def test_object_assert_pattern
105
- assert_equal([0], [0].assert_pattern('_[Fixnum]'))
106
- assert_equal([0], [0].assert_pattern('_[a & Fixnum], guard { a.even? }'))
105
+ assert_equal([0], [0].assert_pattern('_[Integer]'))
106
+ assert_equal([0], [0].assert_pattern('_[a & Integer], guard { a.even? }'))
107
107
  assert_raises(PatternMatch::NoMatchingPatternError) do
108
- [0, 1].assert_pattern('_[Fixnum]')
108
+ [0, 1].assert_pattern('_[Integer]')
109
109
  end
110
110
  end
111
111
 
@@ -145,4 +145,28 @@ class TestExperimental < Test::Unit::TestCase
145
145
  with(_) { flunk }
146
146
  end
147
147
  end
148
+
149
+ def test_fallthrough
150
+ omit unless respond_to?(:fallthrough, true)
151
+
152
+ match(0) do
153
+ with(a) do
154
+ b = 1
155
+ assert_equal 0, a
156
+ assert_equal 1, b
157
+ fallthrough
158
+ end
159
+ with(_[a, c]) do
160
+ assert_equal 0, a
161
+ assert_equal 1, b
162
+ assert_nil c
163
+ end
164
+ end
165
+
166
+ assert_raises(PatternMatch::PatternMatchError) do
167
+ match(0) do
168
+ with(_) { fallthrough }
169
+ end
170
+ end
171
+ end
148
172
  end if defined? PatternMatch::AttributeMatcher
@@ -1,11 +1,11 @@
1
1
  require_relative 'helper'
2
2
  require 'test-unit'
3
- if ENV['DISABLE_REFINEMENTS']
4
- require 'pattern-match/disable_refinements'
3
+ if ENV['DISABLE_REFINEMENTS'].to_i.zero?
5
4
  require 'pattern-match'
5
+ using PatternMatch
6
6
  else
7
+ require 'pattern-match/disable_refinements'
7
8
  require 'pattern-match'
8
- using PatternMatch
9
9
  end
10
10
 
11
11
  class TestStandard < Test::Unit::TestCase
@@ -17,7 +17,7 @@ class TestStandard < Test::Unit::TestCase
17
17
  with(nil) { flunk }
18
18
  with(_[]) { flunk }
19
19
  with(_[a, 0, 0, b]) { flunk }
20
- with(_[a, Fixnum , 2, b]) do
20
+ with(_[a, Integer , 2, b]) do
21
21
  assert_equal(this, self)
22
22
  assert_equal(0, a)
23
23
  assert_equal(3, b)
@@ -125,8 +125,8 @@ class TestStandard < Test::Unit::TestCase
125
125
  end
126
126
 
127
127
  def test_uscore
128
- match([0, 1, Fixnum]) do
129
- with(_[_, ! _(Float), _(Fixnum, :==)]) do
128
+ match([0, 1, Integer]) do
129
+ with(_[_, ! _(Float), _(Integer, :==)]) do
130
130
  assert_raises(NameError) { _ }
131
131
  end
132
132
  with(_) { flunk }
@@ -277,7 +277,7 @@ class TestStandard < Test::Unit::TestCase
277
277
  end
278
278
 
279
279
  match([[0, 1, :a, 'A'], [2, :b, :c, 'B'], ['C'], 3]) do
280
- with(_[_[a & Fixnum, ___, b & Symbol, ___, c], ___, d]) do
280
+ with(_[_[a & Integer, ___, b & Symbol, ___, c], ___, d]) do
281
281
  assert_equal([[0, 1], [2], []], a)
282
282
  assert_equal([[:a], [:b, :c], []], b)
283
283
  assert_equal(['A', 'B', 'C'], c)
@@ -287,7 +287,7 @@ class TestStandard < Test::Unit::TestCase
287
287
  end
288
288
 
289
289
  match([0, 1, 2, 4, 5]) do
290
- with(_[*a, b & Fixnum, __2, *c], guard { b.all?(&:even?) }) do
290
+ with(_[*a, b & Integer, __2, *c], guard { b.all?(&:even?) }) do
291
291
  assert_equal([0, 1], a)
292
292
  assert_equal([2, 4], b)
293
293
  assert_equal([5], c)
@@ -345,7 +345,7 @@ class TestStandard < Test::Unit::TestCase
345
345
  end
346
346
 
347
347
  match([0, :a, 1, 2, :b, 3]) do
348
- with(_[Seq(a & Fixnum, b & Symbol, c & Fixnum), ___]) do
348
+ with(_[Seq(a & Integer, b & Symbol, c & Integer), ___]) do
349
349
  assert_equal([0, 2], a)
350
350
  assert_equal([:a, :b], b)
351
351
  assert_equal([1, 3], c)
@@ -354,12 +354,12 @@ class TestStandard < Test::Unit::TestCase
354
354
  end
355
355
 
356
356
  match([0, :a, 1, 2, :b, :c]) do
357
- with(_[Seq(a & Fixnum, b & Symbol, c & Fixnum), ___]) { flunk }
357
+ with(_[Seq(a & Integer, b & Symbol, c & Integer), ___]) { flunk }
358
358
  with(_) { pass }
359
359
  end
360
360
 
361
361
  match([0, 1, :a, 2, 3, :b, 4, 5]) do
362
- with(_[a, Seq(b & Fixnum, c & Symbol, d & Fixnum), ___, e]) do
362
+ with(_[a, Seq(b & Integer, c & Symbol, d & Integer), ___, e]) do
363
363
  assert_equal(0, a)
364
364
  assert_equal([1, 3], b)
365
365
  assert_equal([:a, :b], c)
@@ -422,7 +422,7 @@ class TestStandard < Test::Unit::TestCase
422
422
 
423
423
  assert_raises(NotImplementedError) do
424
424
  match([0]) do
425
- with(_[Seq(a & Fixnum, ___), ___]) {}
425
+ with(_[Seq(a & Integer, ___), ___]) {}
426
426
  end
427
427
  end
428
428
  end
@@ -632,16 +632,16 @@ class TestStandard < Test::Unit::TestCase
632
632
  end
633
633
 
634
634
  def test_refinements
635
- if ENV['DISABLE_REFINEMENTS']
636
- assert_kind_of(PatternMatch.const_get(:Pattern), eval_in_unrefined_scope('Class.()'))
637
- assert_equal(0, eval_in_unrefined_scope('match(0) { with(_) { 0 } }'))
638
- else
635
+ if ENV['DISABLE_REFINEMENTS'].to_i.zero?
639
636
  assert_raises(NoMethodError) do
640
637
  eval_in_unrefined_scope('Class.()')
641
638
  end
642
639
  assert_raises(NoMethodError) do
643
640
  eval_in_unrefined_scope('match(0) { with(_) { 0 } }')
644
641
  end
642
+ else
643
+ assert_kind_of(PatternMatch.const_get(:Pattern), eval_in_unrefined_scope('Class.()'))
644
+ assert_equal(0, eval_in_unrefined_scope('match(0) { with(_) { 0 } }'))
645
645
  end
646
646
  end
647
647
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pattern-match
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuki Tsujimoto
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-27 00:00:00.000000000 Z
11
+ date: 2024-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: simplecov
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  description: A pattern matching library.
56
42
  email:
57
43
  - kazuki@callcc.net
@@ -60,8 +46,8 @@ extensions: []
60
46
  extra_rdoc_files:
61
47
  - README.rdoc
62
48
  files:
49
+ - ".github/workflows/ci.yml"
63
50
  - ".gitignore"
64
- - ".travis.yml"
65
51
  - BSDL
66
52
  - COPYING
67
53
  - Gemfile
@@ -83,7 +69,7 @@ licenses:
83
69
  - 2-clause BSDL
84
70
  - Ruby's
85
71
  metadata: {}
86
- post_install_message:
72
+ post_install_message:
87
73
  rdoc_options:
88
74
  - "--main"
89
75
  - README.rdoc
@@ -100,9 +86,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
86
  - !ruby/object:Gem::Version
101
87
  version: '0'
102
88
  requirements: []
103
- rubyforge_project:
104
- rubygems_version: 2.4.6
105
- signing_key:
89
+ rubygems_version: 3.4.19
90
+ signing_key:
106
91
  specification_version: 4
107
92
  summary: A pattern matching library
108
- test_files: []
93
+ test_files:
94
+ - test/helper.rb
95
+ - test/test_experimental.rb
96
+ - test/test_standard.rb
data/.travis.yml DELETED
@@ -1,26 +0,0 @@
1
- rvm:
2
- - 1.9.3
3
- - 2.0.0
4
- - 2.1
5
- - 2.2
6
- - ruby-head
7
- - jruby-19mode
8
- env:
9
- - TEST="test/test_*"
10
- - TEST="test/test_standard.rb"
11
- - DISABLE_REFINEMENTS=1 TEST="test/test_*"
12
- - DISABLE_REFINEMENTS=1 TEST="test/test_standard.rb"
13
- matrix:
14
- exclude:
15
- - rvm: 1.9.3
16
- env: TEST="test/test_*"
17
- - rvm: 1.9.3
18
- env: TEST="test/test_standard.rb"
19
- - rvm: jruby-19mode
20
- env: TEST="test/test_*"
21
- - rvm: jruby-19mode
22
- env: TEST="test/test_standard.rb"
23
- - rvm: jruby-19mode
24
- env: DISABLE_REFINEMENTS=1 TEST="test/test_*"
25
- allow_failures:
26
- - rvm: ruby-head