Class: Prism::Pattern

Inherits:
Object
  • Object
show all
Defined in:
lib/prism/pattern.rb

Overview

A pattern is an object that wraps a Ruby pattern matching expression. The expression would normally be passed to an ‘in` clause within a `case` expression or a rightward assignment expression. For example, in the following snippet:

case node
in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]
end

the pattern is the ‘ConstantPathNode` expression.

The pattern gets compiled into an object that responds to #call by running the #compile method. This method itself will run back through Prism to parse the expression into a tree, then walk the tree to generate the necessary callable objects. For example, if you wanted to compile the expression above into a callable, you would:

callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile
callable.call(node)

The callable object returned by #compile is guaranteed to respond to #call with a single argument, which is the node to match against. It also is guaranteed to respond to #===, which means it itself can be used in a ‘case` expression, as in:

case node
when callable
end

If the query given to the initializer cannot be compiled into a valid matcher (either because of a syntax error or because it is using syntax we do not yet support) then a Prism::Pattern::CompilationError will be raised.

Defined Under Namespace

Classes: CompilationError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query) ⇒ Pattern

Returns a new instance of Pattern.



58
59
60
61
# File 'lib/prism/pattern.rb', line 58

def initialize(query)
  @query = query
  @compiled = nil
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



56
57
58
# File 'lib/prism/pattern.rb', line 56

def query
  @query
end

Instance Method Details

#compileObject



63
64
65
66
# File 'lib/prism/pattern.rb', line 63

def compile
  result = Prism.parse("case nil\nin #{query}\nend")
  compile_node(result.value.statements.body.last.conditions.last.pattern)
end

#scan(root) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/prism/pattern.rb', line 68

def scan(root)
  return to_enum(__method__, root) unless block_given?

  @compiled ||= compile
  queue = [root]

  while (node = queue.shift)
    yield node if @compiled.call(node)
    queue.concat(node.compact_child_nodes)
  end
end