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
81 def self.create(*args)
82   # NOTE! Important to use self::DEFAULT and not just DEFAULT since the latter yields PAnyType::DEFAULT
83   args.empty? ? self::DEFAULT : new(*args)
84 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
341 def self.new_function(type)
342   raise ArgumentError.new("Creation of new instance of type '#{type}' is not supported")
343 end
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/types.rb
77 def self.register_ptype(loader, ir)
78   @type = Pcore::create_object_type(loader, ir, self, 'Pcore::AnyType', 'Any', EMPTY_HASH)
79 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
295 def self.simple_name
296   @simple_name ||= (
297     n = name
298     n[n.rindex(DOUBLE_COLON)+3..n.size-5].freeze
299   )
300 end

Public Instance Methods

==(o) click to toggle source
    # File lib/puppet/pops/types/types.rb
284 def ==(o)
285   eql?(o)
286 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
89 def accept(visitor, guard)
90   visitor.visit(self, guard)
91 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
109 def assignable?(o, guard = nil)
110   case o
111   when Class
112     # Safe to call _assignable directly since a Class never is a Unit or Variant
113     _assignable?(TypeCalculator.singleton.type(o), guard)
114   when PUnitType
115     true
116   when PTypeAliasType
117     # An alias may contain self recursive constructs.
118     if o.self_recursion?
119       guard ||= RecursionGuard.new
120       if guard.add_that(o) == RecursionGuard::SELF_RECURSION_IN_BOTH
121         # Recursion detected both in self and other. This means that other is assignable
122         # to self. This point would not have been reached otherwise
123         true
124       else
125         assignable?(o.resolved_type, guard)
126       end
127     else
128       assignable?(o.resolved_type, guard)
129     end
130   when PVariantType
131     # Assignable if all contained types are assignable, or if this is exactly Any
132     return true if self.class == PAnyType
133     # An empty variant may be assignable to NotUndef[T] if T is assignable to empty variant
134     return _assignable?(o, guard) if is_a?(PNotUndefType) && o.types.empty?
135     !o.types.empty? && o.types.all? { |vt| assignable?(vt, guard) }
136   when POptionalType
137     # Assignable if undef and contained type is assignable
138     assignable?(PUndefType::DEFAULT) && (o.type.nil? || assignable?(o.type))
139   when PNotUndefType
140     if !(o.type.nil? || o.type.assignable?(PUndefType::DEFAULT))
141       assignable?(o.type, guard)
142     else
143       _assignable?(o, guard)
144     end
145   else
146     _assignable?(o, guard)
147   end
148 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
155 def callable?(args_type, guard = nil)
156   args_type.is_a?(PAnyType) && kind_of_callable? && args_type.callable_args?(self, guard)
157 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
173 def callable_args?(callable, guard)
174   false
175 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
164 def callable_with?(args,  block = nil)
165   false
166 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
182 def check_self_recursion(originator)
183 end
create(*args) click to toggle source
    # File lib/puppet/pops/types/types.rb
317 def create(*args)
318   Loaders.find_loader(nil).load(:function, 'new').call({}, self, *args)
319 end
eql?(o) click to toggle source
    # File lib/puppet/pops/types/types.rb
280 def eql?(o)
281   self.class == o.class
282 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
190 def generalize
191   # Applicable to all types that have no variables
192   self
193 end
hash() click to toggle source
    # File lib/puppet/pops/types/types.rb
259 def hash
260   self.class.hash
261 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
267 def instance?(o, guard = nil)
268   true
269 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
239 def iterable?(guard = nil)
240   false
241 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
255 def iterable_type(guard = nil)
256   nil
257 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
229 def kind_of_callable?(optional = true, guard = nil)
230   false
231 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
197 def loader
198   Loaders.static_loader
199 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
313 def name
314   simple_name
315 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
328 def new_function
329   self.class.new_function(self)
330 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
208 def normalize(guard = nil)
209   self
210 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
276 def really_instance?(o, guard = nil)
277   instance?(o, guard) ? 1 : -1
278 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
219 def resolve(loader)
220   self
221 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
349 def roundtrip_with_string?
350   false
351 end
simple_name() click to toggle source
    # File lib/puppet/pops/types/types.rb
288 def simple_name
289   self.class.simple_name
290 end
to_alias_expanded_s() click to toggle source
    # File lib/puppet/pops/types/types.rb
302 def to_alias_expanded_s
303   TypeFormatter.new.alias_expanded_string(self)
304 end
to_s() click to toggle source
    # File lib/puppet/pops/types/types.rb
306 def to_s
307   TypeFormatter.string(self)
308 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source

@api private

    # File lib/puppet/pops/types/types.rb
361 def _assignable?(o, guard)
362   o.is_a?(PAnyType)
363 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
396 def alter_type_array(types, method, *method_args)
397   modified = false
398   modified_types = types.map do |t|
399     t_mod = t.send(method, *method_args)
400     modified = !t.equal?(t_mod) unless modified
401     t_mod
402   end
403   if modified
404     block_given? ? yield(modified_types) : modified_types
405   else
406     self
407   end
408 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
372 def tuple_entry_at(tuple_t, to, index)
373   regular = (tuple_t.types.size - 1)
374   if index < regular
375     tuple_t.types[index]
376   elsif index < regular + to
377     # in the varargs part
378     tuple_t.types[-1]
379   else
380     nil
381   end
382 end