class Puppet::Pops::Types::PVariantType

A flexible type describing an any? of other types @api public

Constants

DEFAULT

Attributes

types[R]

Public Class Methods

flatten_variants(types) click to toggle source
     # File lib/puppet/pops/types/types.rb
2970 def self.flatten_variants(types)
2971   modified = false
2972   types = types.map do |t|
2973     if t.is_a?(PVariantType)
2974       modified = true
2975       t.types
2976     else
2977       t
2978     end
2979   end
2980   types.flatten! if modified
2981   types
2982 end
maybe_create(types) click to toggle source

Checks if the number of unique types in the given array is greater than one, and if so creates a Variant with those types and returns it. If only one unique type is found, that type is instead returned.

@param types [Array<PAnyType>] the variants @return [PAnyType] the resulting type @api public

     # File lib/puppet/pops/types/types.rb
2898 def self.maybe_create(types)
2899   types = flatten_variants(types).uniq
2900   types.size == 1 ? types[0] : new(types)
2901 end
new(types) click to toggle source

@param types [Array] the variants

     # File lib/puppet/pops/types/types.rb
2904 def initialize(types)
2905   @types = types.freeze
2906 end
register_ptype(loader, ir) click to toggle source
     # File lib/puppet/pops/types/types.rb
2885 def self.register_ptype(loader, ir)
2886   create_ptype(loader, ir, 'AnyType', 'types' => PArrayType.new(PTypeType::DEFAULT))
2887 end

Public Instance Methods

accept(visitor, guard) click to toggle source
Calls superclass method Puppet::Pops::Types::PAnyType#accept
     # File lib/puppet/pops/types/types.rb
2908 def accept(visitor, guard)
2909   super
2910   @types.each { |t| t.accept(visitor, guard) }
2911 end
assignable?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3011 def assignable?(o, guard = nil)
3012   # an empty Variant does not match Undef (it is void - not even undef)
3013   if o.is_a?(PUndefType) && types.empty?
3014     return false
3015   end
3016 
3017   return super unless o.is_a?(PVariantType)
3018   # If empty, all Variant types match irrespective of the types they hold (including being empty)
3019   return true if types.empty?
3020   # Since this variant is not empty, an empty Variant cannot match, because it matches nothing
3021   # otherwise all types in o must be assignable to this
3022   !o.types.empty? && o.types.all? { |vt| super(vt, guard) }
3023 end
each() { |t| ... } click to toggle source
     # File lib/puppet/pops/types/types.rb
2913 def each
2914   if block_given?
2915     types.each { |t| yield t }
2916   else
2917     types.to_enum
2918   end
2919 end
eql?(o) click to toggle source
     # File lib/puppet/pops/types/types.rb
3005 def eql?(o)
3006   self.class == o.class && @types.size == o.types.size && (@types - o.types).empty?
3007 end
generalize() click to toggle source
     # File lib/puppet/pops/types/types.rb
2921 def generalize
2922   if self == DEFAULT
2923     self
2924   else
2925     alter_type_array(@types, :generalize) { |altered| PVariantType.maybe_create(altered) }
2926   end
2927 end
hash() click to toggle source
     # File lib/puppet/pops/types/types.rb
