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