diff options
Diffstat (limited to 'lib/puppet/pops/functions/dispatcher.rb')
-rw-r--r-- | lib/puppet/pops/functions/dispatcher.rb | 171 |
1 files changed, 2 insertions, 169 deletions
diff --git a/lib/puppet/pops/functions/dispatcher.rb b/lib/puppet/pops/functions/dispatcher.rb index a4f912dc4..f15ad373b 100644 --- a/lib/puppet/pops/functions/dispatcher.rb +++ b/lib/puppet/pops/functions/dispatcher.rb @@ -6,7 +6,7 @@ class Puppet::Pops::Functions::Dispatcher attr_reader :dispatchers -# @api private + # @api private def initialize() @dispatchers = [ ] end @@ -34,7 +34,7 @@ class Puppet::Pops::Functions::Dispatcher if found found.invoke(instance, calling_scope, args) else - raise ArgumentError, "function '#{instance.class.name}' called with mis-matched arguments\n#{diff_string(instance.class.name, actual)}" + raise ArgumentError, "function '#{instance.class.name}' called with mis-matched arguments\n#{Puppet::Pops::Evaluator::CallableMismatchDescriber.diff_string(instance.class.name, actual, @dispatchers)}" end end @@ -67,171 +67,4 @@ class Puppet::Pops::Functions::Dispatcher def signatures @dispatchers end - - private - - # Produces a string with the difference between the given arguments and support signature(s). - # - # @api private - def diff_string(name, args_type) - result = [ ] - if @dispatchers.size < 2 - dispatch = @dispatchers[ 0 ] - params_type = dispatch.type.param_types - block_type = dispatch.type.block_type - params_names = dispatch.param_names - result << "expected:\n #{name}(#{signature_string(dispatch)}) - #{arg_count_string(dispatch.type)}" - else - result << "expected one of:\n" - result << (@dispatchers.map do |d| - params_type = d.type.param_types - " #{name}(#{signature_string(d)}) - #{arg_count_string(d.type)}" - end.join("\n")) - end - result << "\nactual:\n #{name}(#{arg_types_string(args_type)}) - #{arg_count_string(args_type)}" - result.join('') - end - - # Produces a string for the signature(s) - # - # @api private - def signature_string(dispatch) # args_type, param_names - param_types = dispatch.type.param_types - block_type = dispatch.type.block_type - param_names = dispatch.param_names - - from, to = param_types.size_range - if from == 0 && to == 0 - # No parameters function - return '' - end - - required_count = from - # there may be more names than there are types, and count needs to be subtracted from the count - # to make it correct for the last named element - adjust = max(0, param_names.size() -1) - last_range = [max(0, (from - adjust)), (to - adjust)] - - types = - case param_types - when Puppet::Pops::Types::PTupleType - param_types.types - when Puppet::Pops::Types::PArrayType - [ param_types.element_type ] - end - tc = Puppet::Pops::Types::TypeCalculator - - # join type with names (types are always present, names are optional) - # separate entries with comma - # - result = - if param_names.empty? - types.each_with_index.map {|t, index| tc.string(t) + opt_value_indicator(index, required_count, 0) } - else - limit = param_names.size - result = param_names.each_with_index.map do |name, index| - [tc.string(types[index] || types[-1]), name].join(' ') + opt_value_indicator(index, required_count, limit) - end - end.join(', ') - - # Add {from, to} for the last type - # This works for both Array and Tuple since it describes the allowed count of the "last" type element - # for both. It does not show anything when the range is {1,1}. - # - result += range_string(last_range) - - # If there is a block, include it with its own optional count {0,1} - case dispatch.type.block_type - when Puppet::Pops::Types::POptionalType - result << ', ' unless result == '' - result << "#{tc.string(dispatch.type.block_type.optional_type)} #{dispatch.block_name} {0,1}" - when Puppet::Pops::Types::PCallableType - result << ', ' unless result == '' - result << "#{tc.string(dispatch.type.block_type)} #{dispatch.block_name}" - when NilClass - # nothing - end - result - end - - # Why oh why Ruby do you not have a standard Math.max ? - # @api private - def max(a, b) - a >= b ? a : b - end - - # @api private - def opt_value_indicator(index, required_count, limit) - count = index + 1 - (count > required_count && count < limit) ? '?' : '' - end - - # @api private - def arg_count_string(args_type) - if args_type.is_a?(Puppet::Pops::Types::PCallableType) - size_range = args_type.param_types.size_range # regular parameters - adjust_range= - case args_type.block_type - when Puppet::Pops::Types::POptionalType - size_range[1] += 1 - when Puppet::Pops::Types::PCallableType - size_range[0] += 1 - size_range[1] += 1 - when NilClass - # nothing - else - raise ArgumentError, "Internal Error, only nil, Callable, and Optional[Callable] supported by Callable block type" - end - else - size_range = args_type.size_range - end - "arg count #{range_string(size_range, false)}" - end - - # @api private - def arg_types_string(args_type) - types = - case args_type - when Puppet::Pops::Types::PTupleType - last_range = args_type.repeat_last_range - args_type.types - when Puppet::Pops::Types::PArrayType - last_range = args_type.size_range - [ args_type.element_type ] - end - # stringify generalized versions or it will display Integer[10,10] for "10", String['the content'] etc. - # note that type must be copied since generalize is a mutating operation - tc = Puppet::Pops::Types::TypeCalculator - result = types.map { |t| tc.string(tc.generalize!(t.copy)) }.join(', ') - - # Add {from, to} for the last type - # This works for both Array and Tuple since it describes the allowed count of the "last" type element - # for both. It does not show anything when the range is {1,1}. - # - result += range_string(last_range) - result - end - - # Formats a range into a string of the form: `{from, to}` - # - # The following cases are optimized: - # - # * from and to are equal => `{from}` - # * from and to are both and 1 and squelch_one == true => `''` - # * from is 0 and to is 1 => `'?'` - # * to is INFINITY => `{from, }` - # - # @api private - def range_string(size_range, squelch_one = true) - from, to = size_range - if from == to - (squelch_one && from == 1) ? '' : "{#{from}}" - elsif to == Puppet::Pops::Types::INFINITY - "{#{from},}" - elsif from == 0 && to == 1 - '?' - else - "{#{from},#{to}}" - end - end end |