pattern-match 1.0.0 → 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 +5 -5
- data/.github/workflows/ci.yml +35 -0
- data/.gitignore +1 -0
- data/BSDL +1 -1
- data/COPYING +1 -1
- data/Gemfile +6 -0
- data/LEGAL +4 -0
- data/README.rdoc +18 -8
- data/lib/pattern-match/core.rb +42 -32
- data/lib/pattern-match/deconstructor.rb +14 -4
- data/lib/pattern-match/disable_refinements.rb +8 -6
- data/lib/pattern-match/experimental.rb +22 -4
- data/lib/pattern-match/version.rb +1 -1
- data/lib/pattern-match.rb +1 -1
- data/pattern-match.gemspec +3 -3
- data/test/helper.rb +6 -0
- data/test/test_experimental.rb +33 -9
- data/test/test_standard.rb +22 -20
- metadata +12 -23
- data/.travis.yml +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2cd3ccf69d626d2302494e2393796dfb571b06aace34f29def21dde39021e852
|
4
|
+
data.tar.gz: 8cfb00569ac023f7e76d1ae165a4f0ca2c43fa3afb82eb1e17dce30012d8ca4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/.gitignore
CHANGED
data/BSDL
CHANGED
data/COPYING
CHANGED
data/Gemfile
CHANGED
data/LEGAL
ADDED
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(
|
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(_(
|
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 &
|
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 &
|
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 &
|
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
|
-
|
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]
|
data/lib/pattern-match/core.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'pattern-match/deconstructor'
|
2
2
|
|
3
|
+
using PatternMatch if respond_to?(:using, true)
|
4
|
+
|
3
5
|
module PatternMatch
|
4
6
|
module HasOrderedSubPatterns
|
5
7
|
private
|
@@ -16,6 +18,9 @@ module PatternMatch
|
|
16
18
|
class Pattern
|
17
19
|
attr_accessor :parent, :next, :prev
|
18
20
|
|
21
|
+
attr_reader :subpatterns
|
22
|
+
private :subpatterns
|
23
|
+
|
19
24
|
def initialize(*subpatterns)
|
20
25
|
@parent = nil
|
21
26
|
@next = nil
|
@@ -25,7 +30,7 @@ module PatternMatch
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def vars
|
28
|
-
subpatterns.
|
33
|
+
subpatterns.flat_map(&:vars)
|
29
34
|
end
|
30
35
|
|
31
36
|
def ancestors
|
@@ -117,8 +122,6 @@ module PatternMatch
|
|
117
122
|
|
118
123
|
private
|
119
124
|
|
120
|
-
attr_reader :subpatterns
|
121
|
-
|
122
125
|
def repeating_match(vals, is_greedy)
|
123
126
|
quantifier = @next
|
124
127
|
candidates = generate_candidates(vals)
|
@@ -200,8 +203,6 @@ module PatternMatch
|
|
200
203
|
class PatternObjectDeconstructor < PatternDeconstructor
|
201
204
|
include HasOrderedSubPatterns
|
202
205
|
|
203
|
-
using PatternMatch if respond_to?(:using, true)
|
204
|
-
|
205
206
|
def initialize(deconstructor, *subpatterns)
|
206
207
|
super(*subpatterns)
|
207
208
|
@deconstructor = deconstructor
|
@@ -472,10 +473,17 @@ module PatternMatch
|
|
472
473
|
end
|
473
474
|
end
|
474
475
|
|
476
|
+
FALLTHROUGH_TAG = Object.new
|
477
|
+
|
475
478
|
class Env < BasicObject
|
476
479
|
def initialize(ctx, val)
|
477
480
|
@ctx = ctx
|
478
481
|
@val = val
|
482
|
+
@fallthrough_quasibinding = nil
|
483
|
+
end
|
484
|
+
|
485
|
+
def fallthrough_called?
|
486
|
+
!! @fallthrough_quasibinding
|
479
487
|
end
|
480
488
|
|
481
489
|
private
|
@@ -483,14 +491,27 @@ module PatternMatch
|
|
483
491
|
def with(pat_or_val, guard_proc = nil, &block)
|
484
492
|
ctx = @ctx
|
485
493
|
pat = pat_or_val.kind_of?(Pattern) ? pat_or_val : PatternValue.new(pat_or_val)
|
486
|
-
pat.append(PatternCondition.new {
|
494
|
+
pat.append(PatternCondition.new { validate_uniqueness_of_dup_vars(pat.vars) })
|
487
495
|
if guard_proc
|
488
496
|
pat.append(PatternCondition.new { with_quasibinding(ctx, pat.quasibinding, &guard_proc) })
|
489
497
|
end
|
490
498
|
pat.validate
|
499
|
+
if fallthrough_called?
|
500
|
+
ret = with_quasibinding(ctx, pat.quasibinding.merge(@fallthrough_quasibinding), &block)
|
501
|
+
::Kernel.throw(self, ret)
|
502
|
+
end
|
491
503
|
if pat.match([@val])
|
492
|
-
ret =
|
493
|
-
|
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
|
494
515
|
else
|
495
516
|
nil
|
496
517
|
end
|
@@ -524,8 +545,6 @@ module PatternMatch
|
|
524
545
|
when 0
|
525
546
|
uscore = PatternVariable.new(:_)
|
526
547
|
class << uscore
|
527
|
-
using PatternMatch if respond_to?(:using, true)
|
528
|
-
|
529
548
|
def [](*args)
|
530
549
|
Array.(*args)
|
531
550
|
end
|
@@ -568,17 +587,8 @@ module PatternMatch
|
|
568
587
|
PatternNot.new(*subpatterns)
|
569
588
|
end
|
570
589
|
|
571
|
-
def
|
572
|
-
vars.
|
573
|
-
if h.has_key?(v.name)
|
574
|
-
unless h[v.name] == v.val
|
575
|
-
return false
|
576
|
-
end
|
577
|
-
else
|
578
|
-
h[v.name] = v.val
|
579
|
-
end
|
580
|
-
end
|
581
|
-
true
|
590
|
+
def validate_uniqueness_of_dup_vars(vars)
|
591
|
+
vars.group_by(&:name).all? {|_, dup_vars| dup_vars.map(&:val).uniq.length == 1 }
|
582
592
|
end
|
583
593
|
|
584
594
|
class QuasiBindingModule < ::Module
|
@@ -630,27 +640,27 @@ module PatternMatch
|
|
630
640
|
class NoMatchingPatternError < PatternMatchError; end
|
631
641
|
class MalformedPatternError < PatternMatchError; end
|
632
642
|
|
633
|
-
# Make Pattern and its subclasses
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
private_constant c
|
640
|
-
end
|
643
|
+
# Make Pattern and its subclasses, etc private.
|
644
|
+
constants.each do |c|
|
645
|
+
klass = const_get(c)
|
646
|
+
next unless klass.kind_of?(Class)
|
647
|
+
if klass <= Pattern
|
648
|
+
private_constant c
|
641
649
|
end
|
642
|
-
private_constant :Env
|
643
650
|
end
|
651
|
+
private_constant :Env, :HasOrderedSubPatterns
|
644
652
|
|
645
653
|
refine Object do
|
646
|
-
|
647
654
|
private
|
648
655
|
|
649
656
|
def match(*vals, &block)
|
650
657
|
do_match = Proc.new do |val|
|
651
658
|
env = Env.new(self, val)
|
652
|
-
catch(
|
659
|
+
catch(env) do
|
653
660
|
env.instance_eval(&block)
|
661
|
+
if env.fallthrough_called?
|
662
|
+
raise PatternMatchError, 'cannot fallthrough final case in match'
|
663
|
+
end
|
654
664
|
raise NoMatchingPatternError
|
655
665
|
end
|
656
666
|
end
|
@@ -8,17 +8,23 @@ module PatternMatch
|
|
8
8
|
PatternObjectDeconstructor.new(self, *subpatterns)
|
9
9
|
end
|
10
10
|
end
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
using PatternMatch if respond_to?(:using, true)
|
13
|
+
using PatternMatch if respond_to?(:using, true)
|
14
14
|
|
15
|
+
module PatternMatch
|
16
|
+
module Deconstructable
|
15
17
|
def call(*subpatterns)
|
16
18
|
pattern_matcher(*subpatterns)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
refine Class do
|
21
|
-
|
23
|
+
if respond_to?(:import_methods, true)
|
24
|
+
import_methods PatternMatch::Deconstructable
|
25
|
+
else
|
26
|
+
include PatternMatch::Deconstructable
|
27
|
+
end
|
22
28
|
|
23
29
|
def deconstruct(val)
|
24
30
|
raise NotImplementedError, "need to define `#{__method__}'"
|
@@ -67,7 +73,11 @@ module PatternMatch
|
|
67
73
|
end
|
68
74
|
|
69
75
|
refine Regexp do
|
70
|
-
|
76
|
+
if respond_to?(:import_methods, true)
|
77
|
+
import_methods PatternMatch::Deconstructable
|
78
|
+
else
|
79
|
+
include PatternMatch::Deconstructable
|
80
|
+
end
|
71
81
|
|
72
82
|
def deconstruct(val)
|
73
83
|
m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class Module
|
2
|
-
|
2
|
+
refine_orig = "__refine_orig_#{Time.now.to_i}".to_sym
|
3
|
+
|
4
|
+
methods = instance_methods(false) + private_instance_methods(false)
|
3
5
|
if methods.include?(:refine)
|
4
|
-
if methods.include?(
|
6
|
+
if methods.include?(refine_orig)
|
5
7
|
raise LoadError, "can't re-define Module#refine"
|
6
8
|
end
|
7
|
-
alias_method
|
9
|
+
alias_method refine_orig, :refine
|
8
10
|
remove_method :refine
|
9
11
|
end
|
10
12
|
|
@@ -17,9 +19,9 @@ class Module
|
|
17
19
|
ensure
|
18
20
|
remove_method :refine
|
19
21
|
|
20
|
-
if Kernel.respond_to?(
|
21
|
-
alias_method :refine,
|
22
|
-
remove_method
|
22
|
+
if Kernel.respond_to?(refine_orig, true)
|
23
|
+
alias_method :refine, refine_orig
|
24
|
+
remove_method refine_orig
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -4,6 +4,8 @@ require 'set'
|
|
4
4
|
|
5
5
|
raise LoadError, 'Module#prepend required' unless Module.respond_to?(:prepend, true)
|
6
6
|
|
7
|
+
using PatternMatch if respond_to?(:using, true)
|
8
|
+
|
7
9
|
module PatternMatch
|
8
10
|
class Pattern
|
9
11
|
module Backtrackable
|
@@ -50,8 +52,6 @@ module PatternMatch
|
|
50
52
|
end
|
51
53
|
|
52
54
|
module Deconstructable
|
53
|
-
using PatternMatch if respond_to?(:using, true)
|
54
|
-
|
55
55
|
remove_method :call
|
56
56
|
def call(*subpatterns)
|
57
57
|
if Object == self
|
@@ -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
|
@@ -180,11 +186,23 @@ class Hash
|
|
180
186
|
end
|
181
187
|
|
182
188
|
class Object
|
183
|
-
using PatternMatch if respond_to?(:using, true)
|
184
|
-
|
185
189
|
def assert_pattern(pattern)
|
186
190
|
match(self) do
|
187
191
|
Kernel.eval("with(#{pattern}) { self }", Kernel.binding)
|
188
192
|
end
|
189
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
|
190
208
|
end
|
data/lib/pattern-match.rb
CHANGED
data/pattern-match.gemspec
CHANGED
@@ -16,10 +16,10 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
|
18
18
|
s.require_paths = ['lib']
|
19
|
-
s.add_development_dependency 'test-unit'
|
20
|
-
s.add_development_dependency 'rake'
|
21
|
-
s.add_development_dependency 'simplecov'
|
22
19
|
s.extra_rdoc_files = ['README.rdoc']
|
23
20
|
s.rdoc_options = ['--main', 'README.rdoc']
|
24
21
|
s.licenses = ['2-clause BSDL', "Ruby's"]
|
22
|
+
|
23
|
+
s.add_development_dependency 'test-unit'
|
24
|
+
s.add_development_dependency 'rake'
|
25
25
|
end
|
data/test/helper.rb
CHANGED
data/test/test_experimental.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require_relative 'helper'
|
2
2
|
require 'test-unit'
|
3
|
-
if ENV['DISABLE_REFINEMENTS']
|
4
|
-
|
5
|
-
require_relative '../lib/pattern-match'
|
6
|
-
else
|
7
|
-
require_relative '../lib/pattern-match'
|
3
|
+
if ENV['DISABLE_REFINEMENTS'].to_i.zero?
|
4
|
+
require 'pattern-match'
|
8
5
|
using PatternMatch
|
6
|
+
else
|
7
|
+
require 'pattern-match/disable_refinements'
|
8
|
+
require 'pattern-match'
|
9
9
|
end
|
10
10
|
begin
|
11
|
-
|
11
|
+
require 'pattern-match/experimental'
|
12
12
|
rescue LoadError
|
13
13
|
end
|
14
14
|
|
@@ -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('_[
|
106
|
-
assert_equal([0], [0].assert_pattern('_[a &
|
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('_[
|
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
|
data/test/test_standard.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
require_relative 'helper'
|
2
2
|
require 'test-unit'
|
3
|
-
if ENV['DISABLE_REFINEMENTS']
|
4
|
-
|
5
|
-
require_relative '../lib/pattern-match'
|
6
|
-
else
|
7
|
-
require_relative '../lib/pattern-match'
|
3
|
+
if ENV['DISABLE_REFINEMENTS'].to_i.zero?
|
4
|
+
require 'pattern-match'
|
8
5
|
using PatternMatch
|
6
|
+
else
|
7
|
+
require 'pattern-match/disable_refinements'
|
8
|
+
require 'pattern-match'
|
9
9
|
end
|
10
10
|
|
11
11
|
class TestStandard < Test::Unit::TestCase
|
12
|
+
include TestUtils
|
13
|
+
|
12
14
|
def test_basic
|
13
15
|
this = self
|
14
16
|
ret = match([0, 1, 2, 3]) do
|
15
17
|
with(nil) { flunk }
|
16
18
|
with(_[]) { flunk }
|
17
19
|
with(_[a, 0, 0, b]) { flunk }
|
18
|
-
with(_[a,
|
20
|
+
with(_[a, Integer , 2, b]) do
|
19
21
|
assert_equal(this, self)
|
20
22
|
assert_equal(0, a)
|
21
23
|
assert_equal(3, b)
|
@@ -123,8 +125,8 @@ class TestStandard < Test::Unit::TestCase
|
|
123
125
|
end
|
124
126
|
|
125
127
|
def test_uscore
|
126
|
-
match([0, 1,
|
127
|
-
with(_[_, ! _(Float), _(
|
128
|
+
match([0, 1, Integer]) do
|
129
|
+
with(_[_, ! _(Float), _(Integer, :==)]) do
|
128
130
|
assert_raises(NameError) { _ }
|
129
131
|
end
|
130
132
|
with(_) { flunk }
|
@@ -275,7 +277,7 @@ class TestStandard < Test::Unit::TestCase
|
|
275
277
|
end
|
276
278
|
|
277
279
|
match([[0, 1, :a, 'A'], [2, :b, :c, 'B'], ['C'], 3]) do
|
278
|
-
with(_[_[a &
|
280
|
+
with(_[_[a & Integer, ___, b & Symbol, ___, c], ___, d]) do
|
279
281
|
assert_equal([[0, 1], [2], []], a)
|
280
282
|
assert_equal([[:a], [:b, :c], []], b)
|
281
283
|
assert_equal(['A', 'B', 'C'], c)
|
@@ -285,7 +287,7 @@ class TestStandard < Test::Unit::TestCase
|
|
285
287
|
end
|
286
288
|
|
287
289
|
match([0, 1, 2, 4, 5]) do
|
288
|
-
with(_[*a, b &
|
290
|
+
with(_[*a, b & Integer, __2, *c], guard { b.all?(&:even?) }) do
|
289
291
|
assert_equal([0, 1], a)
|
290
292
|
assert_equal([2, 4], b)
|
291
293
|
assert_equal([5], c)
|
@@ -343,7 +345,7 @@ class TestStandard < Test::Unit::TestCase
|
|
343
345
|
end
|
344
346
|
|
345
347
|
match([0, :a, 1, 2, :b, 3]) do
|
346
|
-
with(_[Seq(a &
|
348
|
+
with(_[Seq(a & Integer, b & Symbol, c & Integer), ___]) do
|
347
349
|
assert_equal([0, 2], a)
|
348
350
|
assert_equal([:a, :b], b)
|
349
351
|
assert_equal([1, 3], c)
|
@@ -352,12 +354,12 @@ class TestStandard < Test::Unit::TestCase
|
|
352
354
|
end
|
353
355
|
|
354
356
|
match([0, :a, 1, 2, :b, :c]) do
|
355
|
-
with(_[Seq(a &
|
357
|
+
with(_[Seq(a & Integer, b & Symbol, c & Integer), ___]) { flunk }
|
356
358
|
with(_) { pass }
|
357
359
|
end
|
358
360
|
|
359
361
|
match([0, 1, :a, 2, 3, :b, 4, 5]) do
|
360
|
-
with(_[a, Seq(b &
|
362
|
+
with(_[a, Seq(b & Integer, c & Symbol, d & Integer), ___, e]) do
|
361
363
|
assert_equal(0, a)
|
362
364
|
assert_equal([1, 3], b)
|
363
365
|
assert_equal([:a, :b], c)
|
@@ -420,7 +422,7 @@ class TestStandard < Test::Unit::TestCase
|
|
420
422
|
|
421
423
|
assert_raises(NotImplementedError) do
|
422
424
|
match([0]) do
|
423
|
-
with(_[Seq(a &
|
425
|
+
with(_[Seq(a & Integer, ___), ___]) {}
|
424
426
|
end
|
425
427
|
end
|
426
428
|
end
|
@@ -630,16 +632,16 @@ class TestStandard < Test::Unit::TestCase
|
|
630
632
|
end
|
631
633
|
|
632
634
|
def test_refinements
|
633
|
-
if ENV['DISABLE_REFINEMENTS']
|
634
|
-
assert_kind_of(PatternMatch.const_get(:Pattern), eval('Class.()', TOPLEVEL_BINDING))
|
635
|
-
assert_equal(0, eval('match(0) { with(_) { 0 } }', TOPLEVEL_BINDING))
|
636
|
-
else
|
635
|
+
if ENV['DISABLE_REFINEMENTS'].to_i.zero?
|
637
636
|
assert_raises(NoMethodError) do
|
638
|
-
|
637
|
+
eval_in_unrefined_scope('Class.()')
|
639
638
|
end
|
640
639
|
assert_raises(NoMethodError) do
|
641
|
-
|
640
|
+
eval_in_unrefined_scope('match(0) { with(_) { 0 } }')
|
642
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 } }'))
|
643
645
|
end
|
644
646
|
end
|
645
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.
|
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:
|
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,11 +46,12 @@ 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
|
54
|
+
- LEGAL
|
68
55
|
- README.rdoc
|
69
56
|
- Rakefile
|
70
57
|
- lib/pattern-match.rb
|
@@ -82,7 +69,7 @@ licenses:
|
|
82
69
|
- 2-clause BSDL
|
83
70
|
- Ruby's
|
84
71
|
metadata: {}
|
85
|
-
post_install_message:
|
72
|
+
post_install_message:
|
86
73
|
rdoc_options:
|
87
74
|
- "--main"
|
88
75
|
- README.rdoc
|
@@ -99,9 +86,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
86
|
- !ruby/object:Gem::Version
|
100
87
|
version: '0'
|
101
88
|
requirements: []
|
102
|
-
|
103
|
-
|
104
|
-
signing_key:
|
89
|
+
rubygems_version: 3.4.19
|
90
|
+
signing_key:
|
105
91
|
specification_version: 4
|
106
92
|
summary: A pattern matching library
|
107
|
-
test_files:
|
93
|
+
test_files:
|
94
|
+
- test/helper.rb
|
95
|
+
- test/test_experimental.rb
|
96
|
+
- test/test_standard.rb
|
data/.travis.yml
DELETED
@@ -1,30 +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: 2.0.0
|
20
|
-
env: TEST="test/test_*"
|
21
|
-
- rvm: 2.0.0
|
22
|
-
env: TEST="test/test_standard.rb"
|
23
|
-
- rvm: jruby-19mode
|
24
|
-
env: TEST="test/test_*"
|
25
|
-
- rvm: jruby-19mode
|
26
|
-
env: TEST="test/test_standard.rb"
|
27
|
-
- rvm: jruby-19mode
|
28
|
-
env: DISABLE_REFINEMENTS=1 TEST="test/test_*"
|
29
|
-
allow_failures:
|
30
|
-
- rvm: ruby-head
|