summaryrefslogtreecommitdiff
path: root/lib/puppet/pops/functions/dispatcher.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/pops/functions/dispatcher.rb')
-rw-r--r--lib/puppet/pops/functions/dispatcher.rb171
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