lib/rubocop/ast/node_pattern/compiler/binding.rb
# frozen_string_literal: true module RuboCop module AST class NodePattern class Compiler # Holds the list of bound variable names class Binding def initialize @bound = {} end # Yields the first time a given name is bound # # @return [String] bound variable name 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 # Returns currently bound variable names # @return [Array<String>] variable names that are currently bound def bound_variables @bound.values end # Yields for each branch of the given union, forbidding unification of # bindings which only appear in a subset of the union. def union_bind(enum) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize # 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 def forbid(names) names.each do |name| @bound[name] = :forbidden_unification end end end end end end end