Spec-Zone.ru › Ruby 3.4

класс Prism::Pattern

Родитель:
Object

Шаблон — это объект, который оборачивает выражение сопоставления с образцом на Ruby. Выражение обычно передается в оператор «in» в выражении «case» или в оператор правого присваивания. Например, в следующем фрагменте:

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

шаблоном является ConstantPathNode[...] выражение.

Шаблон компилируется в объект, который отвечает на вызов, выполняя метод compile. Этот метод сам выполнит обратный проход через Prism для разбора выражения в дерево, а затем пройдется по дереву, чтобы сгенерировать необходимые вызываемые объекты. Например, если вы хотите скомпилировать вышеприведенное выражение в вызываемый объект, вы должны:

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

Вызываемый объект, возвращаемый методом compile, гарантированно отвечает на вызов с одним аргументом, который представляет собой узел для сравнения. Он также гарантированно отвечает на ===, что означает, что он сам может использоваться в выражении «case», как в:

case node
when callable
end

Если запрос, переданный инициализатору, не может быть скомпилирован в допустимый согласующийся объект (по причине синтаксической ошибки или из-за использования синтаксиса, который мы пока не поддерживаем), будет поднято исключение Prism::Pattern::CompilationError.

Атрибуты

query [R]

Запрос, с которым был инициализирован этот шаблон.

Публичные методы класса

new (query)
Source
# File lib/prism/pattern.rb, line 63
def initialize(query)
  @query = query
  @compiled = nil
end

Создайте новый шаблон с заданным запросом. Запрос должен быть строкой, содержащей выражение сопоставления шаблонов Ruby.

Публичные методы экземпляра

compile ()
Source
# File lib/prism/pattern.rb, line 70
def compile
  result = Prism.parse("case nil\nin #{query}\nend")

  case_match_node = result.value.statements.body.last
  raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode)

  in_node = case_match_node.conditions.last
  raise CompilationError, in_node.inspect unless in_node.is_a?(InNode)

  compile_node(in_node.pattern)
end

Компилирует запрос в вызываемый объект, который может использоваться для сопоставления с узлами.

scan (root) { |node| ... }
Source
# File lib/prism/pattern.rb, line 86
def scan(root)
  return to_enum(:scan, root) unless block_given?

  @compiled ||= compile
  queue = [root]

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

Сканирует заданный узел и все его дочерние узлы на наличие узлов, которые соответствуют шаблону. Если предоставлен блок, он будет вызван для каждого узла, который соответствует шаблону. Если блок не предоставлен, будет возвращен перечислитель, который будет передавать каждый узел, соответствующий шаблону.

Приватные методы экземпляра

combine_and (left, right)
Source
# File lib/prism/pattern.rb, line 102
def combine_and(left, right)
  ->(other) { left.call(other) && right.call(other) }
end

Сокращение для объединения двух проков в один, который возвращает true, если оба возвращают true.

combine_or (left, right)
Source
# File lib/prism/pattern.rb, line 108
def combine_or(left, right)
  ->(other) { left.call(other) || right.call(other) }
end

Сокращение для объединения двух проков в один, который возвращает true, если хотя бы один возвращает true.

compile_alternation_pattern_node (node)
Source
# File lib/prism/pattern.rb, line 143
def compile_alternation_pattern_node(node)
  combine_or(compile_node(node.left), compile_node(node.right))
end

in foo | bar

compile_array_pattern_node (node)
Source
# File lib/prism/pattern.rb, line 118
def compile_array_pattern_node(node)
  compile_error(node) if !node.rest.nil? || node.posts.any?

  constant = node.constant
  compiled_constant = compile_node(constant) if constant

  preprocessed = node.requireds.map { |required| compile_node(required) }

  compiled_requireds = ->(other) do
    deconstructed = other.deconstruct

    deconstructed.length == preprocessed.length &&
      preprocessed
        .zip(deconstructed)
        .all? { |(matcher, value)| matcher.call(value) }
  end

  if compiled_constant
    combine_and(compiled_constant, compiled_requireds)
  else
    compiled_requireds
  end
