Module: Ruby::Rego::Unifier::Helpers

Defined in:
lib/ruby/rego/unifier/helpers.rb

Overview

Internal helpers that do not rely on instance state.

Class Method Summary collapse

Class Method Details

.bound_value_for(name, bindings, env) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/ruby/rego/unifier/helpers.rb', line 76

def self.bound_value_for(name, bindings, env)
  bound = bindings[name]
  return bound if bound && !bound.is_a?(UndefinedValue)

  env_value = env.lookup(name)
  return nil if env_value.is_a?(UndefinedValue)

  env_value
end

.candidate_keys_for(key_pattern, env, bindings) ⇒ Object

An object-pattern key must be ground: a literal, or a variable already bound elsewhere. An unbound variable key (or wildcard) yields no candidate — OPA rejects it as unsafe rather than enumerating keys.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ruby/rego/unifier/helpers.rb', line 110

def self.candidate_keys_for(key_pattern, env, bindings)
  if key_pattern.is_a?(AST::Variable)
    bound_value = bound_value_for(key_pattern.name, bindings, env)
    return bound_value ? [normalize_key(bound_value.to_ruby)] : []
  end

  key_value = value_for_pattern(key_pattern, env)
  return [] if key_value.is_a?(UndefinedValue)

  [normalize_key(key_value.to_ruby)]
end

.match_scalar(pattern, resolved_value, env, bindings) ⇒ Object

:reek:LongParameterList



123
124
125
126
# File 'lib/ruby/rego/unifier/helpers.rb', line 123

def self.match_scalar(pattern, resolved_value, env, bindings)
  pattern_value = scalar_pattern_value(pattern, env)
  pattern_value == resolved_value ? [bindings] : []
end

.merge_bindings(bindings, additions) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/ruby/rego/unifier/helpers.rb', line 86

def self.merge_bindings(bindings, additions)
  conflict = additions.any? do |name, value|
    existing = bindings[name]
    existing && existing != value
  end
  return nil if conflict

  bindings.merge(additions)
end

.normalize_array(value) ⇒ Object



33
34
35
36
37
38
# File 'lib/ruby/rego/unifier/helpers.rb', line 33

def self.normalize_array(value)
  return normalize_elements(value.to_ruby) if value.is_a?(ArrayValue)
  return normalize_elements(value) if value.is_a?(Array)

  nil
end

.normalize_elements(elements) ⇒ Object



40
41
42
43
44
45
46
47
48
# File 'lib/ruby/rego/unifier/helpers.rb', line 40

def self.normalize_elements(elements)
  values = [] # @type var values: Array[Value]
  elements.each do |element|
    values << Value.from_ruby(element)
  rescue ArgumentError, ObjectKeyConflictError
    return nil
  end
  values
end

.normalize_key(key) ⇒ Object



50
51
52
# File 'lib/ruby/rego/unifier/helpers.rb', line 50

def self.normalize_key(key)
  key.is_a?(Symbol) ? key.to_s : key
end

.normalize_object(value) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/ruby/rego/unifier/helpers.rb', line 61

def self.normalize_object(value)
  return nil unless (pairs = object_pairs(value))

  values = {} # @type var values: Hash[Object, Value]
  pairs.each do |key, val|
    normalized_key = normalize_key(key)
    return nil if values.key?(normalized_key)

    values[normalized_key] = Value.from_ruby(val)
  end
  values
rescue ArgumentError, ObjectKeyConflictError
  nil
end

.normalize_value(value, env) ⇒ Object



19
20
21
22
23
24
25
26
27
# File 'lib/ruby/rego/unifier/helpers.rb', line 19

def self.normalize_value(value, env)
  return value if value.is_a?(Value)
  return env.resolve_reference(value) if value.is_a?(AST::Reference)
  return Value.from_ruby(value.value) if value.is_a?(AST::Literal)

  Value.from_ruby(value)
rescue ArgumentError, ObjectKeyConflictError
  UndefinedValue.new
end

.object_pairs(value) ⇒ Object



54
55
56
57
58
59
# File 'lib/ruby/rego/unifier/helpers.rb', line 54

def self.object_pairs(value)
  return value.to_ruby if value.is_a?(ObjectValue)
  return value if value.is_a?(Hash)

  nil
end

.scalar_pattern_value(pattern, env) ⇒ Object



9
10
11
12
13
14
15
16
17
# File 'lib/ruby/rego/unifier/helpers.rb', line 9

def self.scalar_pattern_value(pattern, env)
  return Value.from_ruby(pattern.value) if pattern.is_a?(AST::Literal)
  return env.resolve_reference(pattern) if pattern.is_a?(AST::Reference)
  return pattern if pattern.is_a?(Value)

  Value.from_ruby(pattern)
rescue ArgumentError, ObjectKeyConflictError
  UndefinedValue.new
end

.unify_variable(variable, value, env, bindings) ⇒ Object

:reek:LongParameterList



97
98
99
100
101
102
103
104
105
# File 'lib/ruby/rego/unifier/helpers.rb', line 97

def self.unify_variable(variable, value, env, bindings)
  name = variable.name
  return [bindings] if name == "_"

  bound_value = bound_value_for(name, bindings, env)
  return bound_value == value ? [bindings] : [] if bound_value

  [bindings.merge(name => value)]
end

.value_for_pattern(pattern, env) ⇒ Object



29
30
31
# File 'lib/ruby/rego/unifier/helpers.rb', line 29

def self.value_for_pattern(pattern, env)
  Helpers.scalar_pattern_value(pattern, env)
end