class Puppet::Pops::Types::PAnyType

Base type for all types @api public

Constants

DEFAULT

The default instance of this type. Each type in the type system has this constant declared.

Public Class Methods

create(*args) click to toggle source
   # File lib/puppet/pops/types/types.rb
82 def self.create(*args)
83   # NOTE! Important to use self::DEFAULT and not just DEFAULT since the latter yields PAnyType::DEFAULT
84   args.empty? ? self::DEFAULT : new(*args)
85 end
new_function(type) click to toggle source

This default implementation of of a new_function raises an Argument Error. Types for which creating a new instance is supported, should create and return a Puppet Function class by using Puppet:Loaders.create_loaded_function(:new, loader) and return that result.

@param type [PAnyType] the type to create a new function for @return [Function] the created function @raises ArgumentError

    # File lib/puppet/pops/types/types.rb
342 def self.new_function(type)
343   raise ArgumentError.new("Creation of new instance of type '#{type}' is not supported")
344 end
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/types.rb
78 def self.register_ptype(loader, ir)
79   @type = Pcore::create_object_type(loader, ir, self, 'Pcore::AnyType', 'Any', EMPTY_HASH)
80 end
simple_name() click to toggle source

Strips the class name from all module prefixes, the leading 'P' and the ending 'Type'. I.e. an instance of PVariantType will return 'Variant' @return [String] the simple name of this type

    # File lib/puppet/pops/types/types.rb
296 def self.simple_name
297   @simple_name ||= (
298     n = name
299     n[n.rindex(DOUBLE_COLON)+3..n.size-5].freeze
300   )
301 end

Public Instance Methods

==(o) click to toggle source
    # File lib/puppet/pops/types/types.rb
285 def ==(o)
286   eql?(o)
287 end
accept(visitor, guard) click to toggle source

Accept a visitor that will be sent the message `visit`, once with `self` as the argument. The visitor will then visit all types that this type contains.

   # File lib/puppet/pops/types/types.rb
90 def accept(visitor, guard)
91   visitor.visit(self, guard)
92 end
assignable?(o, guard = nil) click to toggle source

Checks if o is a type that is assignable to this type. If o is a `Class` then it is first converted to a type. If o is a Variant, then it is considered assignable when all its types are assignable

The check for assignable must be guarded against self recursion since `self`, the given type o, or both, might be a `TypeAlias`. The initial caller of this method will typically never care about this and hence pass only the first argument, but as soon as a check of a contained type encounters a `TypeAlias`, then a `RecursionGuard` instance is created and passed on in all subsequent calls. The recursion is allowed to continue until self recursion has been detected in both `self` and in the given type. At that point the given type is considered to be assignable to `self` since all checks up to that point were positive.

@param o [Class,PAnyType] the class or type to test @param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] `true` when o is assignable to this type @api public

    # File lib/puppet/pops/types/types.rb
110 def assignable?(o, guard = nil)
111   case o
112   when Class
113     # Safe to call _assignable directly since a Class never is a Unit or Variant
114     _assignable?(TypeCalculator.singleton.type(o), guard)
115   when PUnitType
116     true
117   when PTypeAliasType
118     # An alias may contain self recursive constructs.
119     if o.self_recursion?
120       guard ||= RecursionGuard.new
121       if guard.add_that(o) == RecursionGuard::SELF_RECURSION_IN_BOTH
122         # Recursion detected both in self and other. This means that other is assignable
123         # to self. This point would not have been reached otherwise
124         true
125       else
126         assignable?(o.resolved_type, guard)
127       end
128     else
129       assignable?(o.resolved_type, guard)
130     end
131   when PVariantType
132     # Assignable if all contained types are assignable, or if this is exactly Any
133     return true if self.class == PAnyType
134     # An empty variant may be assignable to NotUndef[T] if T is assignable to empty variant
135     return _assignable?(o, guard) if is_a?(PNotUndefType) && o.types.empty?
136     !o.types.empty? && o.types.all? { |vt| assignable?(vt, guard) }
137   when POptionalType
138     # Assignable if undef and contained type is assignable
139     assignable?(PUndefType::DEFAULT) && (o.type.nil? || assignable?(o.type))
140   when PNotUndefType
141     if !(o.type.nil? || o.type.assignable?(PUndefType::DEFAULT))
142       assignable?(o.type, guard)
143     else
144       _assignable?(o, guard)
145     end
146   else
147     _assignable?(o, guard)
148   end
149 end
callable?(args_type, guard = nil) click to toggle source

