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
3371 def initialize(name, type_expr, resolved_type = nil)
3372   @name = name
3373   @type_expr = type_expr
3374   @resolved_type = resolved_type
3375   @self_recursion = false
3376 end
register_ptype(loader, ir) click to toggle source
     # File lib/puppet/pops/types/types.rb
3355 def self.register_ptype(loader, ir)
3356   create_ptype(loader, ir, 'AnyType',
3357      'name' => PStringType::NON_EMPTY,
3358      'type_expr' => PAnyType::DEFAULT,
3359      'resolved_type' => {
3360        KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
3361        KEY_VALUE => nil
3362      }
3363   )
3364 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
3515 def accept(visitor, guard)
3516   guarded_recursion(guard, nil) do |g|
3517     super(visitor, g)
3518     @resolved_type.accept(visitor, g) unless @resolved_type.nil?
3519   end
3520 end
assignable?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3378 def assignable?(o, guard = nil)
3379   if @self_recursion
3380     guard ||= RecursionGuard.new
3381     guard.with_this(self) { |state| state == RecursionGuard::SELF_RECURSION_IN_BOTH ? true : super(o, guard) }
3382   else
3383     super(o, guard)
3384   end
3385 end
callable_args?(callable, guard) click to toggle source
     # File lib/puppet/pops/types/types.rb
3397 def callable_args?(callable, guard)
3398   guarded_recursion(guard, false) { |g| resolved_type.callable_args?(callable, g) }
3399 end
check_self_recursion(originator) click to toggle source
     # File lib/puppet/pops/types/types.rb
3401 def check_self_recursion(originator)
3402   resolved_type.check_self_recursion(originator) unless originator.equal?(self)
3403 end
eql?(o) click to toggle source
Calls superclass method Puppet::Pops::Types::PAnyType#eql?
     # File lib/puppet/pops/types/types.rb
3511 def eql?(o)
3512   super && o.name == @name
3513 end
hash() click to toggle source
     # File lib/puppet/pops/types/types.rb
3421 def hash
3422   @name.hash
3423 end
instance?(o, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3409 def instance?(o, guard = nil)
3410   really_instance?(o, guard) == 1
3411 end
iterable?(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3413 def iterable?(guard = nil)
3414   guarded_recursion(guard, false) { |g| resolved_type.iterable?(g) }
3415 end
iterable_type(guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3417 def iterable_type(guard = nil)
3418   guarded_recursion(guard, nil) { |g| resolved_type.iterable_type(g) }
3419 end
kind_of_callable?(optional=true, guard = nil) click to toggle source
     # File lib/puppet/pops/types/types.rb
3405 def kind_of_callable?(optional=true, guard = nil)
3406   guarded_recursion(guard, false) { |g| resolved_type.kind_of_callable?(optional, g) }
3407 end
method_missing(name, *arguments, &block) click to toggle source

Delegates to resolved type

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

@api private

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

Delegates to resolved type

     # File lib/puppet/pops/types/types.rb
3535 def respond_to_missing?(name, include_private)
3536   resolved_type.respond_to?(name, include_private)
3537 end
self_recursion?() click to toggle source
     # File lib/puppet/pops/types/types.rb
3522 def self_recursion?
3523   @self_recursion
3524 end
set_self_recursion_status() click to toggle source
     # File lib/puppet/pops/types/types.rb
3454 def set_self_recursion_status
3455   return if @self_recursion || @resolved_type.is_a?(PTypeReferenceType)
3456   @self_recursion = true
3457   guard = RecursionGuard.new
3458   accept(NoopTypeAcceptor::INSTANCE, guard)
3459   @self_recursion = guard.recursive_this?(self)
3460   when_self_recursion_detected if @self_recursion # no difference
3461 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
3530 def to_s
3531   TypeFormatter.singleton.alias_expanded_string(self)
3532 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
3559 def type_expr
3560   nil
3561 end

Protected Instance Methods

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

Private Instance Methods

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