Class: Ruby::Rego::Environment
- Inherits:
-
Object
- Object
- Ruby::Rego::Environment
- Defined in:
- lib/ruby/rego/environment.rb
Overview
Execution environment for evaluating Rego policies. :reek:TooManyInstanceVariables rubocop:disable Metrics/ClassLength
Defined Under Namespace
Classes: State
Constant Summary collapse
- RESERVED_BINDINGS =
{ "input" => :input, "data" => :data }.freeze
- RESERVED_NAMES =
RESERVED_BINDINGS.keys.freeze
Constants included from EnvironmentOverrides
Ruby::Rego::EnvironmentOverrides::UNSET
Instance Attribute Summary collapse
-
#builtin_registry ⇒ Builtins::BuiltinRegistry, Builtins::BuiltinRegistryOverlay
readonly
Builtin registry in use.
-
#data ⇒ Value
readonly
Data document as a Rego value.
-
#input ⇒ Value
readonly
Input document as a Rego value.
-
#memoization ⇒ Memoization::Store
readonly
Memoization store for evaluation caches.
-
#rules ⇒ Hash
readonly
Rule index by name.
Class Method Summary collapse
-
.from_state(state) ⇒ Environment
Build an environment from a state struct.
Instance Method Summary collapse
-
#bind(name, value) ⇒ Value
Bind a local name to a value.
-
#initialize(input: {}, data: {}, rules: {}, builtin_registry: Builtins::BuiltinRegistry.instance) ⇒ Environment
constructor
Create an evaluation environment.
-
#local_bound?(name) ⇒ Boolean
Check whether a name is bound in any local scope.
-
#lookup(name) ⇒ Value
Lookup a binding from the current scope chain.
-
#pop_scope ⇒ void
Pop the latest local scope.
-
#prepare_for_pool ⇒ Environment
Reset the environment for pool reuse.
-
#push_scope ⇒ Environment
Push a new scope for local bindings.
-
#reset(state) ⇒ Environment
Reset environment state for reuse without mutation semantics.
-
#reset!(state) ⇒ Environment
Reset environment state for reuse.
-
#with_bindings(bindings) ⇒ Object
Execute a block with additional temporary bindings.
-
#with_builtin_registry(registry) {|environment| ... } ⇒ Object
Execute a block with an overridden builtin registry.
Methods included from EnvironmentReferenceResolution
#reference_key_for, #resolve_reference
Methods included from EnvironmentOverrides
Constructor Details
#initialize(input: {}, data: {}, rules: {}, builtin_registry: Builtins::BuiltinRegistry.instance) ⇒ Environment
Create an evaluation environment.
57 58 59 60 61 62 63 |
# File 'lib/ruby/rego/environment.rb', line 57 def initialize(input: {}, data: {}, rules: {}, builtin_registry: Builtins::BuiltinRegistry.instance) @memoization = Memoization::Store.new @builtin_registry = builtin_registry @locals = [fresh_scope] # @type var locals: Array[Hash[String, Value]] @scope_pool = [] # @type var @scope_pool: Array[Hash[String, Value]] apply_state(State.new(input: input, data: data, rules: rules, builtin_registry: builtin_registry)) end |
Instance Attribute Details
#builtin_registry ⇒ Builtins::BuiltinRegistry, Builtins::BuiltinRegistryOverlay (readonly)
Builtin registry in use.
44 45 46 |
# File 'lib/ruby/rego/environment.rb', line 44 def builtin_registry @builtin_registry end |
#data ⇒ Value (readonly)
Data document as a Rego value.
34 35 36 |
# File 'lib/ruby/rego/environment.rb', line 34 def data @data end |
#input ⇒ Value (readonly)
Input document as a Rego value.
29 30 31 |
# File 'lib/ruby/rego/environment.rb', line 29 def input @input end |
#memoization ⇒ Memoization::Store (readonly)
Memoization store for evaluation caches.
49 50 51 |
# File 'lib/ruby/rego/environment.rb', line 49 def memoization @memoization end |
#rules ⇒ Hash (readonly)
Rule index by name.
39 40 41 |
# File 'lib/ruby/rego/environment.rb', line 39 def rules @rules end |
Class Method Details
.from_state(state) ⇒ Environment
Build an environment from a state struct.
69 70 71 72 73 74 75 76 |
# File 'lib/ruby/rego/environment.rb', line 69 def self.from_state(state) new( input: state.input, data: state.data, rules: state.rules, builtin_registry: state.builtin_registry ) end |
Instance Method Details
#bind(name, value) ⇒ Value
Bind a local name to a value.
136 137 138 139 140 141 142 143 |
# File 'lib/ruby/rego/environment.rb', line 136 def bind(name, value) name = name.to_s raise Error, "Cannot bind reserved name: #{name}" if RESERVED_NAMES.include?(name) value = Value.from_ruby(value) locals.last[name] = value value end |
#local_bound?(name) ⇒ Boolean
Check whether a name is bound in any local scope.
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/ruby/rego/environment.rb', line 166 def local_bound?(name) name = name.to_s return false if RESERVED_NAMES.include?(name) locals.reverse_each do |scope| return true if scope.key?(name) end false end |
#lookup(name) ⇒ Value
Lookup a binding from the current scope chain.
:reek:TooManyStatements
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ruby/rego/environment.rb', line 150 def lookup(name) name = name.to_s reserved = RESERVED_BINDINGS[name] return public_send(reserved) if reserved locals.reverse_each do |scope| return scope[name] if scope.key?(name) end UndefinedValue.new end |
#pop_scope ⇒ void
This method returns an undefined value.
Pop the latest local scope.
95 96 97 98 99 100 101 102 |
# File 'lib/ruby/rego/environment.rb', line 95 def pop_scope return nil if locals.length <= 1 scope = locals.pop # @type var scope: Hash[String, Value] scope.clear scope_pool << scope nil end |
#prepare_for_pool ⇒ Environment
Reset the environment for pool reuse.
126 127 128 129 |
# File 'lib/ruby/rego/environment.rb', line 126 def prepare_for_pool empty_hash = {} # @type var empty_hash: Hash[untyped, untyped] reset(State.new(input: empty_hash, data: empty_hash, rules: rules, builtin_registry: builtin_registry)) end |
#push_scope ⇒ Environment
Push a new scope for local bindings.
84 85 86 87 88 89 90 |
# File 'lib/ruby/rego/environment.rb', line 84 def push_scope scope = scope_pool.pop scope ||= fresh_scope scope.clear locals << scope self end |
#reset(state) ⇒ Environment
Reset environment state for reuse without mutation semantics.
119 120 121 |
# File 'lib/ruby/rego/environment.rb', line 119 def reset(state) reset!(state) end |
#reset!(state) ⇒ Environment
Reset environment state for reuse.
108 109 110 111 112 113 |
# File 'lib/ruby/rego/environment.rb', line 108 def reset!(state) apply_state(state) reset_scopes memoization.reset! self end |
#with_bindings(bindings) ⇒ Object
Execute a block with additional temporary bindings.
182 183 184 185 186 187 188 |
# File 'lib/ruby/rego/environment.rb', line 182 def with_bindings(bindings) push_scope bindings.each { |name, value| bind(name, value) } yield ensure pop_scope end |
#with_builtin_registry(registry) {|environment| ... } ⇒ Object
Execute a block with an overridden builtin registry.
195 196 197 198 199 200 201 202 203 |
# File 'lib/ruby/rego/environment.rb', line 195 def with_builtin_registry(registry) original = @builtin_registry memoization.with_context do @builtin_registry = registry yield self end ensure @builtin_registry = original end |