Returns `true` if this instance is a callable that accepts the given args_type type

@param args_type [PAnyType] the arguments to test @param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] `true` if this instance is a callable that accepts the given args

    # File lib/puppet/pops/types/types.rb
156 def callable?(args_type, guard = nil)
157   args_type.is_a?(PAnyType) && kind_of_callable? && args_type.callable_args?(self, guard)
158 end
callable_args?(callable, guard) click to toggle source

Returns `true` if this instance is considered valid as arguments to the given `callable` @param callable [PAnyType] the callable @param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] `true` if this instance is considered valid as arguments to the given `callable` @api private

    # File lib/puppet/pops/types/types.rb
174 def callable_args?(callable, guard)
175   false
176 end
callable_with?(args, block = nil) click to toggle source

Returns `true` if this instance is a callable that accepts the given args

@param args [Array] the arguments to test @param block [Proc] block, or nil if not called with a block @return [Boolean] `true` if this instance is a callable that accepts the given args

    # File lib/puppet/pops/types/types.rb
165 def callable_with?(args,  block = nil)
166   false
167 end
check_self_recursion(originator) click to toggle source

Called from the `PTypeAliasType` when it detects self recursion. The default is to do nothing but some self recursive constructs are illegal such as when a `PObjectType` somehow inherits itself @param originator [PTypeAliasType] the starting point for the check @raise Puppet::Error if an illegal self recursion is detected @api private

    # File lib/puppet/pops/types/types.rb
183 def check_self_recursion(originator)
184 end
create(*args) click to toggle source
    # File lib/puppet/pops/types/types.rb
318 def create(*args)
319   Loaders.find_loader(nil).load(:function, 'new').call({}, self, *args)
320 end
eql?(o) click to toggle source
    # File lib/puppet/pops/types/types.rb
281 def eql?(o)
282   self.class == o.class
283 end
generalize() click to toggle source

Generalizes value specific types. Types that are not value specific will return `self` otherwise the generalized type is returned.

@return [PAnyType] The generalized type @api public

    # File lib/puppet/pops/types/types.rb
191 def generalize
192   # Applicable to all types that have no variables
193   self
194 end
hash() click to toggle source
    # File lib/puppet/pops/types/types.rb
260 def hash
261   self.class.hash
262 end
instance?(o, guard = nil) click to toggle source

Returns true if the given argument o is an instance of this type @param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] @api public

    # File lib/puppet/pops/types/types.rb
268 def instance?(o, guard = nil)
269   true
270 end
iterable?(guard = nil) click to toggle source

Returns `true` if an instance of this type is iterable, `false` otherwise The method iterable_type must produce a `PIterableType` instance when this method returns `true`

@param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] flag to indicate if instances of this type is iterable.

    # File lib/puppet/pops/types/types.rb
240 def iterable?(guard = nil)
241   false
242 end
iterable_type(guard = nil) click to toggle source

Returns the `PIterableType` that this type should be assignable to, or `nil` if no such type exists. A type that returns a `PIterableType` must respond `true` to `#iterable?`.

@example

Any Collection[T] is assignable to an Iterable[T]
A String is assignable to an Iterable[String] iterating over the strings characters
An Integer is assignable to an Iterable[Integer] iterating over the 'times' enumerator
A Type[T] is assignable to an Iterable[Type[T]] if T is an Integer or Enum

@param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [PIterableType,nil] The iterable type that this type is assignable to or `nil` @api private

    # File lib/puppet/pops/types/types.rb
256 def iterable_type(guard = nil)
257   nil
258 end
kind_of_callable?(optional = true, guard = nil) click to toggle source

Responds `true` for all callables, variants of callables and unless optional is false, all optional callables. @param optional [Boolean] @param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [Boolean] `true`if this type is considered callable @api private

    # File lib/puppet/pops/types/types.rb
230 def kind_of_callable?(optional = true, guard = nil)
231   false
232 end
loader() click to toggle source

Returns the loader that loaded this type. @return [Loaders::Loader] the loader

    # File lib/puppet/pops/types/types.rb
198 def loader
199   Loaders.static_loader
200 end
name() click to toggle source

