Class: Puppet::Pops::Types::PTypeAliasType

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

Overview

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

Defined Under Namespace

Classes: AssertOtherTypeAcceptor, AssertSelfRecursionStatusAcceptor

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from PAnyType

#==, #callable?, #callable_with?, create, #create, #generalize, new_function, #normalize, #roundtrip_with_string?, #simple_name, simple_name, #to_alias_expanded_s

Methods inherited from TypedModelObject

_pcore_type, create_ptype, register_ptypes

Methods included from PuppetObject

#_pcore_all_contents, #_pcore_contents, #_pcore_init_hash, #_pcore_type

Constructor Details

#initialize(name, type_expr, resolved_type = nil) ⇒ PTypeAliasType

Returns a new instance of PTypeAliasType.

Parameters:

  • The name of the type

  • The expression that describes the aliased type

  • (defaults to: nil)

    the resolve type (only used for the DEFAULT initialization)

API:

  • public



3136
3137
3138
3139
3140
3141
# File 'lib/puppet/pops/types/types.rb', line 3136

def initialize(name, type_expr, resolved_type = nil)
  @name = name
  @type_expr = type_expr
  @resolved_type = resolved_type
  @self_recursion = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *arguments, &block) ⇒ Object

Delegates to resolved type

API:

  • public



3304
3305
3306
3307
# File 'lib/puppet/pops/types/types.rb', line 3304

def method_missing(name, *arguments, &block)
  super if @resolved_type.equal?(PTypeReferenceType::DEFAULT)
  resolved_type.send(name, *arguments, &block)
end

Instance Attribute Details

#nameObject (readonly)

API:

  • public



3131
3132
3133
# File 'lib/puppet/pops/types/types.rb', line 3131

def name
  @name
end

Class Method Details

.register_ptype(loader, ir) ⇒ Object

API:

  • public



3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
# File 'lib/puppet/pops/types/types.rb', line 3120

def self.register_ptype(loader, ir)
  create_ptype(loader, ir, 'AnyType',
     'name' => PStringType::NON_EMPTY,
     'type_expr' => PAnyType::DEFAULT,
     'resolved_type' => {
       KEY_TYPE => POptionalType.new(PType::DEFAULT),
       KEY_VALUE => nil
     }
  )
end

Instance Method Details

#accept(visitor, guard) ⇒ Object

API:

  • public



3279
3280
3281
3282
3283
3284
# File 'lib/puppet/pops/types/types.rb', line 3279

def accept(visitor, guard)
  guarded_recursion(guard, nil) do |g|
    super(visitor, g)
    @resolved_type.accept(visitor, g) unless @resolved_type.nil?
  end
end

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

Returns:

API:

  • public



3143
3144
3145
3146
3147
3148
3149
3150
# File 'lib/puppet/pops/types/types.rb', line 3143

def assignable?(o, guard = nil)
  if @self_recursion
    guard ||= RecursionGuard.new
    guard.with_this(self) { |state| state == RecursionGuard::SELF_RECURSION_IN_BOTH ? true : super(o, guard) }
  else
    super(o, guard)
  end
end

#callable_args?(callable, guard) ⇒ Boolean

Returns:

API:

  • public



3162
3163
3164
# File 'lib/puppet/pops/types/types.rb', line 3162

def callable_args?(callable, guard)
  guarded_recursion(guard, false) { |g| resolved_type.callable_args?(callable, g) }
end

#check_self_recursion(originator) ⇒ Object

API:

  • public



3166
3167
3168
# File 'lib/puppet/pops/types/types.rb', line 3166

def check_self_recursion(originator)
  resolved_type.check_self_recursion(originator) unless originator.equal?(self)
end

#eql?(o) ⇒ Boolean

Returns:

API:

  • public



3275
3276
3277
# File 'lib/puppet/pops/types/types.rb', line 3275

def eql?(o)
  super && o.name == @name
end

#hashObject

API:

  • public



3186
3187
3188
# File 'lib/puppet/pops/types/types.rb', line 3186

def hash
  @name.hash
end

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

Returns:

API:

  • public



3174
3175
3176
# File 'lib/puppet/pops/types/types.rb', line 3174

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

#iterable?(guard = nil) ⇒ Boolean

Returns:

API:

  • public



3178
3179
3180
# File 'lib/puppet/pops/types/types.rb', line 3178

def iterable?(guard = nil)
  guarded_recursion(guard, false) { |g| resolved_type.iterable?(g) }
end

#iterable_type(guard = nil) ⇒ Object

API:

  • public



3182
3183
3184
# File 'lib/puppet/pops/types/types.rb', line 3182

