class Puppet::Functions::Function3x
Constants
- PARAM_NAMES
Table of optimized parameter names - 0 to 5 parameters
Public Class Methods
create_function(func_name, func_info, loader)
click to toggle source
Creates an anonymous Function3x
class that wraps a 3x function
@api private
# File lib/puppet/functions.rb 697 def self.create_function(func_name, func_info, loader) 698 func_name = func_name.to_s 699 700 # Creates an anonymous class to represent the function 701 # The idea being that it is garbage collected when there are no more 702 # references to it. 703 # 704 # (Do not give the class the block here, as instance variables should be set first) 705 the_class = Class.new(Function3x) 706 707 unless loader.nil? 708 the_class.instance_variable_set(:'@loader', loader.private_loader) 709 end 710 711 the_class.instance_variable_set(:'@func_name', func_name) 712 the_class.instance_variable_set(:'@method3x', :"function_#{func_name}") 713 714 # Make the anonymous class appear to have the class-name <func_name> 715 # Even if this class is not bound to such a symbol in a global ruby scope and 716 # must be resolved via the loader. 717 # This also overrides any attempt to define a name method in the given block 718 # (Since it redefines it) 719 # 720 the_class.instance_eval do 721 def name 722 @func_name 723 end 724 725 def loader 726 @loader 727 end 728 729 def method3x 730 @method3x 731 end 732 end 733 734 # Add the method that is called - it simply delegates to 735 # the 3.x function by calling it via the calling scope using the @method3x symbol 736 # :"function_#{name}". 737 # 738 # When function is not an rvalue function, make sure it produces nil 739 # 740 the_class.class_eval do 741 742 # Bypasses making the call via the dispatcher to make sure errors 743 # are reported exactly the same way as in 3x. The dispatcher is still needed as it is 744 # used to support other features than calling. 745 # 746 def call(scope, *args, &block) 747 begin 748 result = catch(:return) do 749 mapped_args = Puppet::Pops::Evaluator::Runtime3FunctionArgumentConverter.map_args(args, scope, '') 750 # this is the scope.function_xxx(...) call 751 return scope.send(self.class.method3x, mapped_args) 752 end 753 return result.value 754 rescue Puppet::Pops::Evaluator::Next => jumper 755 begin 756 throw :next, jumper.value 757 rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION 758 raise Puppet::ParseError.new("next() from context where this is illegal", jumper.file, jumper.line) 759 end 760 rescue Puppet::Pops::Evaluator::Return => jumper 761 begin 762 throw :return, jumper 763 rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION 764 raise Puppet::ParseError.new("return() from context where this is illegal", jumper.file, jumper.line) 765 end 766 end 767 end 768 end 769 770 # Create a dispatcher based on func_info 771 type, names = Puppet::Functions.any_signature(*from_to_names(func_info)) 772 last_captures_rest = (type.size_range[1] == Float::INFINITY) 773 774 # The method '3x_function' here is a dummy as the dispatcher is not used for calling, only for information. 775 the_class.dispatcher.add(Puppet::Pops::Functions::Dispatch.new(type, '3x_function', names, last_captures_rest)) 776 # The function class is returned as the result of the create function method 777 the_class 778 end
from_to_names(func_info)
click to toggle source
Compute min and max number of arguments and a list of constructed parameter names p0 - pn (since there are no parameter names in 3x functions).
@api private
# File lib/puppet/functions.rb 784 def self.from_to_names(func_info) 785 arity = func_info[:arity] 786 if arity.nil? 787 arity = -1 788 end 789 if arity < 0 790 from = -arity - 1 # arity -1 is 0 min param, -2 is min 1 param 791 to = :default # infinite range 792 count = -arity # the number of named parameters 793 else 794 count = from = to = arity 795 end 796 # Names of parameters, up to 5 are optimized and use frozen version 797 # Note that (0..count-1) produces expected empty array for count == 0, 0-n for count >= 1 798 names = count <= 5 ? PARAM_NAMES[count] : (0..count-1).map {|n| "p#{n}" } 799 [from, to, names] 800 end
Public Instance Methods
call(scope, *args, &block)
click to toggle source
Bypasses making the call via the dispatcher to make sure errors are reported exactly the same way as in 3x. The dispatcher is still needed as it is used to support other features than calling.
# File lib/puppet/functions.rb 746 def call(scope, *args, &block) 747 begin 748 result = catch(:return) do 749 mapped_args = Puppet::Pops::Evaluator::Runtime3FunctionArgumentConverter.map_args(args, scope, '') 750 # this is the scope.function_xxx(...) call 751 return scope.send(self.class.method3x, mapped_args) 752 end 753 return result.value 754 rescue Puppet::Pops::Evaluator::Next => jumper 755 begin 756 throw :next, jumper.value 757 rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION 758 raise Puppet::ParseError.new("next() from context where this is illegal", jumper.file, jumper.line) 759 end 760 rescue Puppet::Pops::Evaluator::Return => jumper 761 begin 762 throw :return, jumper 763 rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION 764 raise Puppet::ParseError.new("return() from context where this is illegal", jumper.file, jumper.line) 765 end 766 end 767 end
loader()
click to toggle source
# File lib/puppet/functions.rb 725 def loader 726 @loader 727 end
method3x()
click to toggle source
# File lib/puppet/functions.rb 729 def method3x 730 @method3x 731 end
name()
click to toggle source
# File lib/puppet/functions.rb 721 def name 722 @func_name 723 end