patm 3.0.0 → 3.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/README.md +19 -0
- data/lib/patm.rb +153 -60
- data/patm.gemspec +1 -1
- data/spec/patm_spec.rb +21 -0
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: fce015f4cd31a8ee0eb2227373c6e809302411ed
         | 
| 4 | 
            +
              data.tar.gz: 7000cb5f66f204896bf207e8fee63a9f07387e60
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 778234a77d4bf3e4cbc1f3132e29f55ac1dad6f4fb5738f0d7da1145f3f8b4a1bcf9d3e36d7b9271dfd74cf047ed0880178ba6022f64479a91b4d338b8e7c589
         | 
| 7 | 
            +
              data.tar.gz: cba96914ce05332a949d851a48fbfd3d3a840812b4fb402c9b6b6ec55b274bad532bdeea239c77bc9afb9f7a5adf8bd5e073188cb902222e8dbd322bc3bd505a
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # PATM: PATtern Matcher for Ruby
         | 
| 2 2 |  | 
| 3 3 | 
             
            [](https://travis-ci.org/todesking/patm)
         | 
| 4 | 
            +
            [](https://codeclimate.com/github/todesking/patm)
         | 
| 4 5 |  | 
| 5 6 | 
             
            PATM is extremely faster pattern match library.
         | 
| 6 7 |  | 
| @@ -117,6 +118,20 @@ matcher.match(1) | |
| 117 118 |  | 
| 118 119 | 
             
            Value patterns such as `1, :x, String, ...` matches if `pattern === target_value` is true.
         | 
| 119 120 |  | 
| 121 | 
            +
            ### Struct
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            ```ruby
         | 
| 124 | 
            +
            A = Struct.new(:x, :y)
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            # ...
         | 
| 127 | 
            +
            define_matcher :match_struct do|r|
         | 
| 128 | 
            +
              # use Patm[struct_class].( ... ) for match struct
         | 
| 129 | 
            +
              # argument is a Hash(member_name => pattern) or patterns that correspond struct members.
         | 
| 130 | 
            +
              r.on Patm[A].(x: 1, y: Patm._1) {|m| m._1 }
         | 
| 131 | 
            +
              r.on Patm[A].(2, Patm._1) {|m| m._1 }
         | 
| 132 | 
            +
            end
         | 
| 133 | 
            +
            ```
         | 
| 134 | 
            +
             | 
| 120 135 | 
             
            ### Array
         | 
| 121 136 |  | 
| 122 137 | 
             
            `[1, 2, _any]` matches `[1, 2, 3]`, `[1, 2, :x]`, etc.
         | 
| @@ -189,6 +204,10 @@ pattern_match  10.050000   0.070000  10.120000 ( 10.898683) | |
| 189 204 |  | 
| 190 205 | 
             
            ## Changes
         | 
| 191 206 |  | 
| 207 | 
            +
            ### 3.1.0
         | 
| 208 | 
            +
             | 
| 209 | 
            +
            - Struct matcher
         | 
| 210 | 
            +
             | 
| 192 211 | 
             
            ### 3.0.0
         | 
| 193 212 |  | 
| 194 213 | 
             
            - If given value can't match any pattern and no `else`, `Patm::NoMatchError` raised(Instead of return nil).
         | 
    
        data/lib/patm.rb
    CHANGED
    
    | @@ -13,28 +13,36 @@ module Patm | |
| 13 13 | 
             
                  when Pattern
         | 
| 14 14 | 
             
                    plain
         | 
| 15 15 | 
             
                  when ::Array
         | 
| 16 | 
            -
                     | 
| 17 | 
            -
                    rest_index = array.index(&:rest?)
         | 
| 18 | 
            -
                    if rest_index
         | 
| 19 | 
            -
                      head = array[0...rest_index]
         | 
| 20 | 
            -
                      rest = array[rest_index]
         | 
| 21 | 
            -
                      tail = array[(rest_index+1)..-1]
         | 
| 22 | 
            -
                      Arr.new(head, rest, tail)
         | 
| 23 | 
            -
                    else
         | 
| 24 | 
            -
                      Arr.new(array)
         | 
| 25 | 
            -
                    end
         | 
| 16 | 
            +
                    build_from_array(plain)
         | 
| 26 17 | 
             
                  when ::Hash
         | 
| 27 | 
            -
                     | 
| 28 | 
            -
                      plain.each_with_object({}) do|(k, v), h|
         | 
| 29 | 
            -
                        h[k] = build_from(v) if k != Patm.exact
         | 
| 30 | 
            -
                      end,
         | 
| 31 | 
            -
                      plain[Patm.exact]
         | 
| 32 | 
            -
                    )
         | 
| 18 | 
            +
                    build_from_hash(plain)
         | 
| 33 19 | 
             
                  else
         | 
| 34 20 | 
             
                    Obj.new(plain)
         | 
| 35 21 | 
             
                  end
         | 
| 36 22 | 
             
                end
         | 
| 37 23 |  | 
| 24 | 
            +
                def self.build_from_array(plain)
         | 
| 25 | 
            +
                  array = plain.map{|a| build_from(a)}
         | 
| 26 | 
            +
                  rest_index = array.index(&:rest?)
         | 
| 27 | 
            +
                  if rest_index
         | 
| 28 | 
            +
                    head = array[0...rest_index]
         | 
| 29 | 
            +
                    rest = array[rest_index]
         | 
| 30 | 
            +
                    tail = array[(rest_index+1)..-1]
         | 
| 31 | 
            +
                    Arr.new(head, rest, tail)
         | 
| 32 | 
            +
                  else
         | 
| 33 | 
            +
                    Arr.new(array)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def self.build_from_hash(plain)
         | 
| 38 | 
            +
                  self::Hash.new(
         | 
| 39 | 
            +
                    plain.each_with_object({}) do|(k, v), h|
         | 
| 40 | 
            +
                      h[k] = build_from(v) if k != Patm.exact
         | 
| 41 | 
            +
                    end,
         | 
| 42 | 
            +
                    plain[Patm.exact]
         | 
| 43 | 
            +
                  )
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 38 46 | 
             
                module Util
         | 
| 39 47 | 
             
                  def self.compile_value(value, free_index)
         | 
| 40 48 | 
             
                    if value.nil? || value.is_a?(Numeric) || value.is_a?(String) || value.is_a?(Symbol)
         | 
| @@ -200,16 +208,24 @@ module Patm | |
| 200 208 | 
             
                  end
         | 
| 201 209 |  | 
| 202 210 | 
             
                  def execute(mmatch, obj)
         | 
| 203 | 
            -
                    size_min = @head.size + @tail.size
         | 
| 204 211 | 
             
                    return false unless obj.is_a?(Array)
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                    @head. | 
| 212 | 
            +
             | 
| 213 | 
            +
                    size_min = @head.size + @tail.size
         | 
| 214 | 
            +
                    if @rest
         | 
| 215 | 
            +
                      return false if obj.size < size_min
         | 
| 216 | 
            +
                    else
         | 
| 217 | 
            +
                      return false if obj.size != size_min
         | 
| 218 | 
            +
                    end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                    return false unless @head.zip(obj[0..(@head.size - 1)]).all? {|pat, o|
         | 
| 207 221 | 
             
                      pat.execute(mmatch, o)
         | 
| 208 | 
            -
                    } | 
| 209 | 
            -
             | 
| 222 | 
            +
                    }
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                    return false unless @tail.zip(obj[(-@tail.size)..-1]).all? {|pat, o|
         | 
| 210 225 | 
             
                      pat.execute(mmatch, o)
         | 
| 211 | 
            -
                    } | 
