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

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

Overview

as the API for obtaining information in a callable-implementation agnostic way.

Direct Known Subclasses

Named

Defined Under Namespace

Classes: Named

Constant Summary collapse

CLOSURE_NAME =
'lambda'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from CallableSignature

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

Constructor Details

#initialize(evaluator, model, scope) ⇒ Closure

Returns a new instance of Closure.



21
22
23
24
25
# File 'lib/puppet/pops/evaluator/closure.rb', line 21

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

Instance Attribute Details

#enclosing_scopeObject (readonly)



19
20
21
# File 'lib/puppet/pops/evaluator/closure.rb', line 19

def enclosing_scope
  @enclosing_scope
end

#evaluatorObject (readonly)



17
18
19
# File 'lib/puppet/pops/evaluator/closure.rb', line 17

def evaluator
  @evaluator
end

#modelObject (readonly)



18
19
20
# File 'lib/puppet/pops/evaluator/closure.rb', line 18

def model
  @model
end

Instance Method Details

#block_nameObject



99
100
101
102
# File 'lib/puppet/pops/evaluator/closure.rb', line 99

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)



29
30
31
# File 'lib/puppet/pops/evaluator/closure.rb', line 29

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



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/puppet/pops/evaluator/closure.rb', line 44

def call_by_name(args_hash, enforce_parameters)
  if enforce_parameters
    # Push a temporary parameter scope used while resolving the parameter defaults
    @enclosing_scope.with_parameter_scope(parameter_names) do |param_scope|
      args_hash.each { |k, v| param_scope[k] = v unless v.nil? && parameter_names.include?(k) }
      parameters.each do |p|
        name = p.name
        # only set result of default expr if it is defined (it is otherwise not possible to differentiate
        # between explicit undef and no default expression
        arg = args_hash[name]
        if arg.nil? && !p.value.nil?
          param_scope[name] = param_scope.evaluate(name, p.value, @enclosing_scope, @evaluator)
        end
      end
      args_hash = param_scope.to_hash
    end
    Types::TypeMismatchDescriber.validate_parameters(closure_name, params_struct, args_hash)
  end

  @evaluator.evaluate_block_with_bindings(@enclosing_scope, args_hash, @model.body)
end

#closure_nameObject



107
108
109
# File 'lib/puppet/pops/evaluator/closure.rb', line 107

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



37
38
39
40
41
# File 'lib/puppet/pops/evaluator/closure.rb', line 37

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:

  • (Boolean)


93
94
95
96
# File 'lib/puppet/pops/evaluator/closure.rb', line 93

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

#parameter_countInteger

Returns the number of parameters (required and optional)

Returns:

  • (Integer)

    the total number of accepted parameters



72
73
74
75
# File 'lib/puppet/pops/evaluator/closure.rb', line 72

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

#parameter_namesObject



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

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

#parametersObject



66
67
68
# File 'lib/puppet/pops/evaluator/closure.rb', line 66

def parameters
  @model.parameters
end

#params_structObject



88
89
90
# File 'lib/puppet/pops/evaluator/closure.rb', line 88

def params_struct
  @params_struct ||= create_params_struct
end

#typeObject



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

def type
  @callable ||= create_callable_type
end