end

in [foo, bar, baz]

compile_constant_name (node, name)
Source
# File lib/prism/pattern.rb, line 168
def compile_constant_name(node, name)
  if Prism.const_defined?(name, false)
    clazz = Prism.const_get(name)

    ->(other) { clazz === other }
  elsif Object.const_defined?(name, false)
    clazz = Object.const_get(name)

    ->(other) { clazz === other }
  else
    compile_error(node)
  end
end

Компиляция имени, связанного с константой.

compile_constant_path_node (node)
Source
# File lib/prism/pattern.rb, line 148
def compile_constant_path_node(node)
  parent = node.parent

  if parent.is_a?(ConstantReadNode) && parent.slice == "Prism"
    name = node.name
    raise CompilationError, node.inspect if name.nil?

    compile_constant_name(node, name)
  else
    compile_error(node)
  end
end

in Prism::ConstantReadNode

compile_constant_read_node (node)
Source
# File lib/prism/pattern.rb, line 163
def compile_constant_read_node(node)
  compile_constant_name(node, node.name)
end

in ConstantReadNode in String

compile_error (node)
Source
# File lib/prism/pattern.rb, line 113
def compile_error(node)
  raise CompilationError, node.inspect
end

Вызвать ошибку, потому что данный узел не поддерживается.

compile_hash_pattern_node (node)
Source
# File lib/prism/pattern.rb, line 184
def compile_hash_pattern_node(node)
  compile_error(node) if node.rest
  compiled_constant = compile_node(node.constant) if node.constant

  preprocessed =
    node.elements.to_h do |element|
      key = element.key
      if key.is_a?(SymbolNode)
        [key.unescaped.to_sym, compile_node(element.value)]
      else
        raise CompilationError, element.inspect
      end
    end

  compiled_keywords = ->(other) do
    deconstructed = other.deconstruct_keys(preprocessed.keys)

    preprocessed.all? do |keyword, matcher|
      deconstructed.key?(keyword) && matcher.call(deconstructed[keyword])
    end
  end

  if compiled_constant
    combine_and(compiled_constant, compiled_keywords)
  else
    compiled_keywords
  end
end

in InstanceVariableReadNode[name: Symbol] in { name: Symbol }

compile_nil_node (node)
Source
# File lib/prism/pattern.rb, line 214
def compile_nil_node(node)
  ->(attribute) { attribute.nil? }
end

in nil

compile_node (node)
Source
# File lib/prism/pattern.rb, line 243
def compile_node(node)
  case node
  when AlternationPatternNode
    compile_alternation_pattern_node(node)
  when ArrayPatternNode
    compile_array_pattern_node(node)
  when ConstantPathNode
    compile_constant_path_node(node)
  when ConstantReadNode
    compile_constant_read_node(node)
  when HashPatternNode
    compile_hash_pattern_node(node)
  when NilNode
    compile_nil_node(node)
  when RegularExpressionNode
    compile_regular_expression_node(node)
  when StringNode
    compile_string_node(node)
  when SymbolNode
    compile_symbol_node(node)
  else
    compile_error(node)
  end
end

Компиляция любого типа узла. Диспечеризация в отдельные методы компиляции на основе типа узла.

compile_regular_expression_node (node)
Source
# File lib/prism/pattern.rb, line 219
def compile_regular_expression_node(node)
  regexp = Regexp.new(node.unescaped, node.closing[1..])

  ->(attribute) { regexp === attribute }
end

in /foo/

compile_string_node (node)
Source
# File lib/prism/pattern.rb, line 227
def compile_string_node(node)
  string = node.unescaped

  ->(attribute) { string === attribute }
end

in “” in “foo”

compile_symbol_node (node)
Source
# File lib/prism/pattern.rb, line 235
def compile_symbol_node(node)
  symbol = node.unescaped.to_sym

  ->(attribute) { symbol === attribute }
end

in :+ in :foo

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API