Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions autoload/ruby_hl_lvar.vim.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,15 @@ def extract(source)

define_matcher :handle_massign_lhs_item do|r|
p = Patm
r.on [:var_field, [:@ident, p._1, [p._2, p._3]]] do|m|
[[m._1, m._2, m._3]]
end
r.on [:@ident, p._1, [p._2, p._3]] do|m|
[[m._1, m._2, m._3]]
end
r.on [:mlhs, p._xs[:xs]] do|m, _self|
m[:xs].inject([]) {|lhss, l| lhss + _self.handle_massign_lhs(l) }
end
r.on [:mlhs_paren, p._1] do|m, _self|
_self.handle_massign_lhs(m._1)
end
Expand All @@ -134,6 +140,9 @@ def extract(source)
r.on [p.or(:field, :@ivar, :@cvar, :@gvar, :@const), p._xs] do
[]
end
r.on [:rest_param, p._1] do|m, _self|
_self.handle_massign_lhs_item(m._1)
end
r.on nil do
[]
end
Expand Down
2 changes: 2 additions & 0 deletions vendor/patm/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Gemfile.lock
*.gem
coverage
coverage.vim
7 changes: 7 additions & 0 deletions vendor/patm/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: ruby
rvm:
- 2.1.2
- 2.0.0
- 1.9.3
- 1.9.2
script: rspec
202 changes: 163 additions & 39 deletions vendor/patm/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
# PATM: PATtern Matcher for Ruby