def iterable_type(guard = nil)
  guarded_recursion(guard, nil) { |g| resolved_type.iterable_type(g) }
end

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

Returns:

API:

  • public



3170
3171
3172
# File 'lib/puppet/pops/types/types.rb', line 3170

def kind_of_callable?(optional=true, guard = nil)
  guarded_recursion(guard, false) { |g| resolved_type.kind_of_callable?(optional, g) }
end

#really_instance?(o, 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.

Returns:

API:

  • private



3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
# File 'lib/puppet/pops/types/types.rb', line 3310

def really_instance?(o, guard = nil)
  if @self_recursion
    guard ||= RecursionGuard.new
    guard.with_that(o) do
      guard.with_this(self) { |state| state == RecursionGuard::SELF_RECURSION_IN_BOTH ? 0 : resolved_type.really_instance?(o, guard) }
    end
  else
    resolved_type.really_instance?(o, guard)
  end
end

#resolve(type_parser, 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. 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.

Parameters:

  • type parser that will interpret the type expression

  • loader to use when loading type aliases

Returns:

  • the receiver of the call, i.e. ‘self`

API:

  • private



3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
# File 'lib/puppet/pops/types/types.rb', line 3236

def resolve(type_parser, loader)
  if @resolved_type.nil?
    # resolved to PTypeReferenceType::DEFAULT during resolve to avoid endless recursion
    @resolved_type = PTypeReferenceType::DEFAULT
    @self_recursion = true # assumed while it being found out below
    begin
      if @type_expr.is_a?(PTypeReferenceType)
        @resolved_type = @type_expr.resolve(type_parser, loader)
      else
        @resolved_type = type_parser.interpret(@type_expr, loader).normalize
      end

      # Find out if this type is recursive. A recursive type has performance implications
      # on several methods and this knowledge is used to avoid that for non-recursive
      # types.
      guard = RecursionGuard.new
      real_type_asserter = AssertOtherTypeAcceptor.new
      accept(real_type_asserter, guard)
      unless real_type_asserter.other_type_detected?
        raise ArgumentError, "Type alias '#{name}' cannot be resolved to a real type"
      end
      @self_recursion = guard.recursive_this?(self)
      # All aliases involved must re-check status since this alias is now resolved
      if @self_recursion
        accept(AssertSelfRecursionStatusAcceptor.new, RecursionGuard.new)
        when_self_recursion_detected
      end
    rescue
      @resolved_type = nil
      raise
    end
  else
    # An alias may appoint an Object type that isn't resolved yet. The default type
    # reference is used to prevent endless recursion and should not be resolved here.
    @resolved_type.resolve(type_parser, loader) unless @resolved_type.equal?(PTypeReferenceType::DEFAULT)
  end
  self
end

#resolved_typePAnyType

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.

Returns:

  • The resolved type of this alias.

Raises:

  • unless the type has been resolved prior to calling this method

API:

  • public



3157
3158
3159
3160
# File 'lib/puppet/pops/types/types.rb', line 3157

def resolved_type
  raise Puppet::Error, "Reference to unresolved type #{@name}" unless @resolved_type
  @resolved_type
end

#respond_to_missing?(name, include_private) ⇒ Boolean

Delegates to resolved type

Returns:

API:

  • public



3299
3300
3301
# File 'lib/puppet/pops/types/types.rb', line 3299

def respond_to_missing?(name, include_private)
  resolved_type.respond_to?(name, include_private)
end

#self_recursion?Boolean

Returns:

API:

  • public



3286
3287
3288
# File 'lib/puppet/pops/types/types.rb', line 3286

def self_recursion?
  @self_recursion
end

#set_self_recursion_statusObject

API:

  • public



3219
3220
3221
3222
3223
3224
3225
3226
# File 'lib/puppet/pops/types/types.rb', line 3219

def set_self_recursion_status
  return if @self_recursion || @resolved_type.is_a?(PTypeReferenceType)
  @self_recursion = true
  guard = RecursionGuard.new
  accept(NoopTypeAcceptor::INSTANCE, guard)
  @self_recursion = guard.recursive_this?(self)
  when_self_recursion_detected if @self_recursion # no difference
end

#to_sString

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

Returns:

  • the expanded form of this alias

API:

  • public



3294
3295
3296
# File 'lib/puppet/pops/types/types.rb', line 3294

def to_s
  TypeFormatter.singleton.alias_expanded_string(self)
end

#type_exprObject

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 ‘nil` to prevent serialization of the type_expr used when first initializing this instance.

Returns:

  • ‘nil` to prevent serialization of the type_expr used when first initializing this instance

API:

  • private



3323
3324
3325
# File 'lib/puppet/pops/types/types.rb', line 3323

def type_expr
  nil
end