Class: Puppet::Pops::Types::PAnyType

Inherits:
TypedModelObject show all
Defined in:
lib/puppet/pops/types/types.rb

Overview

Base type for all types

Constant Summary collapse

DEFAULT =

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

PAnyType.new

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from TypedModelObject

_pcore_type, create_ptype, register_ptypes

Methods included from PuppetObject

#_pcore_all_contents, #_pcore_contents, #_pcore_init_hash, #_pcore_type

Class Method Details

.create(*args) ⇒ Object



82
83
84
85
# File 'lib/puppet/pops/types/types.rb', line 82

def self.create(*args)
  # NOTE! Important to use self::DEFAULT and not just DEFAULT since the latter yields PAnyType::DEFAULT
  args.empty? ? self::DEFAULT : new(*args)
end

.new_function(type) ⇒ Function

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.

Parameters:

  • type (PAnyType)

    the type to create a new function for

Returns:

  • (Function)

    the created function

Raises:

  • (ArgumentError)


342
343
344
# File 'lib/puppet/pops/types/types.rb', line 342

def self.new_function(type)
  raise ArgumentError.new("Creation of new instance of type '#{type.to_s}' is not supported")
end

.register_ptype(loader, ir) ⇒ Object



78
79
80
# File 'lib/puppet/pops/types/types.rb', line 78

def self.register_ptype(loader, ir)
  @type = Pcore::create_object_type(loader, ir, self, 'Pcore::AnyType', 'Any', EMPTY_HASH)
end

.simple_nameString

Strips the class name from all module prefixes, the leading ‘P’ and the ending ‘Type’. I.e. an instance of PVariantType will return ‘Variant’

Returns:

  • (String)

    the simple name of this type



296
297
298
299
300
301
# File 'lib/puppet/pops/types/types.rb', line 296

def self.simple_name
  @simple_name ||= (
    n = name
    n[n.rindex(DOUBLE_COLON)+3..n.size-5].freeze
  )
end

Instance Method Details

#==(o) ⇒ Object



285
286
287
# File 'lib/puppet/pops/types/types.rb', line 285

def ==(o)
  eql?(o)
end

#accept(visitor, guard) ⇒ Object

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.



90
91
92
# File 'lib/puppet/pops/types/types.rb', line 90

def accept(visitor, guard)
  visitor.visit(self, guard)
end

#assignable?(o, guard = nil) ⇒ Boolean

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.

Parameters:

  • o (Class, PAnyType)

    the class or type to test

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)

    ‘true` when o is assignable to this type



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/puppet/pops/types/types.rb', line 110

def assignable?(o, guard = nil)
  case o
  when Class
    # Safe to call _assignable directly since a Class never is a Unit or Variant
    _assignable?(TypeCalculator.singleton.type(o), guard)
  when PUnitType
    true
  when PTypeAliasType
    # An alias may contain self recursive constructs.
    if o.self_recursion?
      guard ||= RecursionGuard.new
      if guard.add_that(o) == RecursionGuard::SELF_RECURSION_IN_BOTH
        # Recursion detected both in self and other. This means that other is assignable
        # to self. This point would not have been reached otherwise
        true
      else
        assignable?(o.resolved_type, guard)
      end
    else
      assignable?(o.resolved_type, guard)
    end
  when PVariantType
    # Assignable if all contained types are assignable, or if this is exactly Any
    return true if self.class == PAnyType
    # An empty variant may be assignable to NotUndef[T] if T is assignable to empty variant
    return _assignable?(o, guard) if is_a?(PNotUndefType) && o.types.empty?
    !o.types.empty? && o.types.all? { |vt| assignable?(vt, guard) }
  when POptionalType
    # Assignable if undef and contained type is assignable
    assignable?(PUndefType::DEFAULT) && (o.type.nil? || assignable?(o.type))
  when PNotUndefType
    if !(o.type.nil? || o.type.assignable?(PUndefType::DEFAULT))
      assignable?(o.type, guard)
    else
      _assignable?(o, guard)
    end
  else
    _assignable?(o, guard)
  end
end

#callable?(args_type, guard = nil) ⇒ Boolean

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

Parameters:

  • args_type (PAnyType)

    the arguments to test

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)

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



156
157
158
# File 'lib/puppet/pops/types/types.rb', line 156

def callable?(args_type, guard = nil)
  args_type.is_a?(PAnyType) && kind_of_callable? && args_type.callable_args?(self, guard)
end

#callable_args?(callable, guard) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns ‘true` if this instance is considered valid as arguments to the given `callable`

