Module: Ruby::Rego::Evaluator::VariableCollectorHelpers

Defined in:
lib/ruby/rego/evaluator/variable_collector/pattern_names.rb,
lib/ruby/rego/evaluator/variable_collector/dispatch_tables.rb

Overview

Node-class dispatch tables and lookups for variable collection.

Constant Summary collapse

NODE_COLLECTORS =
{
  AST::Variable => ->(node, collector) { collector.send(:add_name, node.name) },
  AST::SomeDecl => ->(node, collector) { collector.send(:collect_some_decl, node) },
  AST::Every => ->(node, collector) { collector.send(:collect_every, node) },
  AST::QueryLiteral => ->(node, collector) { collector.send(:collect_node, node.expression) },
  AST::ArrayComprehension => lambda do |node, collector|
    collector.send(:collect_comprehension, [node.term], node.body)
  end,
  AST::SetComprehension => lambda do |node, collector|
    collector.send(:collect_comprehension, [node.term], node.body)
  end,
  AST::ObjectComprehension => lambda do |node, collector|
    key_node, value_node = node.term
    collector.send(:collect_comprehension, [key_node, value_node], node.body)
  end
}.freeze
CHILDREN_EXTRACTORS =
{
  AST::Reference => ->(node) { [node.base] + node.path.map(&:value) },
  AST::BinaryOp => ->(node) { [node.left, node.right] },
  AST::UnaryOp => ->(node) { [node.operand] },
  AST::ArrayLiteral => :elements.to_proc,
  AST::SetLiteral => :elements.to_proc,
  AST::ObjectLiteral => lambda do |node|
    node.pairs.flat_map { |key_node, value_node| [key_node, value_node] }
  end,
  AST::ArrayComprehension => ->(node) { [node.term] },
  AST::SetComprehension => ->(node) { [node.term] },
  AST::ObjectComprehension => lambda do |node|
    key_node, value_node = node.term
    [key_node, value_node]
  end,
  AST::Call => ->(node) { node.args.dup }
}.freeze

Class Method Summary collapse

Class Method Details

.children_for(node) ⇒ Object



47
48
49
50
51
52
# File 'lib/ruby/rego/evaluator/variable_collector/dispatch_tables.rb', line 47

def self.children_for(node)
  extractor = CHILDREN_EXTRACTORS[node.class]
  return [] unless extractor

  extractor.call(node)
end

.collector_for(node) ⇒ Object



43
44
45
# File 'lib/ruby/rego/evaluator/variable_collector/dispatch_tables.rb', line 43

def self.collector_for(node)
  NODE_COLLECTORS[node.class]
end

.comprehension_node?(node) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/ruby/rego/evaluator/variable_collector/dispatch_tables.rb', line 54

def self.comprehension_node?(node)
  node.is_a?(AST::ArrayComprehension) || node.is_a?(AST::SetComprehension) || node.is_a?(AST::ObjectComprehension)
end

.some_decl_all_names(variables) ⇒ Object

All variable names appearing in some targets, including object keys. Keys are referenced but never bound, so they surface as unsafe when not bound elsewhere (OPA rejects a variable object key in a pattern).



16
17
18
# File 'lib/ruby/rego/evaluator/variable_collector/pattern_names.rb', line 16

def self.some_decl_all_names(variables)
  variables.flat_map { |variable| some_pattern_all_names(variable) }
end

.some_decl_names(variables) ⇒ Object

Variable names bound by a list of some targets (value positions only).



9
10
11
# File 'lib/ruby/rego/evaluator/variable_collector/pattern_names.rb', line 9

def self.some_decl_names(variables)
  variables.flat_map { |variable| some_pattern_names(variable) }
end

.some_pattern_all_names(node) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'lib/ruby/rego/evaluator/variable_collector/pattern_names.rb', line 20

def self.some_pattern_all_names(node)
  case node
  when AST::Variable then [node.name]
  when AST::ArrayLiteral then node.elements.flat_map { |element| some_pattern_all_names(element) }
  when AST::ObjectLiteral
    node.pairs.flat_map { |(key, value)| some_pattern_all_names(key) + some_pattern_all_names(value) }
  else []
  end
end

.some_pattern_names(node) ⇒ Object

Variable names bound by a single some target, recursing into array/object destructuring patterns (value positions only; object keys are matched, not bound).



33
34
35
36
37
38
39
40
# File 'lib/ruby/rego/evaluator/variable_collector/pattern_names.rb', line 33

def self.some_pattern_names(node)
  case node
  when AST::Variable then [node.name]
  when AST::ArrayLiteral then node.elements.flat_map { |element| some_pattern_names(element) }
  when AST::ObjectLiteral then node.pairs.flat_map { |(_key, value)| some_pattern_names(value) }
  else []
  end
end