Class: Puppet::Pops::Evaluator::Closure
Overview
A Closure represents logic bound to a particular scope. As long as the runtime (basically the scope implementation) has the behavior of Puppet 3x it is not safe to return and later use this closure.
The 3x scope is essentially a named scope with an additional internal local/ephemeral nested scope state. In 3x there is no way to directly refer to the nested scopes, instead, the named scope must be in a particular state. Specifically, closures that require a local/ephemeral scope to exist at a later point will fail. It is safe to call a closure (even with 3x scope) from the very same place it was defined, but not returning it and expecting the closure to reference the scope’s state at the point it was created.
Note that this class is a CallableSignature, and the methods defined there should be used as the API for obtaining information in a callable-implementation agnostic way.
Defined Under Namespace
Classes: Dynamic, Named
Constant Summary
collapse
- CLOSURE_NAME =
'lambda'.freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
#args_range, #argument_mismatch_handler?, #block_range, #block_type, #infinity?
Constructor Details
#initialize(evaluator, model) ⇒ Closure
Returns a new instance of Closure.
60
61
62
63
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 60
def initialize(evaluator, model)
@evaluator = evaluator
@model = model
end
|
Instance Attribute Details
#enclosing_scope ⇒ Object
58
59
60
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 58
def enclosing_scope
@enclosing_scope
end
|
#evaluator ⇒ Object
56
57
58
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 56
def evaluator
@evaluator
end
|
57
58
59
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 57
def model
@model
end
|
Instance Method Details
#block_name ⇒ Object
153
154
155
156
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 153
def block_name
'unsupported_block'
end
|
#call(*args) ⇒ Object
Evaluates a closure in its enclosing scope after having matched given arguments with parameters (from left to right)
67
68
69
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 67
def call(*args)
call_with_scope(enclosing_scope, args)
end
|
#call_by_name(args_hash, enforce_parameters) ⇒ Object
Call closure with argument assignment by name
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 82
def call_by_name(args_hash, enforce_parameters)
closure_scope = enclosing_scope
if enforce_parameters
closure_scope.with_parameter_scope(closure_name, parameter_names) do |param_scope|
args_hash.each { |k, v| param_scope[k] = v unless v.nil? }
parameters.each do |p|
name = p.name
arg = args_hash[name]
if arg.nil?
if p.value.nil?
param_scope[name] = nil if args_hash.include?(name)
else
param_scope[name] = param_scope.evaluate(name, p.value, closure_scope, @evaluator)
end
end
end
args_hash = param_scope.to_hash
end
Types::TypeMismatchDescriber.validate_parameters(closure_name, params_struct, args_hash)
result = catch(:next) do
@evaluator.evaluate_block_with_bindings(closure_scope, args_hash, @model.body)
end
Types::TypeAsserter.assert_instance_of(nil, return_type, result) do
"value returned from #{closure_name}"
end
else
@evaluator.evaluate_block_with_bindings(closure_scope, args_hash, @model.body)
end
end
|
#closure_name ⇒ Object
161
162
163
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 161
def closure_name()
CLOSURE_NAME
end
|
#invoke(instance, calling_scope, args, &block) ⇒ Object
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
This method makes a Closure compatible with a Dispatch. This is used when the closure is wrapped in a Function and the function is called. (Saves an extra Dispatch that just delegates to a Closure and avoids having two checks of the argument type/arity validity).
75
76
77
78
79
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 75
def invoke(instance, calling_scope, args, &block)
enclosing_scope.with_global_scope do |global_scope|
call_with_scope(global_scope, args, &block)
end
end
|
#last_captures_rest? ⇒ Boolean
147
148
149
150
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 147
def last_captures_rest?
last = @model.parameters[-1]
last && last.captures_rest
end
|
#parameter_count ⇒ Integer
Returns the number of parameters (required and optional)
122
123
124
125
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 122
def parameter_count
@model.parameters.size
end
|
#parameter_names ⇒ Object
128
129
130
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 128
def parameter_names
@model.parameters.collect(&:name)
end
|
#parameters ⇒ Object
116
117
118
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 116
def parameters
@model.parameters
end
|
#params_struct ⇒ Object
142
143
144
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 142
def params_struct
@params_struct ||= create_params_struct
end
|
#return_type ⇒ Object
132
133
134
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 132
def return_type
@return_type ||= create_return_type
end
|
137
138
139
|
# File 'lib/puppet/pops/evaluator/closure.rb', line 137
def type
@callable ||= create_callable_type
end
|