Parameters:

  • callable (PAnyType)

    the callable

  • guard (RecursionGuard)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)

    ‘true` if this instance is considered valid as arguments to the given `callable`



174
175
176
# File 'lib/puppet/pops/types/types.rb', line 174

def callable_args?(callable, guard)
  false
end

#callable_with?(args, block = nil) ⇒ Boolean

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

Parameters:

  • args (Array)

    the arguments to test

  • block (Proc) (defaults to: nil)

    block, or nil if not called with a block

Returns:

  • (Boolean)

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



165
166
167
# File 'lib/puppet/pops/types/types.rb', line 165

def callable_with?(args,  block = nil)
  false
end

#check_self_recursion(originator) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Parameters:

Raises:

  • Puppet::Error if an illegal self recursion is detected



183
184
# File 'lib/puppet/pops/types/types.rb', line 183

def check_self_recursion(originator)
end

#create(*args) ⇒ Object



318
319
320
# File 'lib/puppet/pops/types/types.rb', line 318

def create(*args)
  Loaders.find_loader(nil).load(:function, 'new').call({}, self, *args)
end

#eql?(o) ⇒ Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/puppet/pops/types/types.rb', line 281

def eql?(o)
  self.class == o.class
end

#generalizePAnyType

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

Returns:



191
192
193
194
# File 'lib/puppet/pops/types/types.rb', line 191

def generalize
  # Applicable to all types that have no variables
  self
end

#hashObject



260
261
262
# File 'lib/puppet/pops/types/types.rb', line 260

def hash
  self.class.hash
end

#instance?(o, guard = nil) ⇒ Boolean

Returns true if the given argument o is an instance of this type

Parameters:

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)


268
269
270
# File 'lib/puppet/pops/types/types.rb', line 268

def instance?(o, guard = nil)
  true
end

#iterable?(guard = nil) ⇒ Boolean

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`

Parameters:

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)

    flag to indicate if instances of this type is iterable.



240
241
242
# File 'lib/puppet/pops/types/types.rb', line 240

def iterable?(guard = nil)
  false
end

#iterable_type(guard = nil) ⇒ PIterableType?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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?`.

Examples:

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

Parameters:

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (PIterableType, nil)

    The iterable type that this type is assignable to or ‘nil`



256
257
258
# File 'lib/puppet/pops/types/types.rb', line 256

def iterable_type(guard = nil)
  nil
end

#kind_of_callable?(optional = true, guard = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Responds ‘true` for all callables, variants of callables and unless optional is false, all optional callables.

Parameters:

  • optional (Boolean) (defaults to: true)
  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (Boolean)

    ‘true`if this type is considered callable



230
231
232
# File 'lib/puppet/pops/types/types.rb', line 230

def kind_of_callable?(optional = true, guard = nil)
  false
end

#loaderLoaders::Loader

Returns the loader that loaded this type.

Returns:

  • (Loaders::Loader)

    the loader



198
199
200
# File 'lib/puppet/pops/types/types.rb', line 198

def loader
  Loaders.static_loader
end

#nameString

Returns the name of the type, without parameters

Returns:

  • (String)

    the name of the type



314
315
316
# File 'lib/puppet/pops/types/types.rb', line 314

def name
  simple_name
end

#new_functionFunction

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.

Returns:

  • (Function)

    the created function



329
330
331
# File 'lib/puppet/pops/types/types.rb', line 329

def new_function
  self.class.new_function(self)
end

#normalize(guard = nil) ⇒ PAnyType

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.

Parameters:

  • guard (RecursionGuard) (defaults to: nil)

    guard against recursion. Only used by internal calls

Returns:

  • (PAnyType)

    The iterable type that this type is assignable to or ‘nil`



209
210
211
# File 'lib/puppet/pops/types/types.rb', line 209

def normalize(guard = nil)
  self
end

#really_instance?(o, guard = nil) ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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?.

Returns:

  • (Integer)

    -1 = is not instance, 0 = recursion detected, 1 = is instance



277
278
279
# File 'lib/puppet/pops/types/types.rb', line 277

def really_instance?(o, guard = nil)
  instance?(o, guard) ? 1 : -1
end

#resolve(loader) ⇒ PTypeAliasType

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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}.

Parameters:

Returns:



220
221
222
# File 'lib/puppet/pops/types/types.rb', line 220

def resolve(loader)
  self
end

#roundtrip_with_string?Boolean

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

Returns:

  • (Boolean)

    whether or not the instance has a canonical string representation



350
351
352
# File 'lib/puppet/pops/types/types.rb', line 350

def roundtrip_with_string?
  false
end

#simple_nameObject



289
290
291
# File 'lib/puppet/pops/types/types.rb', line 289

def simple_name
  self.class.simple_name
end

#to_alias_expanded_sObject



303
304
305
# File 'lib/puppet/pops/types/types.rb', line 303

def to_alias_expanded_s
  TypeFormatter.new.alias_expanded_string(self)
end

#to_sObject



307
308
309
# File 'lib/puppet/pops/types/types.rb', line 307

def to_s
  TypeFormatter.string(self)
end