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
# 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
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
# 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
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
# File lib/puppet/pops/types/types.rb 284 def ==(o) 285 eql?(o) 286 end
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
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
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
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
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
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
# File lib/puppet/pops/types/types.rb 317 def create(*args) 318 Loaders.find_loader(nil).load(:function, 'new').call({}, self, *args) 319 end
# File lib/puppet/pops/types/types.rb 280 def eql?(o) 281 self.class == o.class 282 end
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
# File lib/puppet/pops/types/types.rb 259 def hash 260 self.class.hash 261 end
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
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
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
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
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
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
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
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
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
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
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
# File lib/puppet/pops/types/types.rb 288 def simple_name 289 self.class.simple_name 290 end
# File lib/puppet/pops/types/types.rb 302 def to_alias_expanded_s 303 TypeFormatter.new.alias_expanded_string(self) 304 end
# File lib/puppet/pops/types/types.rb 306 def to_s 307 TypeFormatter.string(self) 308 end
Protected Instance Methods
@api private
# File lib/puppet/pops/types/types.rb 361 def _assignable?(o, guard) 362 o.is_a?(PAnyType) 363 end
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
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