| 212 | 
            -
             | 
| 226 | 
            +
                    }
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                    !@rest || @rest.execute(mmatch, obj[@head.size..-(@tail.size+1)])
         | 
| 213 229 | 
             
                  end
         | 
| 214 230 |  | 
| 215 231 | 
             
                  def inspect
         | 
| @@ -227,48 +243,59 @@ module Patm | |
| 227 243 |  | 
| 228 244 | 
             
                    srcs << "#{target_name}.is_a?(::Array)"
         | 
| 229 245 |  | 
| 230 | 
            -
                     | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 246 | 
            +
                    i = compile_size_check(target_name, srcs, ctxs, i)
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                    i = compile_part(target_name, @head, srcs, ctxs, i)
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    unless @tail.empty?
         | 
| 251 | 
            +
                      srcs << "#{target_name}_t = #{target_name}[(-#{@tail.size})..-1]; true"
         | 
| 252 | 
            +
                      i = compile_part("#{target_name}_t", @tail, srcs, ctxs, i)
         | 
| 235 253 | 
             
                    end
         | 
| 236 254 |  | 
| 237 | 
            -
                     | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 255 | 
            +
                    i = compile_rest(target_name, srcs, ctxs, i)
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                    [
         | 
| 258 | 
            +
                      srcs.compact.map{|s| "(#{s})"}.join(" &&\n"),
         | 
| 259 | 
            +
                      ctxs.flatten(1),
         | 
| 260 | 
            +
                      i
         | 
| 261 | 
            +
                    ]
         | 