2984 def hash
2985   @types.hash
2986 end
instance?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2988 def instance?(o, guard = nil)
2989   # instance of variant if o is instance? of any of variant's types
2990   @types.any? { |type| type.instance?(o, guard) }
2991 end
kind_of_callable?(optional = true, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3001 def kind_of_callable?(optional = true, guard = nil)
3002   @types.all? { |type| type.kind_of_callable?(optional, guard) }
3003 end
normalize(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2929 def normalize(guard = nil)
2930   if self == DEFAULT || @types.empty?
2931     self
2932   else
2933     # Normalize all contained types
2934     modified = false
2935     types = alter_type_array(@types, :normalize, guard)
2936     if types == self
2937       types = @types
2938     else
2939       modified = true
2940     end
2941 
2942     if types.size == 1
2943       types[0]
2944     elsif types.any? { |t| t.is_a?(PUndefType) || t.is_a?(POptionalType) }
2945       # Undef entry present. Use an OptionalType with a normalized Variant without Undefs and Optional wrappers
2946       POptionalType.new(PVariantType.maybe_create(types.reject { |t| t.is_a?(PUndefType) }.map { |t| t.is_a?(POptionalType) ? t.type : t })).normalize
2947     else
2948       # Merge all variants into this one
2949       types = PVariantType.flatten_variants(types)
2950       size_before_merge = types.size
2951 
2952       types = swap_not_undefs(types)
2953       types = merge_enums(types)
2954       types = merge_patterns(types)
2955       types = merge_version_ranges(types)
2956       types = merge_numbers(PIntegerType, types)
2957       types = merge_numbers(PFloatType, types)
2958       types = merge_numbers(PTimespanType, types)
2959       types = merge_numbers(PTimestampType, types)
2960 
2961       if types.size == 1
2962         types[0]
2963       else
2964         modified || types.size != size_before_merge ? PVariantType.maybe_create(types) : self
2965       end
2966     end
2967   end
2968 end
really_instance?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
2993 def really_instance?(o, guard = nil)
2994   @types.reduce(-1) do |memo, type|
2995     ri = type.really_instance?(o, guard)
2996     break ri if ri > 0
2997     ri > memo ? ri : memo
2998   end
2999 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3028 def _assignable?(o, guard)
3029   # A variant is assignable if o is assignable to any of its types
3030   types.any? { |option_t| option_t.assignable?(o, guard) }
3031 end
merge_enums(array) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3048 def merge_enums(array)
3049   # Merge case sensitive enums and strings
3050   if array.size > 1
3051     parts = array.partition {|t| t.is_a?(PEnumType) && !t.values.empty? && !t.case_insensitive? || t.is_a?(PStringType) && !t.value.nil? }
3052     enums = parts[0]
3053     if enums.size > 1
3054       others = parts[1]
3055       others <<  PEnumType.new(enums.map { |enum| enum.is_a?(PStringType) ? enum.value : enum.values }.flatten.uniq)
3056       array = others
3057     end
3058   end
3059 
3060   # Merge case insensitive enums
3061   if array.size > 1
3062     parts = array.partition {|t| t.is_a?(PEnumType) && !t.values.empty? && t.case_insensitive? }
3063     enums = parts[0]
3064     if enums.size > 1
3065       others = parts[1]
3066       values = []
3067       enums.each { |enum| enum.values.each { |value| values << value.downcase }}
3068       values.uniq!
3069       others <<  PEnumType.new(values, true)
3070       array = others
3071     end
3072   end
3073   array
3074 end
merge_numbers(clazz, array) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3091 def merge_numbers(clazz, array)
3092   if array.size > 1
3093     parts = array.partition {|t| t.is_a?(clazz) }
3094     ranges = parts[0]
3095     array = merge_ranges(ranges) + parts[1] if ranges.size > 1
3096   end
3097   array
3098 end
merge_patterns(array) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3077 def merge_patterns(array)
3078   if array.size > 1
3079     parts = array.partition {|t| t.is_a?(PPatternType) }
3080     patterns = parts[0]
3081     if patterns.size > 1
3082       others = parts[1]
3083       others <<  PPatternType.new(patterns.map { |pattern| pattern.patterns }.flatten.uniq)
3084       array = others
3085     end
3086   end
3087   array
3088 end
merge_ranges(ranges) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3110 def merge_ranges(ranges)
3111   result = []
3112   until ranges.empty?
3113     unmerged = []
3114     x = ranges.pop
3115     result << ranges.inject(x) do |memo, y|
3116       merged = memo.merge(y)
3117       if merged.nil?
3118         unmerged << y
3119       else
3120         memo = merged
3121       end
3122       memo
3123     end
3124     ranges = unmerged
3125   end
3126   result
3127 end
merge_version_ranges(array) click to toggle source
     # File lib/puppet/pops/types/types.rb
3100 def merge_version_ranges(array)
3101   if array.size > 1
3102     parts = array.partition {|t| t.is_a?(PSemVerType) }
3103     ranges = parts[0]
3104     array = [PSemVerType.new(ranges.map(&:ranges).flatten)] + parts[1] if ranges.size > 1
3105   end
3106   array
3107 end
swap_not_undefs(array) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3034 def swap_not_undefs(array)
3035   if array.size > 1
3036     parts = array.partition {|t| t.is_a?(PNotUndefType) }
3037     not_undefs = parts[0]
3038     if not_undefs.size > 1
3039       others = parts[1]
3040       others <<  PNotUndefType.new(PVariantType.maybe_create(not_undefs.map { |not_undef| not_undef.type }).normalize)
3041       array = others
3042     end
3043   end
3044   array
3045 end