Returns the name of the type, without parameters @return [String] the name of the type @api public

    # File lib/puppet/pops/types/types.rb
314 def name
315   simple_name
316 end
new_function() click to toggle source

Create an instance of this type. The default implementation will just dispatch the call to the class method with the same name and pass `self` as the first argument.

@return [Function] the created function @raises ArgumentError

    # File lib/puppet/pops/types/types.rb
329 def new_function
330   self.class.new_function(self)
331 end
normalize(guard = nil) click to toggle source

Normalizes the type. This does not change the characteristics of the type but it will remove duplicates and constructs like NotUndef where T is not assignable from Undef and change Variant where all T are enums into an Enum.

@param guard [RecursionGuard] guard against recursion. Only used by internal calls @return [PAnyType] The iterable type that this type is assignable to or `nil` @api public

    # File lib/puppet/pops/types/types.rb
209 def normalize(guard = nil)
210   self
211 end
really_instance?(o, guard = nil) click to toggle source

An object is considered to really be an instance of a type when something other than a TypeAlias or a Variant responds true to a call to {#instance?}.

@return [Integer] -1 = is not instance, 0 = recursion detected, 1 = is instance @api private

    # File lib/puppet/pops/types/types.rb
277 def really_instance?(o, guard = nil)
278   instance?(o, guard) ? 1 : -1
279 end
resolve(loader) click to toggle source

Called from the TypeParser once it has found a type using the Loader to enable that this type can resolve internal type expressions using a loader. Presently, this method is a no-op for all types except the {{PTypeAliasType}}.

@param loader [Loader::Loader] loader to use @return [PTypeAliasType] the receiver of the call, i.e. `self` @api private

    # File lib/puppet/pops/types/types.rb
220 def resolve(loader)
221   self
222 end
roundtrip_with_string?() click to toggle source

Answers the question if instances of this type can represent themselves as a string that can then be passed to the create method

@return [Boolean] whether or not the instance has a canonical string representation

    # File lib/puppet/pops/types/types.rb
350 def roundtrip_with_string?
351   false
352 end
simple_name() click to toggle source
    # File lib/puppet/pops/types/types.rb
289 def simple_name
290   self.class.simple_name
291 end
to_alias_expanded_s() click to toggle source
    # File lib/puppet/pops/types/types.rb
303 def to_alias_expanded_s
304   TypeFormatter.new.alias_expanded_string(self)
305 end
to_s() click to toggle source
    # File lib/puppet/pops/types/types.rb
307 def to_s
308   TypeFormatter.string(self)
309 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source

@api private

    # File lib/puppet/pops/types/types.rb
362 def _assignable?(o, guard)
363   o.is_a?(PAnyType)
364 end
alter_type_array(types, method, *method_args) { |modified_types| ... } click to toggle source

Applies a transformation by sending the given method and method_args to each of the types of the given array and collecting the results in a new array. If all transformation calls returned the type instance itself (i.e. no transformation took place), then this method will return `self`. If a transformation did occur, then this method will either return the transformed array or in case a block was given, the result of calling a given block with the transformed array.

@param types [Array<PAnyType>] the array of types to transform @param method [Symbol] The method to call on each type @param method_args [Object] The arguments to pass to the method, if any @return [Object] self, the transformed array, or the result of calling a given block with the transformed array @yieldparam altered_types [Array<PAnyType>] the altered type array @api private

    # File lib/puppet/pops/types/types.rb
397 def alter_type_array(types, method, *method_args)
398   modified = false
399   modified_types = types.map do |t|
400     t_mod = t.send(method, *method_args)
401     modified = !t.equal?(t_mod) unless modified
402     t_mod
403   end
404   if modified
405     block_given? ? yield(modified_types) : modified_types
406   else
407     self
408   end
409 end
tuple_entry_at(tuple_t, to, index) click to toggle source

Produces the tuple entry at the given index given a tuple type, its from/to constraints on the last type, and an index. Produces nil if the index is out of bounds from must be less than to, and from may not be less than 0

@api private

    # File lib/puppet/pops/types/types.rb
373 def tuple_entry_at(tuple_t, to, index)
374   regular = (tuple_t.types.size - 1)
375   if index < regular
376     tuple_t.types[index]
377   elsif index < regular + to
378     # in the varargs part
379     tuple_t.types[-1]
380   else
381     nil
382   end
383 end