patm 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +5 -0
- data/benchmark/benchmark.rb +99 -0
- data/lib/patm.rb +174 -16
- data/patm.gemspec +1 -1
- data/spec/patm_spec.rb +59 -4
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6f5f8bcb3f5f3031bac6f117418b1d3bc917e8a
|
4
|
+
data.tar.gz: 56f203d9076b6905894ffb752954c7caa41fcca6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f01fa35d647fea7658029071682a77dea11e7da92968087c383028f13476ba7a7745a7f04093457c1a45beb92bc1328fab4c9feb464f55550ef3df08b38bb40
|
7
|
+
data.tar.gz: 9ac471509e902916d52693fc7fe0bac69fb84106b8a539bcbd1f6a6657c34150e6214e73d0555b28c32ac6038bbdfaa7f40073160327ac024a9be16c2d7d1bdd
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'patm.rb')
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
P = Patm
|
5
|
+
|
6
|
+
def match_with_case(obj)
|
7
|
+
_1 = P._1
|
8
|
+
_2 = P._2
|
9
|
+
_3 = P._3
|
10
|
+
_4 = P._4
|
11
|
+
_xs = P::ARRAY_REST
|
12
|
+
|
13
|
+
case obj
|
14
|
+
when m = P.match([:assign, [:var_field, [:@ident, _1, [_2, _3]]], _4])
|
15
|
+
:as
|
16
|
+
when m = P.match([:massign, _1, _2])
|
17
|
+
:mas
|
18
|
+
when m = P.match([:var_ref, [:@ident, _1, [_2, _3]]])
|
19
|
+
:vr
|
20
|
+
when m = P.match([:params, _1, _2, _3, _xs])
|
21
|
+
:par
|
22
|
+
when m = P.match(P.or(nil, true, false, Numeric, String, Symbol, []))
|
23
|
+
:ignore
|
24
|
+
else
|
25
|
+
:else
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@ruledef = lambda do|r|
|
30
|
+
_1 = P._1
|
31
|
+
_2 = P._2
|
32
|
+
_3 = P._3
|
33
|
+
_4 = P._4
|
34
|
+
_xs = P::ARRAY_REST
|
35
|
+
|
36
|
+
r.on [:assign, [:var_field, [:@ident, _1, [_2, _3]]], _4] do|m|
|
37
|
+
:as
|
38
|
+
end
|
39
|
+
r.on [:massign, _1, _2] do|m|
|
40
|
+
:mas
|
41
|
+
end
|
42
|
+
r.on [:var_ref, [:@ident, _1, [_2, _3]]] do|m|
|
43
|
+
:vr
|
44
|
+
end
|
45
|
+
r.on [:params, _1, _2, _3, _xs] do|m|
|
46
|
+
:par
|
47
|
+
end
|
48
|
+
r.on P.or(nil, true, false, Numeric, String, Symbol, []) do|m|
|
49
|
+
:ignore
|
50
|
+
end
|
51
|
+
r.else do|obj|
|
52
|
+
:else
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@rule = P::Rule.new(&@ruledef)
|
57
|
+
@compiled_rule = P::Rule.new(true, &@ruledef)
|
58
|
+
|
59
|
+
def match_with_rule(obj)
|
60
|
+
@rule.apply(obj)
|
61
|
+
end
|
62
|
+
|
63
|
+
def match_with_compiled_rule(obj)
|
64
|
+
@compiled_rule.apply(obj)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
VALUES = [
|
69
|
+
[ [:assign, [:var_field, [:@ident, 10, [20, 30]]], false], :as ],
|
70
|
+
[ [:massign, 1, 2], :mas],
|
71
|
+
[ [:var_ref, [:@ident, "x", [1, 2]]], :vr ],
|
72
|
+
[ [:params, 10, 20, 30, 40, 50, 60, 70, 80], :par ],
|
73
|
+
[ nil, :ignore ],
|
74
|
+
[ 100, :ignore ],
|
75
|
+
[ [1,2,3], :else],
|
76
|
+
]
|
77
|
+
|
78
|
+
|
79
|
+
def bm(&b)
|
80
|
+
10000.times do
|
81
|
+
VALUES.each do|obj, expected|
|
82
|
+
actual = b.call obj
|
83
|
+
raise "e:#{expected.inspect} a:#{actual.inspect}" unless actual == expected
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Benchmark.bm(15) do|b|
|
89
|
+
b.report("case-when") { bm {|obj| match_with_case(obj) } }
|
90
|
+
b.report("rule") { bm {|obj| match_with_rule(obj) } }
|
91
|
+
b.report("compiled-rule") { bm {|obj| match_with_compiled_rule(obj) } }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# [:assign, [:var_field, [:@ident, _1, [_2, _3]]], _4] do|m|
|
96
|
+
# [:massign, _1, _2] do|m|
|
97
|
+
# [:var_ref, [:@ident, _1, [_2, _3]]] do|m|
|
98
|
+
# [:params, _1, _2, _3, _xs] do|m|
|
99
|
+
# p.or(nil, true, false, Numeric, String, Symbol, []) do|m|
|
data/lib/patm.rb
CHANGED
@@ -11,20 +11,67 @@ module Patm
|
|
11
11
|
when Pattern
|
12
12
|
plain
|
13
13
|
when Array
|
14
|
-
|
15
|
-
Arr.new(plain[0..-2].map{|p| build_from(p) }, plain.last)
|
16
|
-
else
|
17
|
-
Arr.new(plain.map{|p| build_from(p) })
|
18
|
-
end
|
14
|
+
build_from_array(plain)
|
19
15
|
else
|
20
16
|
Obj.new(plain)
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
20
|
+
def self.build_from_array(array)
|
21
|
+
array = array.map{|a| build_from(a)}
|
22
|
+
rest_index = array.index(&:rest?)
|
23
|
+
if rest_index
|
24
|
+
head = array[0...rest_index]
|
25
|
+
rest = array[rest_index]
|
26
|
+
tail = array[(rest_index+1)..-1]
|
27
|
+
Arr.new(head, rest, tail)
|
28
|
+
else
|
29
|
+
Arr.new(array)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
24
33
|
def &(rhs)
|
25
34
|
And.new([self, rhs])
|
26
35
|
end
|
27
36
|
|
37
|
+
def compile
|
38
|
+
src, context, _ = self.compile_internal(0)
|
39
|
+
|
40
|
+
Compiled.new(self.inspect, src, context)
|
41
|
+
end
|
42
|
+
|
43
|
+
# free_index:Numeric -> [src, context, free_index]
|
44
|
+
# variables: _ctx, _match, _obj
|
45
|
+
def compile_internal(free_index, target_name = "_obj")
|
46
|
+
[
|
47
|
+
"_ctx[#{free_index}].execute(_match, #{target_name})",
|
48
|
+
[self],
|
49
|
+
free_index + 1
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
class Compiled < self
|
54
|
+
def initialize(desc, src, context)
|
55
|
+
@desc = desc
|
56
|
+
@context = context
|
57
|
+
singleton_class = class <<self; self; end
|
58
|
+
@src = <<-RUBY
|
59
|
+
def execute(_match, _obj)
|
60
|
+
_ctx = @context
|
61
|
+
#{src}
|
62
|
+
end
|
63
|
+
RUBY
|
64
|
+
singleton_class.class_eval(@src)
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :src
|
68
|
+
|
69
|
+
def compile_internal(free_index, target_name = "_obj")
|
70
|
+
raise "Already compiled"
|
71
|
+
end
|
72
|
+
def inspect; "<compiled>#{@desc}"; end
|
73
|
+
end
|
74
|
+
|
28
75
|
class Arr < self
|
29
76
|
def initialize(head, rest = nil, tail = [])
|
30
77
|
@head = head
|
@@ -45,7 +92,55 @@ module Patm
|
|
45
92
|
(!@rest || @rest.execute(mmatch, obj[@head.size..-(@tail.size+1)]))
|
46
93
|
end
|
47
94
|
|
48
|
-
def inspect
|
95
|
+
def inspect
|
96
|
+
if @rest
|
97
|
+
(@head + [@rest] + @tail).inspect
|
98
|
+
else
|
99
|
+
(@head + @tail).inspect
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def compile_internal(free_index, target_name = "_obj")
|
104
|
+
i = free_index
|
105
|
+
srcs = []
|
106
|
+
ctxs = []
|
107
|
+
|
108
|
+
srcs << "#{target_name}.is_a?(::Array)"
|
109
|
+
|
110
|
+
size_min = @head.size + @tail.size
|
111
|
+
if @rest
|
112
|
+
srcs << "#{target_name}.size >= #{size_min}"
|
113
|
+
else
|
114
|
+
srcs << "#{target_name}.size == #{size_min}"
|
115
|
+
end
|
116
|
+
|
117
|
+
elm_target_name = "#{target_name}_elm"
|
118
|
+
@head.each_with_index do|h, hi|
|
119
|
+
s, c, i = h.compile_internal(i, elm_target_name)
|
120
|
+
srcs << "(#{elm_target_name} = #{target_name}[#{hi}]; #{s})"
|
121
|
+
ctxs << c
|
122
|
+
end
|
123
|
+
|
124
|
+
srcs << "(#{target_name}_t = #{target_name}[(-#{@tail.size})..-1]; true)"
|
125
|
+
@tail.each_with_index do|t, ti|
|
126
|
+
s, c, i = t.compile_internal(i, elm_target_name)
|
127
|
+
srcs << "(#{elm_target_name} = #{target_name}_t[#{ti}]; #{s})"
|
128
|
+
ctxs << c
|
129
|
+
end
|
130
|
+
|
131
|
+
if @rest
|
132
|
+
tname = "#{target_name}_r"
|
133
|
+
s, c, i = @rest.compile_internal(i, tname)
|
134
|
+
srcs << "(#{tname} = #{target_name}[#{@head.size}..-(#{@tail.size+1})];#{s})"
|
135
|
+
ctxs << c
|
136
|
+
end
|
137
|
+
|
138
|
+
[
|
139
|
+
srcs.map{|s| "(#{s})"}.join(" &&\n"),
|
140
|
+
ctxs.flatten(1),
|
141
|
+
i
|
142
|
+
]
|
143
|
+
end
|
49
144
|
end
|
50
145
|
|
51
146
|
class ArrRest < self
|
@@ -56,6 +151,13 @@ module Patm
|
|
56
151
|
true
|
57
152
|
end
|
58
153
|
def inspect; "..."; end
|
154
|
+
def compile_internal(free_index, target_name = "_obj")
|
155
|
+
[
|
156
|
+
"true",
|
157
|
+
[],
|
158
|
+
free_index
|
159
|
+
]
|
160
|
+
end
|
59
161
|
end
|
60
162
|
|
61
163
|
class Obj < self
|
@@ -70,11 +172,26 @@ module Patm
|
|
70
172
|
def inspect
|
71
173
|
"OBJ(#{@obj.inspect})"
|
72
174
|
end
|
175
|
+
|
176
|
+
def compile_internal(free_index, target_name = "_obj")
|
177
|
+
[
|
178
|
+
"_ctx[#{free_index}] === #{target_name}",
|
179
|
+
[@obj],
|
180
|
+
free_index + 1,
|
181
|
+
]
|
182
|
+
end
|
73
183
|
end
|
74
184
|
|
75
185
|
class Any < self
|
76
186
|
def execute(match, obj); true; end
|
77
187
|
def inspect; 'ANY'; end
|
188
|
+
def compile_internal(free_index, target_name = "_obj")
|
189
|
+
[
|
190
|
+
"true",
|
191
|
+
[],
|
192
|
+
free_index
|
193
|
+
]
|
194
|
+
end
|
78
195
|
end
|
79
196
|
|
80
197
|
class Group < self
|
@@ -87,11 +204,41 @@ module Patm
|
|
87
204
|
true
|
88
205
|
end
|
89
206
|
def inspect; "GROUP(#{@index})"; end
|
207
|
+
def compile_internal(free_index, target_name = "_obj")
|
208
|
+
[
|
209
|
+
"_match[#{@index}] = #{target_name}; true",
|
210
|
+
[],
|
211
|
+
free_index
|
212
|
+
]
|
213
|
+
end
|
90
214
|
end
|
91
215
|
|
92
|
-
class
|
93
|
-
def initialize(pats)
|
216
|
+
class LogicalOp < self
|
217
|
+
def initialize(pats, op_str)
|
94
218
|
@pats = pats
|
219
|
+
@op_str = op_str
|
220
|
+
end
|
221
|
+
def compile_internal(free_index, target_name = "_obj")
|
222
|
+
srcs = []
|
223
|
+
i = free_index
|
224
|
+
ctxs = []
|
225
|
+
@pats.each do|pat|
|
226
|
+
s, c, i = pat.compile_internal(i, target_name)
|
227
|
+
srcs << s
|
228
|
+
ctxs << c
|
229
|
+
end
|
230
|
+
|
231
|
+
[
|
232
|
+
srcs.map{|s| "(#{s})" }.join(" #{@op_str}\n"),
|
233
|
+
ctxs.flatten(1),
|
234
|
+
i
|
235
|
+
]
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
class Or < LogicalOp
|
240
|
+
def initialize(pats)
|
241
|
+
super(pats, '||')
|
95
242
|
end
|
96
243
|
def execute(mmatch, obj)
|
97
244
|
@pats.any? do|pat|
|
@@ -99,16 +246,16 @@ module Patm
|
|
99
246
|
end
|
100
247
|
end
|
101
248
|
def rest?
|
102
|
-
@pats.any?(
|
249
|
+
@pats.any?(&:rest?)
|
103
250
|
end
|
104
251
|
def inspect
|
105
252
|
"OR(#{@pats.map(&:inspect).join(',')})"
|
106
253
|
end
|
107
254
|
end
|
108
255
|
|
109
|
-
class And <
|
256
|
+
class And < LogicalOp
|
110
257
|
def initialize(pats)
|
111
|
-
|
258
|
+
super(pats, '&&')
|
112
259
|
end
|
113
260
|
def execute(mmatch, obj)
|
114
261
|
@pats.all? do|pat|
|
@@ -129,18 +276,27 @@ module Patm
|
|
129
276
|
ARRAY_REST = Pattern::ArrRest.new
|
130
277
|
|
131
278
|
class Rule
|
132
|
-
def initialize(&block)
|
279
|
+
def initialize(compile = false, &block)
|
280
|
+
@compile = compile
|
133
281
|
# { Pattern => Proc }
|
134
282
|
@rules = []
|
135
283
|
block[self]
|
136
284
|
end
|
137
285
|
|
138
286
|
def on(pat, &block)
|
139
|
-
@
|
287
|
+
if @compile
|
288
|
+
@rules << [Pattern.build_from(pat).compile, block]
|
289
|
+
else
|
290
|
+
@rules << [Pattern.build_from(pat), block]
|
291
|
+
end
|
140
292
|
end
|
141
293
|
|
142
294
|
def else(&block)
|
143
|
-
@
|
295
|
+
if @compile
|
296
|
+
@rules << [ANY.compile, lambda {|m,o| block[o] }]
|
297
|
+
else
|
298
|
+
@rules << [ANY, lambda {|m,o| block[o] }]
|
299
|
+
end
|
144
300
|
end
|
145
301
|
|
146
302
|
def apply(obj)
|
@@ -155,11 +311,12 @@ module Patm
|
|
155
311
|
end
|
156
312
|
|
157
313
|
class RuleCache
|
158
|
-
def initialize
|
314
|
+
def initialize(compile = false)
|
315
|
+
@compile = compile
|
159
316
|
@rules = {}
|
160
317
|
end
|
161
318
|
def match(rule_name, obj, &rule)
|
162
|
-
(@rules[rule_name] ||= ::Patm::Rule.new(&rule)).apply(obj)
|
319
|
+
(@rules[rule_name] ||= ::Patm::Rule.new(@compile, &rule)).apply(obj)
|
163
320
|
end
|
164
321
|
end
|
165
322
|
|
@@ -206,6 +363,7 @@ module Patm
|
|
206
363
|
end
|
207
364
|
|
208
365
|
def self.match_array(head, rest_spat = nil, tail = [])
|
366
|
+
# TODO: deprecated
|
209
367
|
Match.new(
|
210
368
|
Pattern::Arr.new(
|
211
369
|
head.map{|e| Pattern.build_from(e)},
|
data/patm.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.platform = Gem::Platform::RUBY
|
3
3
|
s.name = 'patm'
|
4
|
-
s.version = '0.0
|
4
|
+
s.version = '0.1.0'
|
5
5
|
s.summary = 'PATtern Matching library'
|
6
6
|
s.description = 'Pattern matching library for plain data structure'
|
7
7
|
s.required_ruby_version = '>= 1.9.0'
|
data/spec/patm_spec.rb
CHANGED
@@ -22,16 +22,16 @@ module PatmHelper
|
|
22
22
|
|
23
23
|
def match; @match; end
|
24
24
|
|
25
|
-
def and_capture(g1, g2 = nil, g3 = nil)
|
25
|
+
def and_capture(g1, g2 = nil, g3 = nil, g4 = nil)
|
26
26
|
these_matches(
|
27
|
-
self, _capture(self, g1, g2, g3)
|
27
|
+
self, _capture(self, g1, g2, g3, g4)
|
28
28
|
)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
matcher :_capture do|m, g1, g2, g3|
|
32
|
+
matcher :_capture do|m, g1, g2, g3, g4|
|
33
33
|
match do|_|
|
34
|
-
[m.match[1], m.match[2], m.match[3]] == [g1, g2, g3]
|
34
|
+
[m.match[1], m.match[2], m.match[3], m.match[4]] == [g1, g2, g3, g4]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -60,6 +60,17 @@ describe "Usage:" do
|
|
60
60
|
r.apply([1, 2, 3]).should == [2, 3]
|
61
61
|
end
|
62
62
|
|
63
|
+
it 'with predefined Rule(compiled)' do
|
64
|
+
p = Patm
|
65
|
+
r = p::Rule.new(true) do|r|
|
66
|
+
r.on [1, p._1, p._2] do|m|
|
67
|
+
[m._1, m._2]
|
68
|
+
end
|
69
|
+
r.else {|obj| [] }
|
70
|
+
end
|
71
|
+
r.apply([1, 2, 3]).should == [2, 3]
|
72
|
+
end
|
73
|
+
|
63
74
|
it 'with RuleCache' do
|
64
75
|
p = Patm
|
65
76
|
rs = p::RuleCache.new
|
@@ -74,6 +85,21 @@ describe "Usage:" do
|
|
74
85
|
|
75
86
|
rs.match(:pattern_1, [1, 3, 5]) {|r| fail "should not reach here" }.should == [3, 5]
|
76
87
|
end
|
88
|
+
|
89
|
+
it 'with RuleCache(compiled)' do
|
90
|
+
p = Patm
|
91
|
+
rs = p::RuleCache.new(true)
|
92
|
+
|
93
|
+
rs.match(:pattern_1, [1, 2, 3]) do|r|
|
94
|
+
r.on [1, p._1, p._2] do|m|
|
95
|
+
[m._1, m._2]
|
96
|
+
end
|
97
|
+
r.else {|obj| [] }
|
98
|
+
end
|
99
|
+
.should == [2, 3]
|
100
|
+
|
101
|
+
rs.match(:pattern_1, [1, 3, 5]) {|r| fail "should not reach here" }.should == [3, 5]
|
102
|
+
end
|
77
103
|
end
|
78
104
|
|
79
105
|
describe Patm::Pattern do
|
@@ -83,6 +109,10 @@ describe Patm::Pattern do
|
|
83
109
|
subject { Patm::Pattern.build_from(plain) }
|
84
110
|
instance_eval(&b)
|
85
111
|
end
|
112
|
+
context "pattern '#{plain.inspect}'(Compiled)" do
|
113
|
+
subject { Patm::Pattern.build_from(plain).compile }
|
114
|
+
instance_eval(&b)
|
115
|
+
end
|
86
116
|
end
|
87
117
|
|
88
118
|
pattern 1 do
|
@@ -125,6 +155,10 @@ describe Patm::Pattern do
|
|
125
155
|
it { should match_to('x').and_capture('x') }
|
126
156
|
end
|
127
157
|
|
158
|
+
pattern Patm._1 & Patm._2 do
|
159
|
+
it { should match_to(1).and_capture(1, 1) }
|
160
|
+
end
|
161
|
+
|
128
162
|
pattern [0, Patm._1, Patm._2] do
|
129
163
|
it { should match_to([0, 1, 2]).and_capture(1, 2) }
|
130
164
|
it { should_not match_to(['x', 1, 2]).and_capture(1, 2) }
|
@@ -140,4 +174,25 @@ describe Patm::Pattern do
|
|
140
174
|
it { should match_to([0, 1]).and_capture([]) }
|
141
175
|
it { should match_to([0, 1, 2, 3]).and_capture([2, 3]) }
|
142
176
|
end
|
177
|
+
|
178
|
+
pattern [0, 1, Patm::ARRAY_REST, 2] do
|
179
|
+
it { should match_to([0,1,2]) }
|
180
|
+
it { should match_to([0,1,10,20,30,2]) }
|
181
|
+
it { should_not match_to([0,1]) }
|
182
|
+
end
|
183
|
+
|
184
|
+
pattern [0, [1, 2]] do
|
185
|
+
it { should match_to [0, [1, 2]] }
|
186
|
+
it { should_not match_to [0, [1, 3]] }
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'regression' do
|
190
|
+
pattern [:assign, [:var_field, [:@ident, Patm._1, [Patm._2, Patm._3]]], Patm._4] do
|
191
|
+
it { should match_to([:assign, [:var_field, [:@ident, 10, [20, 30]]], false]).and_capture(10, 20, 30, false) }
|
192
|
+
end
|
193
|
+
pattern [Patm.or(1, 2)] do
|
194
|
+
it { should match_to [1] }
|
195
|
+
it { should match_to [2] }
|
196
|
+
end
|
197
|
+
end
|
143
198
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- todesking
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- Gemfile
|
49
49
|
- LICENSE
|
50
50
|
- README.md
|
51
|
+
- benchmark/benchmark.rb
|
51
52
|
- lib/patm.rb
|
52
53
|
- patm.gemspec
|
53
54
|
- spec/patm_spec.rb
|
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
72
|
version: '0'
|
72
73
|
requirements: []
|
73
74
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.
|
75
|
+
rubygems_version: 2.0.14
|
75
76
|
signing_key:
|
76
77
|
specification_version: 4
|
77
78
|
summary: PATtern Matching library
|