| 262 | 
            +
                  end
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                  private
         | 
| 265 | 
            +
                    def compile_size_check(target_name, srcs, ctxs, i)
         | 
| 266 | 
            +
                      size_min = @head.size + @tail.size
         | 
| 267 | 
            +
                      if @rest
         | 
| 268 | 
            +
                        srcs << "#{target_name}.size >= #{size_min}"
         | 
| 243 269 | 
             
                      else
         | 
| 244 | 
            -
                         | 
| 245 | 
            -
                        srcs << "#{elm_target_name} = #{target_name}[#{hi}]; #{s}" if s
         | 
| 246 | 
            -
                        ctxs << c
         | 
| 270 | 
            +
                        srcs << "#{target_name}.size == #{size_min}"
         | 
| 247 271 | 
             
                      end
         | 
| 272 | 
            +
                      i
         | 
| 248 273 | 
             
                    end
         | 
| 249 274 |  | 
| 250 | 
            -
                     | 
| 251 | 
            -
                       | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 275 | 
            +
                    def compile_part(target_name, part, srcs, ctxs, i)
         | 
| 276 | 
            +
                      part.each_with_index do|h, hi|
         | 
| 277 | 
            +
                        if h.is_a?(Obj)
         | 
| 278 | 
            +
                          s, c, i = h.compile_internal(i, "#{target_name}[#{hi}]")
         | 
| 279 | 
            +
                          srcs << "#{s}" if s
         | 
| 280 | 
            +
                          ctxs << c
         | 
| 281 | 
            +
                        else
         | 
| 282 | 
            +
                          elm_target_name = "#{target_name}_elm"
         | 
| 283 | 
            +
                          s, c, i = h.compile_internal(i, elm_target_name)
         | 
| 284 | 
            +
                          srcs << "#{elm_target_name} = #{target_name}[#{hi}]; #{s}" if s
         | 
| 285 | 
            +
                          ctxs << c
         | 
| 286 | 
            +
                        end
         | 
| 256 287 | 
             
                      end
         | 
| 288 | 
            +
                      i
         | 
| 257 289 | 
             
                    end
         | 
| 258 290 |  | 
| 259 | 
            -
                     | 
| 291 | 
            +
                    def compile_rest(target_name, srcs, ctxs, i)
         | 
| 292 | 
            +
                      return i unless @rest
         | 
| 260 293 | 
             
                      tname = "#{target_name}_r"
         | 
| 261 294 | 
             
                      s, c, i = @rest.compile_internal(i, tname)
         | 
| 262 295 | 
             
                      srcs << "#{tname} = #{target_name}[#{@head.size}..-(#{@tail.size+1})];#{s}" if s
         | 
