patm 0.0.1 → 0.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 +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
|