Class: Puppet::Pops::Evaluator::Closure

Inherits:
CallableSignature show all
Defined in:
lib/puppet/pops/evaluator/closure.rb

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.

API:

  • public

Direct Known Subclasses

Dynamic, Named

Defined Under Namespace

Classes: Dynamic, Named

Constant Summary collapse

CLOSURE_NAME =

API:

  • public

'lambda'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from CallableSignature

#args_range, #argument_mismatch_handler?, #block_range, #block_type, #infinity?

Constructor Details

#initialize(evaluator, model) ⇒ Closure

Returns a new instance of Closure.

API:

  • public



61
62
63
64
# File 'lib/puppet/pops/evaluator/closure.rb', line 61

def initialize(evaluator, model)
  @evaluator = evaluator
  @model = model
end

Instance Attribute Details

#enclosing_scopeObject (readonly)

API:

  • public



59
60
61
# File 'lib/puppet/pops/evaluator/closure.rb', line 59

def enclosing_scope
  @enclosing_scope
end

#evaluatorObject (readonly)

API:

  • public



57
58
59
# File 'lib/puppet/pops/evaluator/closure.rb', line 57

def evaluator
  @evaluator
end

#modelObject (readonly)

API:

  • public



58
59
60
# File 'lib/puppet/pops/evaluator/closure.rb', line 58

def model
  @model
end

Instance Method Details

#block_nameObject

API:

  • public



162
163
164
165
# File 'lib/puppet/pops/evaluator/closure.rb', line 162

def block_name
  # TODO: Lambda's does not support blocks yet. This is a placeholder
  'unsupported_block'
end

#call(*args) ⇒ Object

Evaluates a closure in its enclosing scope after having matched given arguments with parameters (from left to right)

API:

  • public



68
69
70
# File 'lib/puppet/pops/evaluator/closure.rb', line 68

def call(*args)
  call_with_scope(enclosing_scope, args)
end

#call_by_name(args_hash, enforce_parameters) ⇒ Object

API:

  • public



86
87
88
# File 'lib/puppet/pops/evaluator/closure.rb', line 86

def call_by_name(args_hash, enforce_parameters)
  call_by_name_internal(enclosing_scope, args_hash, enforce_parameters)
end

#call_by_name_with_scope(scope, args_hash, enforce_parameters) ⇒ Object

API:

  • public



82
83
84
# File 'lib/puppet/pops/evaluator/closure.rb', line 82

def call_by_name_with_scope(scope, args_hash, enforce_parameters)
  call_by_name_internal(scope, args_hash, enforce_parameters)
end

#closure_nameObject

API:

  • public



170
171
172
# File 'lib/puppet/pops/evaluator/closure.rb', line 170

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).

API:

  • private



76
77
78
79
80
# File 'lib/puppet/pops/evaluator/closure.rb', line 76

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

Returns:

API:

  • public



156
157
158
159
# File 'lib/puppet/pops/evaluator/closure.rb', line 156

def last_captures_rest?
  last = @model.parameters[-1]
  last && last.captures_rest
end

#parameter_countInteger

Returns the number of parameters (required and optional)

Returns:

  • the total number of accepted parameters

API:

  • public



131
132
133
134
# File 'lib/puppet/pops/evaluator/closure.rb', line 131

def parameter_count
  # yes, this is duplication of code, but it saves a method call
  @model.parameters.size
end

#parameter_namesObject

API:

  • public



137
138
139
# File 'lib/puppet/pops/evaluator/closure.rb', line 137

def parameter_names
  @model.parameters.collect(&:name)
end

#parametersObject

API:

  • public



125
126
127
# File 'lib/puppet/pops/evaluator/closure.rb', line 125

def parameters
  @model.parameters
end

#params_structObject

API:

  • public



151
152
153
# File 'lib/puppet/pops/evaluator/closure.rb', line 151

def params_struct
  @params_struct ||= create_params_struct
end

#return_typeObject

API:

  • public



141
142
143
# File 'lib/puppet/pops/evaluator/closure.rb', line 141

def return_type
  @return_type ||= create_return_type
end

#typeObject

API:

  • public



146
147
148
# File 'lib/puppet/pops/evaluator/closure.rb', line 146

def type
  @callable ||= create_callable_type
end