class RuboCop::AST::NodePattern::Compiler::Binding

Holds the list of bound variable names

Public Class Methods

new() click to toggle source
# File lib/rubocop/ast/node_pattern/compiler/binding.rb, line 9
def initialize
  @bound = {}
end

Public Instance Methods

bind(name) { |n = bound = "unify_#{gsub('-', '__')}"| ... } click to toggle source

Yields the first time a given name is bound

@return [String] bound variable name

# File lib/rubocop/ast/node_pattern/compiler/binding.rb, line 16
def bind(name)
  var = @bound.fetch(name) do
    yield n = @bound[name] = "unify_#{name.gsub('-', '__')}"
    n
  end

  if var == :forbidden_unification
    raise Invalid, "Wildcard #{name} was first seen in a subset of a" \
                   " union and can't be used outside that union"
  end
  var
end
union_bind(enum) { |e| ... } click to toggle source

rubocop:disable Metrics/MethodLength, Metrics/AbcSize

# File lib/rubocop/ast/node_pattern/compiler/binding.rb, line 30
def union_bind(enum)
  # We need to reset @bound before each branch is processed.
  # Moreover we need to keep track of newly encountered wildcards.
  # Var `newly_bound_intersection` will hold those that are encountered
  # in all branches; these are not a problem.
  # Var `partially_bound` will hold those encountered in only a subset
  # of the branches; these can't be used outside of the union.

  return to_enum __method__, enum unless block_given?

  newly_bound_intersection = nil
  partially_bound = []
  bound_before = @bound.dup

  result = enum.each do |e|
    @bound = bound_before.dup if newly_bound_intersection
    yield e
    newly_bound = @bound.keys - bound_before.keys
    if newly_bound_intersection.nil?
      # First iteration
      newly_bound_intersection = newly_bound
    else
      union = newly_bound_intersection | newly_bound
      newly_bound_intersection &= newly_bound
      partially_bound |= union - newly_bound_intersection
    end
  end

  # At this point, all members of `newly_bound_intersection` can be used
  # for unification outside of the union, but partially_bound may not

  forbid(partially_bound)

  result
end

Private Instance Methods

forbid(names) click to toggle source

rubocop:enable Metrics/MethodLength, Metrics/AbcSize

# File lib/rubocop/ast/node_pattern/compiler/binding.rb, line 69
def forbid(names)
  names.each do |name|
    @bound[name] = :forbidden_unification
  end
end