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 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
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
# 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
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
# File lib/puppet/pops/types/types.rb 285 def ==(o) 286 eql?(o) 287 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 90 def accept(visitor, guard) 91 visitor.visit(self, guard) 92 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 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
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
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
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
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
# File lib/puppet/pops/types/types.rb 318 def create(*args) 319 Loaders.find_loader(nil).load(:function, 'new').call({}, self, *args) 320 end
# File lib/puppet/pops/types/types.rb 281 def eql?(o) 282 self.class == o.class 283 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 191 def generalize 192 # Applicable to all types that have no variables 193 self 194 end
# File lib/puppet/pops/types/types.rb 260 def hash 261 self.class.hash 262 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 268 def instance?(o, guard = nil) 269 true 270 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 240 def iterable?(guard = nil) 241 false 242 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 256 def iterable_type(guard = nil) 257 nil 258 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 230 def kind_of_callable?(optional = true, guard = nil) 231 false 232 end
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
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
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
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
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
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
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
# File lib/puppet/pops/types/types.rb 289 def simple_name 290 self.class.simple_name 291 end
# File lib/puppet/pops/types/types.rb 303 def to_alias_expanded_s 304 TypeFormatter.new.alias_expanded_string(self) 305 end
# File lib/puppet/pops/types/types.rb 307 def to_s 308 TypeFormatter.string(self) 309 end
Protected Instance Methods
@api private
# File lib/puppet/pops/types/types.rb 362 def _assignable?(o, guard) 363 o.is_a?(PAnyType) 364 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 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
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