| 263 296 | 
             
                      ctxs << c
         | 
| 264 | 
            -
                    end
         | 
| 265 | 
            -
             | 
| 266 | 
            -
                    [
         | 
| 267 | 
            -
                      srcs.compact.map{|s| "(#{s})"}.join(" &&\n"),
         | 
| 268 | 
            -
                      ctxs.flatten(1),
         | 
| 269 297 | 
             
                      i
         | 
| 270 | 
            -
                     | 
| 271 | 
            -
                  end
         | 
| 298 | 
            +
                    end
         | 
| 272 299 | 
             
                end
         | 
| 273 300 |  | 
| 274 301 | 
             
                class ArrRest < self
         | 
| @@ -323,6 +350,70 @@ module Patm | |
| 323 350 | 
             
                  end
         | 
| 324 351 | 
             
                end
         | 
| 325 352 |  | 
| 353 | 
            +
                class Struct < self
         | 
| 354 | 
            +
                  def initialize(klass, pat)
         | 
| 355 | 
            +
                    @klass, @pat = klass, pat
         | 
| 356 | 
            +
                  end
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                  def inspect
         | 
| 359 | 
            +
                    "STRUCT(#{@klass.name || "<unnamed>"}, #{@pat.inspect})"
         | 
| 360 | 
            +
                  end
         | 
| 361 | 
            +
             | 
| 362 | 
            +
                  def execute(match, obj)
         | 
| 363 | 
            +
                    obj.is_a?(@klass) && @pat.all?{|k, v| v.execute(match, obj[k]) }
         | 
| 364 | 
            +
                  end
         | 
| 365 | 
            +
             | 
| 366 | 
            +
                  def compile_internal(free_index, target_name = "_obj")
         | 
| 367 | 
            +
                    srcs = []
         | 
| 368 | 
            +
                    ctxs = []
         | 
| 369 | 
            +
                    i = free_index
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                    if @klass.name
         | 
| 372 | 
            +
                      srcs << "#{target_name}.is_a?(::#{@klass.name})"
         | 
| 373 | 
            +
                    else
         | 
| 374 | 
            +
                      srcs << "#{target_name}.is_a?(_ctx[#{i}])"
         | 
| 375 | 
            +
                      ctxs << [@klass]
         | 
| 376 | 
            +
                      i += 1
         | 
| 377 | 
            +
                    end
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                    @pat.each do|(member, v)|
         | 
| 380 | 
            +
                      s, c, i = v.compile_internal(i, "#{target_name}_elm")
         | 
| 381 | 
            +
                      srcs << "#{target_name}_elm = #{target_name}.#{member}; #{s}" if s
         | 
| 382 | 
            +
                      ctxs << c
         | 
| 383 | 
            +
                    end
         | 
| 384 | 
            +
             | 
| 385 | 
            +
                    [
         | 
| 386 | 
            +
                      srcs.map{|s| "(#{s})"}.join(" &&\n"),
         | 
| 387 | 
            +
                      ctxs.flatten(1),
         | 
| 388 | 
            +
                      i
         | 
| 389 | 
            +
                    ]
         | 
| 390 | 
            +
                  end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                  class Builder
         | 
| 393 | 
            +
                    def initialize(klass)
         | 
| 394 | 
            +
                      raise ArgumentError, "#{klass} is not Struct" unless klass.ancestors.include?(::Struct)
         | 
| 395 | 
            +
                      @klass = klass
         | 
| 396 | 
            +
                    end
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                    # member_1_pat -> member_2_pat -> ... -> Pattern
         | 
| 399 | 
            +
                    # {member:Symbol => pattern} -> Pattern
         | 
| 400 | 
            +
                    def call(*args)
         | 
| 401 | 
            +
                      if args.size == 1 && args.first.is_a?(::Hash)
         | 
| 402 | 
            +
                        hash = args.first
         | 
| 403 | 
            +
                        hash.keys.each do|k|
         | 
| 404 | 
            +
                          raise ArgumentError, "#{k.inspect} is not member of #{@klass}" unless @klass.members.include?(k)
         | 
| 405 | 
            +
                        end
         | 
| 406 | 
            +
                        Struct.new(@klass, hash.each_with_object({}){|(k, plain), h|
         | 
| 407 | 
            +
                          h[k] = Pattern.build_from(plain)
         | 
| 408 | 
            +
                        })
         | 
| 409 | 
            +
                      else
         | 
| 410 | 
            +
                        raise ArgumentError, "Member size not match: expected #{@klass.members.size} but #{args.size}" unless args.size == @klass.members.size
         | 
| 411 | 
            +
                        Struct.new(@klass, ::Hash[*@klass.members.zip(args.map{|a| Pattern.build_from(a) }).flatten(1)])
         | 
| 412 | 
            +
                      end
         | 
| 413 | 
            +
                    end
         | 
| 414 | 
            +
                  end
         | 
| 415 | 
            +
                end
         | 
| 416 | 
            +
             | 
| 326 417 | 
             
                class Named < self
         | 
| 327 418 | 
             
                  def initialize(name)
         | 
| 328 419 | 
             
                    raise ::ArgumentError unless name.is_a?(Symbol) || name.is_a?(Numeric)
         | 
| @@ -345,7 +436,8 @@ module Patm | |
| 345 436 | 
             
                end
         | 
| 346 437 |  | 
| 347 438 | 
             
                class LogicalOp < self
         | 
| 348 | 
            -
                  def initialize(pats, op_str)
         | 
| 439 | 
            +
                  def initialize(name, pats, op_str)
         | 
| 440 | 
            +
                    @name = name
         | 
| 349 441 | 
             
                    @pats = pats
         | 
| 350 442 | 
             
                    @op_str = op_str
         | 
| 351 443 | 
             
                  end
         | 
| @@ -375,34 +467,31 @@ module Patm | |
| 375 467 | 
             
                  def opt?
         | 
| 376 468 | 
             
                    @pats.any?(&:opt?)
         | 
| 377 469 | 
             
                  end
         | 
| 470 | 
            +
                  def inspect
         | 
| 471 | 
            +
                    "#{@name}(#{@pats.map(&:inspect).join(',')})"
         | 
| 472 | 
            +
                  end
         | 
| 378 473 | 
             
                end
         | 
| 379 474 |  | 
| 380 475 | 
             
                class Or < LogicalOp
         | 
| 381 476 | 
             
                  def initialize(pats)
         | 
| 382 | 
            -
                    super(pats, '||')
         | 
| 477 | 
            +
                    super('OR', pats, '||')
         | 
| 383 478 | 
             
                  end
         | 
| 384 479 | 
             
                  def execute(mmatch, obj)
         | 
| 385 480 | 
             
                    @pats.any? do|pat|
         | 
| 386 481 | 
             
                      pat.execute(mmatch, obj)
         | 
| 387 482 | 
             
                    end
         | 
| 388 483 | 
             
                  end
         | 
| 389 | 
            -
                  def inspect
         | 
| 390 | 
            -
                    "OR(#{@pats.map(&:inspect).join(',')})"
         | 
| 391 | 
            -
                  end
         | 
| 392 484 | 
             
                end
         | 
| 393 485 |  | 
| 394 486 | 
             
                class And < LogicalOp
         | 
| 395 487 | 
             
                  def initialize(pats)
         | 
| 396 | 
            -
                    super(pats, '&&')
         | 
| 488 | 
            +
                    super('AND', pats, '&&')
         | 
| 397 489 | 
             
                  end
         | 
| 398 490 | 
             
                  def execute(mmatch, obj)
         | 
| 399 491 | 
             
                    @pats.all? do|pat|
         | 
| 400 492 | 
             
                      pat.execute(mmatch, obj)
         | 
| 401 493 | 
             
                    end
         | 
| 402 494 | 
             
                  end
         | 
| 403 | 
            -
                  def inspect
         | 
| 404 | 
            -
                    "AND(#{@pats.map(&:inspect).join(',')})"
         | 
| 405 | 
            -
                  end
         | 
| 406 495 | 
             
                end
         | 
| 407 496 | 
             
              end
         | 
| 408 497 |  | 
| @@ -434,6 +523,10 @@ module Patm | |
| 434 523 | 
             
                EXACT
         | 
| 435 524 | 
             
              end
         | 
| 436 525 |  | 
| 526 | 
            +
              def self.[](struct_klass)
         | 
| 527 | 
            +
                Pattern::Struct::Builder.new(struct_klass)
         | 
| 528 | 
            +
              end
         | 
| 529 | 
            +
             | 
| 437 530 | 
             
              PREDEF_GROUP_SIZE = 100
         | 
| 438 531 |  | 
| 439 532 | 
             
              class <<self
         | 
    
        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     = '3. | 
| 4 | 
            +
              s.version     = '3.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
    
    | @@ -2,6 +2,7 @@ require 'simplecov' | |
| 2 2 | 
             
            require 'simplecov-vim/formatter'
         | 
| 3 3 | 
             
            SimpleCov.start do
         | 
| 4 4 | 
             
              formatter SimpleCov::Formatter::VimFormatter
         | 
| 5 | 
            +
              formatter SimpleCov::Formatter::HTMLFormatter
         | 
| 5 6 | 
             
            end
         | 
| 6 7 |  | 
| 7 8 | 
             
            require File.join(File.dirname(__FILE__), '..', 'lib', 'patm.rb')
         | 
| @@ -300,6 +301,26 @@ describe Patm::Pattern do | |
| 300 301 | 
             
                it { should     match_to({a: 1} => {b: 2}) }
         | 
| 301 302 | 
             
              end
         | 
| 302 303 |  | 
| 304 | 
            +
              Struct1 = Struct.new(:a, :b)
         | 
| 305 | 
            +
             | 
| 306 | 
            +
              pattern(Patm[Struct1].(1, Patm._1)) do
         | 
| 307 | 
            +
                it { should_not match_to(nil) }
         | 
| 308 | 
            +
                it { should_not match_to(Struct1.new(2, 2)) }
         | 
| 309 | 
            +
                it { should     match_to(Struct1.new(1, 2)).and_capture(2) }
         | 
| 310 | 
            +
              end
         | 
| 311 | 
            +
             | 
| 312 | 
            +
              pattern(Patm[Struct1].(a: 1, b: Patm._1)) do
         | 
| 313 | 
            +
                it { should_not match_to(nil) }
         | 
| 314 | 
            +
                it { should_not match_to(Struct1.new(2, 2)) }
         | 
| 315 | 
            +
                it { should     match_to(Struct1.new(1, 2)).and_capture(2) }
         | 
| 316 | 
            +
              end
         | 
| 317 | 
            +
             | 
| 318 | 
            +
              unnamed_struct = Struct.new(:x, :y)
         | 
| 319 | 
            +
              pattern(Patm[unnamed_struct].(x: 1, y: Patm._1)) do
         | 
| 320 | 
            +
                it { should_not match_to(nil) }
         | 
| 321 | 
            +
                it { should match_to(unnamed_struct.new(1, 2)).and_capture(2) }
         | 
| 322 | 
            +
              end
         | 
| 323 | 
            +
             | 
| 303 324 | 
             
              context 'regression' do
         | 
| 304 325 | 
             
                pattern [:assign, [:var_field, [:@ident, Patm._1, [Patm._2, Patm._3]]], Patm._4] do
         | 
| 305 326 | 
             
                  it { should match_to([:assign, [:var_field, [:@ident, 10, [20, 30]]], false]).and_capture(10, 20, 30, false) }
         | 
    
        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: 3. | 
| 4 | 
            +
              version: 3.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-05- | 
| 11 | 
            +
            date: 2014-05-25 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: simplecov
         |