?
Current Path : /usr/share/ruby/vendor_ruby/puppet/pops/functions/ |
Linux gator3171.hostgator.com 4.19.286-203.ELK.el7.x86_64 #1 SMP Wed Jun 14 04:33:55 CDT 2023 x86_64 |
Current File : //usr/share/ruby/vendor_ruby/puppet/pops/functions/function.rb |
# @note WARNING: This new function API is still under development and may change at # any time # # A function in the puppet evaluator. # # Functions are normally defined by another system, which produces subclasses # of this class as well as constructing delegations to call the appropriate methods. # # This class should rarely be used directly. Instead functions should be # constructed using {Puppet::Functions.create_function}. # # @api public class Puppet::Pops::Functions::Function # The scope where the function was defined attr_reader :closure_scope # The loader that loaded this function. # Should be used if function wants to load other things. # attr_reader :loader def initialize(closure_scope, loader) @closure_scope = closure_scope @loader = loader end # Invokes the function via the dispatching logic that performs type check and weaving. # A specialized function may override this method to do its own dispatching and checking of # the raw arguments. A specialized implementation can rearrange arguments, add or remove # arguments and then delegate to the dispatching logic by calling: # # @example Delegating to the dispatcher # def call(scope, *args) # manipulated_args = args + ['easter_egg'] # self.class.dispatcher.dispatch(self, scope, manipulated_args) # end # # System functions that must have access to the calling scope can use this technique. Functions # in general should not need the calling scope. (The closure scope; what is visible where the function # is defined) is available via the method `closure_scope`). # # @api public def call(scope, *args, &block) self.class.dispatcher.dispatch(self, scope, args, &block) end # Allows the implementation of a function to call other functions by name. The callable functions # are those visible to the same loader that loaded this function (the calling function). The # referenced function is called with the calling functions closure scope as the caller's scope. # # @param function_name [String] The name of the function # @param *args [Object] splat of arguments # @return [Object] The result returned by the called function # # @api public def call_function(function_name, *args, &block) internal_call_function(closure_scope, function_name, args, &block) end # The dispatcher for the function # # @api private def self.dispatcher @dispatcher ||= Puppet::Pops::Functions::Dispatcher.new end # Produces information about parameters in a way that is compatible with Closure # # @api private def self.signatures @dispatcher.signatures end protected # Allows the implementation of a function to call other functions by name and pass the caller # scope. The callable functions are those visible to the same loader that loaded this function # (the calling function). # # @param scope [Puppet::Parser::Scope] The caller scope # @param function_name [String] The name of the function # @param args [Array] array of arguments # @return [Object] The result returned by the called function # # @api public def internal_call_function(scope, function_name, args, &block) the_loader = loader raise ArgumentError, "Function #{self.class.name}(): cannot call function '#{function_name}' - no loader specified" unless the_loader func = the_loader.load(:function, function_name) return func.call(scope, *args, &block) if func # Check if a 3x function is present. Raise a generic error if it's not to allow upper layers to fill in the details # about where in a puppet manifest this error originates. (Such information is not available here). loader_scope = closure_scope func_3x = Puppet::Parser::Functions.function(function_name, loader_scope.environment) if loader_scope.is_a?(Puppet::Parser::Scope) raise ArgumentError, "Function #{self.class.name}(): cannot call function '#{function_name}' - not found" unless func_3x # Call via 3x API # Arguments must be mapped since functions are unaware of the new and magical creatures in 4x. # NOTE: Passing an empty string last converts nil/:undef to empty string result = scope.send(func_3x, Puppet::Pops::Evaluator::Runtime3Converter.map_args(args, loader_scope, ''), &block) # Prevent non r-value functions from leaking their result (they are not written to care about this) Puppet::Parser::Functions.rvalue?(function_name) ? result : nil end end