[![Build Status](https://travis-ci.org/todesking/patm.svg?branch=master)](https://travis-ci.org/todesking/patm)
[![Code Climate](https://codeclimate.com/github/todesking/patm.png)](https://codeclimate.com/github/todesking/patm)

PATM is extremely faster pattern match library.

Features: Match value/classes, Capture, Array/Hash decomposition.

## Usage

```ruby
require 'patm'
```

```ruby
# With DSL
class A
extend ::Patm::DSL

define_matcher :match1 do|r|
p = Patm
r.on [:x, p._1, p._2] do|m|
[m._1, m._2]
end
end

define_matcher :match2 do|r|
r.on [:a, Patm._xs & Patm._1] do|m, _self|
_self.match1(m._1)
end
# ...
r.else do
nil
end
end
end

A.new.match1([:x, 1, 2])
# => [1, 2]
```

```ruby
# With case(simple but slow)
def match(obj)
Expand Down Expand Up @@ -52,57 +86,147 @@ rule.apply([])
# => nil
```

## DSL

```ruby
# With cached rules
class A
def initialize
@rules = Patm::RuleCache.new
class PatternMatcher
extend Patm::DSL

define_matcher(:match) do|r| # r is instance of Patm::Rule
# r.on( PATTERN ) {|match, _self|
# First argument is instance of Patm::Match. Use it to access captured value.
# ex. m._1, m._2, ..., m[capture_name]
#
# Second argument is instance of the class. Use it to access other methods.
# ex. _self.other_method
# }
#
# r.else {|value, _self|
# First argument is the value. Second is instance of the class.
# }
end
end

def match1(obj)
@rules.match(:match1, obj) do|r|
p = Patm
r.on [:x, p._1, p._2] do|m|
[m._1, m._2]
end
end
end
matcher = PatternMatcher.new

def match2(obj)
@rules.match(:match2, obj) do|r|
# ...
end
end
end
```
matcher.match(1)
```

```ruby
# With DSL
class A
extend ::Patm::DSL
## Patterns

define_matcher :match1 do|r|
p = Patm
r.on [:x, p._1, p._2] do|m|
[m._1, m._2]
end
end
### Value

define_matcher :match2 do|r|
r.on [:a, Patm._xs & Patm._1] do|m, _self|
_self.match1(m._1)
end
# ...
end
Value patterns such as `1, :x, String, ...` matches if `pattern === target_value` is true.

### Struct

```ruby
A = Struct.new(:x, :y)

# ...
define_matcher :match_struct do|r|
# use Patm[struct_class].( ... ) for match struct
# argument is a Hash(member_name => pattern) or patterns that correspond struct members.
r.on Patm[A].(x: 1, y: Patm._1) {|m| m._1 }
r.on Patm[A].(2, Patm._1) {|m| m._1 }
end
```

### Array

`[1, 2, _any]` matches `[1, 2, 3]`, `[1, 2, :x]`, etc.

`[1, 2, _xs]` matches `[1, 2]`, `[1, 2, 3]`, `[1, 2, 3, 4]`, etc.

`[1, _xs, 2]` matches `[1, 2]`, `[1, 10, 2]`, etc.

Note: More than one `_xs` in same array is invalid.

### Hash

`{a: 1}` matches `{a: 1}`, `{a: 1, b: 2}`, etc.

`{a: 1, Patm.exact => true}` matches only `{a: 1}`.

`{a: 1, b: Patm.opt(2)}` matches `{a: 1}`, `{a: 1, b: 2}`.

### Capture

`_1`, `_2`, etc matches any value, and capture the value as correspond match group.

`Pattern#[capture_name]` also used for capture.`Patm._any[:foo]` capture any value as `foo`.

Captured values are accessible through `Match#_1, _2, ...` and `Match#[capture_name]`

### Compose

`_1&[_any, _any]` matches any two element array, and capture the array as _1.
`Patm.or(1, 2)` matches 1 or 2.


## Performance

see [benchmark code](./benchmark/comparison.rb) for details

Machine: MacBook Air(Late 2010) C2D 1.8GHz, OS X 10.9.2

```
RUBY_VERSION: 2.1.2 p95

Benchmark: Empty(x10000)
user system total real
manual 0.010000 0.000000 0.010000 ( 0.012252)
patm 0.060000 0.000000 0.060000 ( 0.057050)
pattern_match 1.710000 0.010000 1.720000 ( 1.765749)

Benchmark: SimpleConst(x10000)
user system total real
manual 0.020000 0.000000 0.020000 ( 0.018274)
patm 0.060000 0.000000 0.060000 ( 0.075068)
patm_case 0.160000 0.000000 0.160000 ( 0.161002)
pattern_match 1.960000 0.020000 1.980000 ( 2.007936)

Benchmark: ArrayDecomposition(x10000)
user system total real
manual 0.050000 0.000000 0.050000 ( 0.047948)
patm 0.250000 0.000000 0.250000 ( 0.254039)
patm_case 1.710000 0.000000 1.710000 ( 1.765656)
pattern_match 12.890000 0.060000 12.950000 ( 13.343334)

Benchmark: VarArray(x10000)
user system total real
manual 0.050000 0.000000 0.050000 ( 0.052425)
patm 0.210000 0.000000 0.210000 ( 0.223190)
patm_case 1.440000 0.000000 1.440000 ( 1.587535)
pattern_match 10.050000 0.070000 10.120000 ( 10.898683)
```

A.new.match1([:x, 1, 2])
# => [1, 2]
```

## Changes

### x.x.x
### 3.1.0

- Struct matcher

### 3.0.0

- If given value can't match any pattern and no `else`, `Patm::NoMatchError` raised(Instead of return nil).
- RuleCache is now obsoleted. Use DSL.
- More optimized compiler

### 2.0.1

- Bugfix: About pattern `Patm._1 & Array`.
- Bugfix: Compiler bug fix.

### 2.0.0

- Named capture
- Patm::GROUPS is obsolete. Use `pattern[number_or_name]` or `Patm._1, _2, ...` instead.
- More optimize for compiled pattern.
- Hash patterns

### 1.0.0

- DSL
- Compile is enabled by default
Expand Down
4 changes: 2 additions & 2 deletions vendor/patm/benchmark/benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def match_with_case(obj)
end
end

@rule = P::Rule.new(false, &@ruledef)
@compiled_rule = P::Rule.new(true, &@ruledef)
@rule = P::Rule.new(&@ruledef)
@compiled_rule = P::Rule.new(&@ruledef).compile

def match_with_rule(obj)
@rule.apply(obj)
Expand Down
Loading