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
2971 def self.flatten_variants(types)
2972   modified = false
2973   types = types.map do |t|
2974     if t.is_a?(PVariantType)
2975       modified = true
2976       t.types
2977     else
2978       t
2979     end
2980   end
2981   types.flatten! if modified
2982   types
2983 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
2899 def self.maybe_create(types)
2900   types = flatten_variants(types).uniq
2901   types.size == 1 ? types[0] : new(types)
2902 end
new(types) click to toggle source

@param types [Array] the variants

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

Protected Instance Methods

_assignable?(o, guard) click to toggle source

@api private

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

@api private

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

@api private

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

@api private

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

@api private

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

@api private

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