class Puppet::Pops::Types::PTypeAliasType

Describes a named alias for another Type. The alias is created with a name and an unresolved type expression. The type expression may in turn contain other aliases (including the alias that contains it) which means that an alias might contain self recursion. Whether or not that is the case is computed and remembered when the alias is resolved since guarding against self recursive constructs is relatively expensive.

@api public

Constants

DEFAULT

Attributes

loader[R]
name[R]

Public Class Methods

new(name, type_expr, resolved_type = nil) click to toggle source

@param name [String] The name of the type @param type_expr [Model::PopsObject] The expression that describes the aliased type @param resolved_type [PAnyType] the resolve type (only used for the DEFAULT initialization)

     # File lib/puppet/pops/types/types.rb
3370 def initialize(name, type_expr, resolved_type = nil)
3371   @name = name
3372   @type_expr = type_expr
3373   @resolved_type = resolved_type
3374   @self_recursion = false
3375 end
register_ptype(loader, ir) click to toggle source
     # File lib/puppet/pops/types/types.rb
3354 def self.register_ptype(loader, ir)
3355   create_ptype(loader, ir, 'AnyType',
3356      'name' => PStringType::NON_EMPTY,
3357      'type_expr' => PAnyType::DEFAULT,
3358      'resolved_type' => {
3359        KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
3360        KEY_VALUE => nil
3361      }
3362   )
3363 end

Public Instance Methods

accept(visitor, guard) click to toggle source
Calls superclass method Puppet::Pops::Types::PAnyType#accept
     # File lib/puppet/pops/types/types.rb
3514 def accept(visitor, guard)
3515   guarded_recursion(guard, nil) do |g|
3516     super(visitor, g)
3517     @resolved_type.accept(visitor, g) unless @resolved_type.nil?
3518   end
3519 end
assignable?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3377 def assignable?(o, guard = nil)
3378   if @self_recursion
3379     guard ||= RecursionGuard.new
3380     guard.with_this(self) { |state| state == RecursionGuard::SELF_RECURSION_IN_BOTH ? true : super(o, guard) }
3381   else
3382     super(o, guard)
3383   end
3384 end
callable_args?(callable, guard) click to toggle source
     # File lib/puppet/pops/types/types.rb
3396 def callable_args?(callable, guard)
3397   guarded_recursion(guard, false) { |g| resolved_type.callable_args?(callable, g) }
3398 end
check_self_recursion(originator) click to toggle source
     # File lib/puppet/pops/types/types.rb
3400 def check_self_recursion(originator)
3401   resolved_type.check_self_recursion(originator) unless originator.equal?(self)
3402 end
eql?(o) click to toggle source
Calls superclass method Puppet::Pops::Types::PAnyType#eql?
     # File lib/puppet/pops/types/types.rb
3510 def eql?(o)
3511   super && o.name == @name
3512 end
hash() click to toggle source
     # File lib/puppet/pops/types/types.rb
