Method: Puppet::Functions::Function3x.create_function
- Defined in:
- lib/puppet/functions.rb
.create_function(func_name, func_info, loader) ⇒ 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.
Creates an anonymous Function3x class that wraps a 3x function
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 |
# File 'lib/puppet/functions.rb', line 697 def self.create_function(func_name, func_info, loader) func_name = func_name.to_s # Creates an anonymous class to represent the function # The idea being that it is garbage collected when there are no more # references to it. # # (Do not give the class the block here, as instance variables should be set first) the_class = Class.new(Function3x) unless loader.nil? the_class.instance_variable_set(:'@loader', loader.private_loader) end the_class.instance_variable_set(:'@func_name', func_name) the_class.instance_variable_set(:'@method3x', :"function_#{func_name}") # Make the anonymous class appear to have the class-name <func_name> # Even if this class is not bound to such a symbol in a global ruby scope and # must be resolved via the loader. # This also overrides any attempt to define a name method in the given block # (Since it redefines it) # the_class.instance_eval do def name @func_name end def loader @loader end def method3x @method3x end end # Add the method that is called - it simply delegates to # the 3.x function by calling it via the calling scope using the @method3x symbol # :"function_#{name}". # # When function is not an rvalue function, make sure it produces nil # the_class.class_eval do # 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. # def call(scope, *args, &block) result = catch(:return) do mapped_args = Puppet::Pops::Evaluator::Runtime3FunctionArgumentConverter.map_args(args, scope, '') # this is the scope.function_xxx(...) call return scope.send(self.class.method3x, mapped_args) end result.value rescue Puppet::Pops::Evaluator::Next => jumper begin throw :next, jumper.value rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION raise Puppet::ParseError.new("next() from context where this is illegal", jumper.file, jumper.line) end rescue Puppet::Pops::Evaluator::Return => jumper begin throw :return, jumper rescue Puppet::Parser::Scope::UNCAUGHT_THROW_EXCEPTION raise Puppet::ParseError.new("return() from context where this is illegal", jumper.file, jumper.line) end end end # Create a dispatcher based on func_info type, names = Puppet::Functions.any_signature(*from_to_names(func_info)) last_captures_rest = (type.size_range[1] == Float::INFINITY) # The method '3x_function' here is a dummy as the dispatcher is not used for calling, only for information. the_class.dispatcher.add(Puppet::Pops::Functions::Dispatch.new(type, '3x_function', names, last_captures_rest)) # The function class is returned as the result of the create function method the_class end |