3420 def hash
3421   @name.hash
3422 end
instance?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3408 def instance?(o, guard = nil)
3409   really_instance?(o, guard) == 1
3410 end
iterable?(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3412 def iterable?(guard = nil)
3413   guarded_recursion(guard, false) { |g| resolved_type.iterable?(g) }
3414 end
iterable_type(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3416 def iterable_type(guard = nil)
3417   guarded_recursion(guard, nil) { |g| resolved_type.iterable_type(g) }
3418 end
kind_of_callable?(optional=true, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3404 def kind_of_callable?(optional=true, guard = nil)
3405   guarded_recursion(guard, false) { |g| resolved_type.kind_of_callable?(optional, g) }
3406 end
method_missing(name, *arguments, &block) click to toggle source

Delegates to resolved type

Calls superclass method
     # File lib/puppet/pops/types/types.rb
3539 def method_missing(name, *arguments, &block)
3540   super if @resolved_type.equal?(PTypeReferenceType::DEFAULT)
3541   resolved_type.send(name, *arguments, &block)
3542 end
really_instance?(o, guard = nil) click to toggle source

@api private

     # File lib/puppet/pops/types/types.rb
3545 def really_instance?(o, guard = nil)
3546   if @self_recursion
3547     guard ||= RecursionGuard.new
3548     guard.with_that(o) do
3549       guard.with_this(self) { |state| state == RecursionGuard::SELF_RECURSION_IN_BOTH ? 0 : resolved_type.really_instance?(o, guard) }
3550     end
3551   else
3552     resolved_type.really_instance?(o, guard)
3553   end
3554 end
resolve(loader) click to toggle source

Called from the TypeParser once it has found a type using the Loader. The TypeParser will interpret the contained expression and the resolved type is remembered. This method also checks and remembers if the resolve type contains self recursion.

@param type_parser [TypeParser] type parser that will interpret the type expression @param loader [Loader::Loader] loader to use when loading type aliases @return [PTypeAliasType] the receiver of the call, i.e. `self` @api private

     # File lib/puppet/pops/types/types.rb
3470 def resolve(loader)
3471   @loader = loader
3472   if @resolved_type.nil?
3473     # resolved to PTypeReferenceType::DEFAULT during resolve to avoid endless recursion
3474     @resolved_type = PTypeReferenceType::DEFAULT
3475     @self_recursion = true # assumed while it being found out below
3476     begin
3477       if @type_expr.is_a?(PTypeReferenceType)
3478         @resolved_type = @type_expr.resolve(loader)
3479       else
3480         @resolved_type = TypeParser.singleton.interpret(@type_expr, loader).normalize
3481       end
3482 
3483       # Find out if this type is recursive. A recursive type has performance implications
3484       # on several methods and this knowledge is used to avoid that for non-recursive
3485       # types.
3486       guard = RecursionGuard.new
3487       real_type_asserter = AssertOtherTypeAcceptor.new
3488       accept(real_type_asserter, guard)
3489       unless real_type_asserter.other_type_detected?
3490         raise ArgumentError, "Type alias '#{name}' cannot be resolved to a real type"
3491       end
3492       @self_recursion = guard.recursive_this?(self)
3493       # All aliases involved must re-check status since this alias is now resolved
3494       if @self_recursion
3495         accept(AssertSelfRecursionStatusAcceptor.new, RecursionGuard.new)
3496         when_self_recursion_detected
3497       end
3498     rescue
3499       @resolved_type = nil
3500       raise
3501     end
3502   else
3503     # An alias may appoint an Object type that isn't resolved yet. The default type
3504     # reference is used to prevent endless recursion and should not be resolved here.
3505     @resolved_type.resolve(loader) unless @resolved_type.equal?(PTypeReferenceType::DEFAULT)
3506   end
3507   self
3508 end
resolved_type() click to toggle source

Returns the resolved type. The type must have been resolved by a call prior to calls to this method or an error will be raised.

@return [PAnyType] The resolved type of this alias. @raise [Puppet::Error] unless the type has been resolved prior to calling this method

     # File lib/puppet/pops/types/types.rb
3391 def resolved_type
3392   raise Puppet::Error, "Reference to unresolved type #{@name}" unless @resolved_type
3393   @resolved_type
3394 end
respond_to_missing?(name, include_private) click to toggle source

Delegates to resolved type

     # File lib/puppet/pops/types/types.rb
3534 def respond_to_missing?(name, include_private)
3535   resolved_type.respond_to?(name, include_private)
3536 end
self_recursion?() click to toggle source
     # File lib/puppet/pops/types/types.rb
3521 def self_recursion?
3522   @self_recursion
3523 end
set_self_recursion_status() click to toggle source
     # File lib/puppet/pops/types/types.rb
3453 def set_self_recursion_status
3454   return if @self_recursion || @resolved_type.is_a?(PTypeReferenceType)
3455   @self_recursion = true
3456   guard = RecursionGuard.new
3457   accept(NoopTypeAcceptor::INSTANCE, guard)
3458   @self_recursion = guard.recursive_this?(self)
3459   when_self_recursion_detected if @self_recursion # no difference
3460 end
to_s() click to toggle source

Returns the expanded string the form of the alias, e.g. <alias name> = <resolved type>

@return [String] the expanded form of this alias @api public

     # File lib/puppet/pops/types/types.rb
3529 def to_s
3530   TypeFormatter.singleton.alias_expanded_string(self)
3531 end
type_expr() click to toggle source

@return `nil` to prevent serialization of the type_expr used when first initializing this instance @api private

     # File lib/puppet/pops/types/types.rb
3558 def type_expr
3559   nil
3560 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source
     # File lib/puppet/pops/types/types.rb
3564 def _assignable?(o, guard)
3565   resolved_type.assignable?(o, guard)
3566 end
new_function() click to toggle source
     # File lib/puppet/pops/types/types.rb
3568 def new_function
3569   resolved_type.new_function
3570 end

Private Instance Methods

guarded_recursion(guard, dflt) { |guard| ... } click to toggle source
     # File lib/puppet/pops/types/types.rb
3574 def guarded_recursion(guard, dflt)
3575   if @self_recursion
3576     guard ||= RecursionGuard.new
3577     guard.with_this(self) { |state| (state & RecursionGuard::SELF_RECURSION_IN_THIS) == 0 ? yield(guard) : dflt }
3578   else
3579     yield(guard)
3580   end
3581 end
when_self_recursion_detected() click to toggle source
     # File lib/puppet/pops/types/types.rb
3583 def when_self_recursion_detected
3584   if @resolved_type.is_a?(PVariantType)
3585     # Drop variants that are not real types
3586     resolved_types = @resolved_type.types
3587     real_types = resolved_types.select do |type|
3588       next false if type == self
3589       real_type_asserter = AssertOtherTypeAcceptor.new
3590       type.accept(real_type_asserter, RecursionGuard.new)
3591       real_type_asserter.other_type_detected?
3592     end
3593     if real_types.size != resolved_types.size
3594       if real_types.size == 1
3595         @resolved_type = real_types[0]
3596       else
3597         @resolved_type = PVariantType.maybe_create(real_types)
3598       end
3599       # Drop self recursion status in case it's not self recursive anymore
3600       guard = RecursionGuard.new
3601       accept(NoopTypeAcceptor::INSTANCE, guard)
3602       @self_recursion = guard.recursive_this?(self)
3603     end
3604   end
3605   @resolved_type.check_self_recursion(self) if @self_recursion
3606 end