class Puppet::Pops::Types::TypeCalculator
The TypeCalculator
can answer questions about puppet types.
The Puppet
type system is primarily based on sub-classing. When asking the type calculator to infer types from Ruby in general, it may not provide the wanted answer; it does not for instance take module inclusions and extensions into account. In general the type system should be unsurprising for anyone being exposed to the notion of type. The type `Data` may require a bit more explanation; this is an abstract type that includes all scalar types, as well as Array with an element type compatible with Data, and Hash with key compatible with scalar and elements compatible with Data. Expressed differently; Data is what you typically express using JSON (with the exception that the Puppet
type system also includes Pattern (regular expression) as a scalar.
Inference
The `infer(o)` method infers a Puppet
type for scalar Ruby objects, and for Arrays and Hashes. The inference result is instance specific for single typed collections and allows answering questions about its embedded type. It does not however preserve multiple types in a collection, and can thus not answer questions like `[1,a].infer() =~ Array[Integer, String]` since the inference computes the common type Scalar when combining Integer and String.
The `infer_generic(o)` method infers a generic Puppet
type for scalar Ruby object, Arrays and Hashes. This inference result does not contain instance specific information; e.g. Array where the integer range is the generic default. Just `infer` it also combines types into a common type.
The `infer_set(o)` method works like `infer` but preserves all type information. It does not do any reduction into common types or ranges. This method of inference is best suited for answering questions about an object being an instance of a type. It correctly answers: `[1,a].infer_set() =~ Array[Integer, String]`
The `generalize!(t)` method modifies an instance specific inference result to a generic. The method mutates the given argument. Basically, this removes string instances from String, and range from Integer and Float.
Assignability
The `assignable?(t1, t2)` method answers if t2 conforms to t1. The type t2 may be an instance, in which case its type is inferred, or a type.
Instance?
The `instance?(t, o)` method answers if the given object (instance) is an instance that is assignable to the given type.
String
Creates a string representation of a type.
Creation of Type
instances
Instance of the classes in the {Types type model} are used to denote a specific type. It is most convenient to use the {TypeFactory} when creating instances.
@note
In general, new instances of the wanted type should be created as they are assigned to models using containment, and a contained object can only be in one container at a time. Also, the type system may include more details in each type instance, such as if it may be nil, be empty, contain a certain count etc. Or put differently, the puppet types are not singletons.
All types support `copy` which should be used when assigning a type where it is unknown if it is bound or not to a parent type. A check can be made with `t.eContainer().nil?`
Equality and Hash
Type
instances are equal in terms of Ruby eql? and `==` if they describe the same type, but they are not `equal?` if they are not the same type instance. Two types that describe the same type have identical hash - this makes them usable as hash keys.
Types
and Subclasses
In general, the type calculator should be used to answer questions if a type is a subtype of another (using {#assignable?}, or {#instance?} if the question is if a given object is an instance of a given type (or is a subtype thereof). Many of the types also have a Ruby subtype relationship; e.g. PHashType
and PArrayType
are both subtypes of PCollectionType
, and PIntegerType
, PFloatType
, PStringType
,… are subtypes of PScalarType
. Even if it is possible to answer certain questions about type by looking at the Ruby class of the types this is considered an implementation detail, and such checks should in general be performed by the type_calculator which implements the type system semantics.
The PRuntimeType
The PRuntimeType
corresponds to a type in the runtime system (currently only supported runtime is 'ruby'). The type has a runtime_type_name that corresponds to a Ruby Class
name. A Runtime type can be used to describe any ruby class except for the puppet types that are specialized (i.e. PRuntimeType
should not be used for Integer, String, etc. since there are specialized types for those). When the type calculator deals with PRuntimeTypes and checks for assignability, it determines the “common ancestor class” of two classes. This check is made based on the superclasses of the two classes being compared. In order to perform this, the classes must be present (i.e. they are resolved from the string form in the PRuntimeType
to a loaded, instantiated Ruby Class
). In general this is not a problem, since the question to produce the common super type for two objects means that the classes must be present or there would have been no instances present in the first place. If however the classes are not present, the type calculator will fall back and state that the two types at least have Any in common.
@see TypeFactory
for how to create instances of types @see TypeParser
how to construct a type instance from a String @see Types
for details about the type model
Using the Type
Calculator
The type calculator can be directly used via its class methods. If doing time critical work and doing many calls to the type calculator, it is more performant to create an instance and invoke the corresponding instance methods. Note that inference is an expensive operation, rather than inferring the same thing several times, it is in general better to infer once and then copy the result if mutation to a more generic form is required.
@api public
Public Class Methods
@api public
# File lib/puppet/pops/types/type_calculator.rb 107 def self.assignable?(t1, t2) 108 singleton.assignable?(t1,t2) 109 end
Answers, does the given callable accept the arguments given in args (an array or a tuple) @param callable [PCallableType] - the callable @param args [PArrayType, PTupleType] args optionally including a lambda callable at the end @return [Boolean] true if the callable accepts the arguments
@api public
# File lib/puppet/pops/types/type_calculator.rb 117 def self.callable?(callable, args) 118 singleton.callable?(callable, args) 119 end
@api public
# File lib/puppet/pops/types/type_calculator.rb 151 def self.generalize(o) 152 singleton.generalize(o) 153 end
@api public
# File lib/puppet/pops/types/type_calculator.rb 122 def self.infer(o) 123 singleton.infer(o) 124 end
Infers a type if given object may have callable members, else returns nil. Caller must check for nil or if returned type supports members. This is a much cheaper call than doing a call to the general infer(o) method.
@api private
# File lib/puppet/pops/types/type_calculator.rb 131 def self.infer_callable_methods_t(o) 132 # If being a value that cannot have Pcore based methods callable from Puppet Language 133 if (o.is_a?(String) || 134 o.is_a?(Numeric) || 135 o.is_a?(TrueClass) || 136 o.is_a?(FalseClass) || 137 o.is_a?(Regexp) || 138 o.instance_of?(Array) || 139 o.instance_of?(Hash) || 140 Types::PUndefType::DEFAULT.instance?(o) 141 ) 142 return nil 143 end 144 # For other objects (e.g. PObjectType instances, and runtime types) full inference needed, since that will 145 # cover looking into the runtime type registry. 146 # 147 infer(o) 148 end
@api public
# File lib/puppet/pops/types/type_calculator.rb 156 def self.infer_set(o) 157 singleton.infer_set(o) 158 end
Answers 'is o an instance of type t' @api public
# File lib/puppet/pops/types/type_calculator.rb 292 def self.instance?(t, o) 293 singleton.instance?(t,o) 294 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 760 def self.is_kind_of_callable?(t, optional = true) 761 t.is_a?(PAnyType) && t.kind_of_callable?(optional) 762 end
@api public
# File lib/puppet/pops/types/type_calculator.rb 161 def self.iterable(t) 162 singleton.iterable(t) 163 end
@api public
# File lib/puppet/pops/types/type_calculator.rb 167 def initialize 168 @infer_visitor = Visitor.new(nil, 'infer',0,0) 169 @extract_visitor = Visitor.new(nil, 'extract',0,0) 170 end
Public Instance Methods
Answers 'can an instance of type t2 be assigned to a variable of type t'. Does not accept nil/undef unless the type accepts it.
@api public
# File lib/puppet/pops/types/type_calculator.rb 177 def assignable?(t, t2) 178 if t.is_a?(Module) 179 t = type(t) 180 end 181 t.is_a?(PAnyType) ? t.assignable?(t2) : false 182 end
Answers, does the given callable accept the arguments given in args (an array or a tuple)
# File lib/puppet/pops/types/type_calculator.rb 192 def callable?(callable, args) 193 callable.is_a?(PAnyType) && callable.callable?(args) 194 end
Answers, 'What is the common type of t1 and t2?'
TODO: The current implementation should be optimized for performance
@api public
# File lib/puppet/pops/types/type_calculator.rb 326 def common_type(t1, t2) 327 raise ArgumentError, 'two types expected' unless (is_ptype?(t1) || is_pnil?(t1)) && (is_ptype?(t2) || is_pnil?(t2)) 328 329 # TODO: This is not right since Scalar U Undef is Any 330 # if either is nil, the common type is the other 331 if is_pnil?(t1) 332 return t2 333 elsif is_pnil?(t2) 334 return t1 335 end 336 337 # If either side is Unit, it is the other type 338 if t1.is_a?(PUnitType) 339 return t2 340 elsif t2.is_a?(PUnitType) 341 return t1 342 end 343 344 # Simple case, one is assignable to the other 345 if assignable?(t1, t2) 346 return t1 347 elsif assignable?(t2, t1) 348 return t2 349 end 350 351 # when both are arrays, return an array with common element type 352 if t1.is_a?(PArrayType) && t2.is_a?(PArrayType) 353 return PArrayType.new(common_type(t1.element_type, t2.element_type)) 354 end 355 356 # when both are hashes, return a hash with common key- and element type 357 if t1.is_a?(PHashType) && t2.is_a?(PHashType) 358 key_type = common_type(t1.key_type, t2.key_type) 359 value_type = common_type(t1.value_type, t2.value_type) 360 return PHashType.new(key_type, value_type) 361 end 362 363 # when both are host-classes, reduce to PHostClass[] (since one was not assignable to the other) 364 if t1.is_a?(PClassType) && t2.is_a?(PClassType) 365 return PClassType::DEFAULT 366 end 367 368 # when both are resources, reduce to Resource[T] or Resource[] (since one was not assignable to the other) 369 if t1.is_a?(PResourceType) && t2.is_a?(PResourceType) 370 # only Resource[] unless the type name is the same 371 return t1.type_name == t2.type_name ? PResourceType.new(t1.type_name, nil) : PResourceType::DEFAULT 372 end 373 374 # Integers have range, expand the range to the common range 375 if t1.is_a?(PIntegerType) && t2.is_a?(PIntegerType) 376 return PIntegerType.new([t1.numeric_from, t2.numeric_from].min, [t1.numeric_to, t2.numeric_to].max) 377 end 378 379 # Floats have range, expand the range to the common range 380 if t1.is_a?(PFloatType) && t2.is_a?(PFloatType) 381 return PFloatType.new([t1.numeric_from, t2.numeric_from].min, [t1.numeric_to, t2.numeric_to].max) 382 end 383 384 if t1.is_a?(PStringType) && (t2.is_a?(PStringType) || t2.is_a?(PEnumType)) 385 if(t2.is_a?(PEnumType)) 386 return t1.value.nil? ? PEnumType::DEFAULT : PEnumType.new(t2.values | [t1.value]) 387 end 388 389 if t1.size_type.nil? || t2.size_type.nil? 390 return t1.value.nil? || t2.value.nil? ? PStringType::DEFAULT : PEnumType.new([t1.value, t2.value]) 391 end 392 393 return PStringType.new(common_type(t1.size_type, t2.size_type)) 394 end 395 396 if t1.is_a?(PPatternType) && t2.is_a?(PPatternType) 397 return PPatternType.new(t1.patterns | t2.patterns) 398 end 399 400 if t1.is_a?(PEnumType) && (t2.is_a?(PStringType) || t2.is_a?(PEnumType)) 401 # The common type is one that complies with either set 402 if t2.is_a?(PEnumType) 403 return PEnumType.new(t1.values | t2.values) 404 end 405 406 return t2.value.nil? ? PEnumType::DEFAULT : PEnumType.new(t1.values | [t2.value]) 407 end 408 409 if t1.is_a?(PVariantType) && t2.is_a?(PVariantType) 410 # The common type is one that complies with either set 411 return PVariantType.maybe_create(t1.types | t2.types) 412 end 413 414 if t1.is_a?(PRegexpType) && t2.is_a?(PRegexpType) 415 # if they were identical, the general rule would return a parameterized regexp 416 # since they were not, the result is a generic regexp type 417 return PRegexpType::DEFAULT 418 end 419 420 if t1.is_a?(PCallableType) && t2.is_a?(PCallableType) 421 # They do not have the same signature, and one is not assignable to the other, 422 # what remains is the most general form of Callable 423 return PCallableType::DEFAULT 424 end 425 426 # Common abstract types, from most specific to most general 427 if common_numeric?(t1, t2) 428 return PNumericType::DEFAULT 429 end 430 431 if common_scalar_data?(t1, t2) 432 return PScalarDataType::DEFAULT 433 end 434 435 if common_scalar?(t1, t2) 436 return PScalarType::DEFAULT 437 end 438 439 if common_data?(t1,t2) 440 return TypeFactory.data 441 end 442 443 # Meta types Type[Integer] + Type[String] => Type[Data] 444 if t1.is_a?(PTypeType) && t2.is_a?(PTypeType) 445 return PTypeType.new(common_type(t1.type, t2.type)) 446 end 447 448 if common_rich_data?(t1,t2) 449 return TypeFactory.rich_data 450 end 451 452 # If both are Runtime types 453 if t1.is_a?(PRuntimeType) && t2.is_a?(PRuntimeType) 454 if t1.runtime == t2.runtime && t1.runtime_type_name == t2.runtime_type_name 455 return t1 456 end 457 # finding the common super class requires that names are resolved to class 458 # NOTE: This only supports runtime type of :ruby 459 c1 = ClassLoader.provide_from_type(t1) 460 c2 = ClassLoader.provide_from_type(t2) 461 if c1 && c2 462 c2_superclasses = superclasses(c2) 463 superclasses(c1).each do|c1_super| 464 c2_superclasses.each do |c2_super| 465 if c1_super == c2_super 466 return PRuntimeType.new(:ruby, c1_super.name) 467 end 468 end 469 end 470 end 471 end 472 473 # They better both be Any type, or the wrong thing was asked and nil is returned 474 t1.is_a?(PAnyType) && t2.is_a?(PAnyType) ? PAnyType::DEFAULT : nil 475 end
Answers if the two given types describe the same type
# File lib/puppet/pops/types/type_calculator.rb 197 def equals(left, right) 198 return false unless left.is_a?(PAnyType) && right.is_a?(PAnyType) 199 # Types compare per class only - an extra test must be made if the are mutually assignable 200 # to find all types that represent the same type of instance 201 # 202 left == right || (assignable?(right, left) && assignable?(left, right)) 203 end
Generalizes value specific types. The generalized type is returned. @api public
# File lib/puppet/pops/types/type_calculator.rb 244 def generalize(o) 245 o.is_a?(PAnyType) ? o.generalize : o 246 end
Answers 'what is the single common Puppet
Type
describing o', or if o is an Array or Hash, what is the single common type of the elements (or keys and elements for a Hash). @api public
# File lib/puppet/pops/types/type_calculator.rb 252 def infer(o) 253 # Optimize the most common cases into direct calls. 254 # Explicit if/elsif/else is faster than case 255 if o.is_a?(String) 256 infer_String(o) 257 elsif o.is_a?(Integer) # need subclasses for Ruby < 2.4 258 infer_Integer(o) 259 elsif o.is_a?(Array) 260 infer_Array(o) 261 elsif o.is_a?(Hash) 262 infer_Hash(o) 263 elsif o.is_a?(Evaluator::PuppetProc) 264 infer_PuppetProc(o) 265 else 266 @infer_visitor.visit_this_0(self, o) 267 end 268 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 660 def infer_Array(o) 661 if o.instance_of?(Array) 662 if o.empty? 663 PArrayType::EMPTY 664 else 665 PArrayType.new(infer_and_reduce_type(o), size_as_type(o)) 666 end 667 else 668 infer_Object(o) 669 end 670 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 673 def infer_Binary(o) 674 PBinaryType::DEFAULT 675 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 509 def infer_Closure(o) 510 o.type 511 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 639 def infer_FalseClass(o) 640 PBooleanType::FALSE 641 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 561 def infer_Float(o) 562 PFloatType.new(o, o) 563 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 519 def infer_Function(o) 520 o.class.dispatcher.to_type 521 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 688 def infer_Hash(o) 689 if o.instance_of?(Hash) 690 if o.empty? 691 PHashType::EMPTY 692 else 693 ktype = infer_and_reduce_type(o.keys) 694 etype = infer_and_reduce_type(o.values) 695 PHashType.new(ktype, etype, size_as_type(o)) 696 end 697 else 698 infer_Object(o) 699 end 700 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 566 def infer_Integer(o) 567 PIntegerType.new(o, o) 568 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 514 def infer_Iterator(o) 515 PIteratorType.new(o.element_type) 516 end
The type of all modules is PTypeType
@api private
# File lib/puppet/pops/types/type_calculator.rb 504 def infer_Module(o) 505 PTypeType::new(PRuntimeType.new(:ruby, o.name)) 506 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 576 def infer_NilClass(o) 577 PUndefType::DEFAULT 578 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 524 def infer_Object(o) 525 if o.is_a?(PuppetObject) 526 o._pcore_type 527 else 528 name = o.class.name 529 return PRuntimeType.new(:ruby, nil) if name.nil? # anonymous class that doesn't implement PuppetObject is impossible to infer 530 ir = Loaders.implementation_registry 531 type = ir.nil? ? nil : ir.type_for_module(name) 532 return PRuntimeType.new(:ruby, name) if type.nil? 533 if type.is_a?(PObjectType) && type.parameterized? 534 type = PObjectTypeExtension.create_from_instance(type, o) 535 end 536 type 537 end 538 end
The type of all types is PTypeType
@api private
# File lib/puppet/pops/types/type_calculator.rb 543 def infer_PAnyType(o) 544 PTypeType.new(o) 545 end
The type of all types is PTypeType
This is the metatype short circuit. @api private
# File lib/puppet/pops/types/type_calculator.rb 551 def infer_PTypeType(o) 552 PTypeType.new(o) 553 end
@api private @param o [Proc]
# File lib/puppet/pops/types/type_calculator.rb 582 def infer_Proc(o) 583 min = 0 584 max = 0 585 mapped_types = o.parameters.map do |p| 586 case p[0] 587 when :rest 588 max = :default 589 break PAnyType::DEFAULT 590 when :req 591 min += 1 592 end 593 max += 1 594 PAnyType::DEFAULT 595 end 596 param_types = Types::PTupleType.new(mapped_types, Types::PIntegerType.new(min, max)) 597 Types::PCallableType.new(param_types) 598 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 601 def infer_PuppetProc(o) 602 infer_Closure(o.closure) 603 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 571 def infer_Regexp(o) 572 PRegexpType.new(o) 573 end
@api private A Puppet::Parser::Resource
, or Puppet::Resource
# File lib/puppet/pops/types/type_calculator.rb 651 def infer_Resource(o) 652 # Only Puppet::Resource can have a title that is a symbol :undef, a PResource cannot. 653 # A mapping must be made to empty string. A nil value will result in an error later 654 title = o.title 655 title = '' if :undef == title 656 PTypeType.new(PResourceType.new(o.type.to_s, title)) 657 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 619 def infer_Sensitive(o) 620 PSensitiveType.new(infer(o.unwrap)) 621 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 556 def infer_String(o) 557 PStringType.new(o) 558 end
Inference of :default as PDefaultType
, and all other are Ruby @api private
# File lib/puppet/pops/types/type_calculator.rb 607 def infer_Symbol(o) 608 case o 609 when :default 610 PDefaultType::DEFAULT 611 when :undef 612 PUndefType::DEFAULT 613 else 614 infer_Object(o) 615 end 616 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 624 def infer_Timespan(o) 625 PTimespanType.new(o, o) 626 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 629 def infer_Timestamp(o) 630 PTimestampType.new(o, o) 631 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 634 def infer_TrueClass(o) 635 PBooleanType::TRUE 636 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 644 def infer_URI(o) 645 PURIType.new(o) 646 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 678 def infer_Version(o) 679 PSemVerType::DEFAULT 680 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 683 def infer_VersionRange(o) 684 PSemVerRangeType::DEFAULT 685 end
Reduce an enumerable of objects to a single common type @api public
# File lib/puppet/pops/types/type_calculator.rb 497 def infer_and_reduce_type(enumerable) 498 reduce_type(enumerable.map {|o| infer(o) }) 499 end
# File lib/puppet/pops/types/type_calculator.rb 270 def infer_generic(o) 271 generalize(infer(o)) 272 end
Answers 'what is the set of Puppet
Types
of o' @api public
# File lib/puppet/pops/types/type_calculator.rb 277 def infer_set(o) 278 if o.instance_of?(Array) 279 infer_set_Array(o) 280 elsif o.instance_of?(Hash) 281 infer_set_Hash(o) 282 elsif o.instance_of?(SemanticPuppet::Version) 283 infer_set_Version(o) 284 else 285 infer(o) 286 end 287 end
# File lib/puppet/pops/types/type_calculator.rb 712 def infer_set_Array(o) 713 if o.empty? 714 PArrayType::EMPTY 715 else 716 PTupleType.new(o.map {|x| infer_set(x) }) 717 end 718 end
# File lib/puppet/pops/types/type_calculator.rb 720 def infer_set_Hash(o) 721 if o.empty? 722 PHashType::EMPTY 723 elsif o.keys.all? {|k| PStringType::NON_EMPTY.instance?(k) } 724 PStructType.new(o.each_pair.map { |k,v| PStructElement.new(PStringType.new(k), infer_set(v)) }) 725 else 726 ktype = PVariantType.maybe_create(o.keys.map {|k| infer_set(k) }) 727 etype = PVariantType.maybe_create(o.values.map {|e| infer_set(e) }) 728 PHashType.new(unwrap_single_variant(ktype), unwrap_single_variant(etype), size_as_type(o)) 729 end 730 end
Common case for everything that intrinsically only has a single type
# File lib/puppet/pops/types/type_calculator.rb 708 def infer_set_Object(o) 709 infer(o) 710 end
@api private
# File lib/puppet/pops/types/type_calculator.rb 733 def infer_set_Version(o) 734 PSemVerType.new([SemanticPuppet::VersionRange.new(o, o)]) 735 end
Answers 'is o an instance of type t' @api public
# File lib/puppet/pops/types/type_calculator.rb 299 def instance?(t, o) 300 if t.is_a?(Module) 301 t = type(t) 302 end 303 t.is_a?(PAnyType) ? t.instance?(o) : false 304 end
Answers if t represents the puppet type PUndefType
@api public
# File lib/puppet/pops/types/type_calculator.rb 316 def is_pnil?(t) 317 t.nil? || t.is_a?(PUndefType) 318 end
Answers if t is a puppet type @api public
# File lib/puppet/pops/types/type_calculator.rb 309 def is_ptype?(t) 310 t.is_a?(PAnyType) 311 end
Returns an iterable if the t represents something that can be iterated
# File lib/puppet/pops/types/type_calculator.rb 185 def iterable(t) 186 # Create an iterable on the type if possible 187 Iterable.on(t) 188 end
# File lib/puppet/pops/types/type_calculator.rb 764 def max(a,b) 765 a >=b ? a : b 766 end
# File lib/puppet/pops/types/type_calculator.rb 768 def min(a,b) 769 a <= b ? a : b 770 end
Reduces an enumerable of types to a single common type. @api public
# File lib/puppet/pops/types/type_calculator.rb 490 def reduce_type(enumerable) 491 enumerable.reduce(nil) {|memo, t| common_type(memo, t) } 492 end
# File lib/puppet/pops/types/type_calculator.rb 702 def size_as_type(collection) 703 size = collection.size 704 PIntegerType.new(size, size) 705 end
Transform int range to a size constraint if range == nil the constraint is 1,1 if range.from == nil min size = 1 if range.to == nil max size == Infinity
# File lib/puppet/pops/types/type_calculator.rb 750 def size_range(range) 751 return [1,1] if range.nil? 752 from = range.from 753 to = range.to 754 x = from.nil? ? 1 : from 755 y = to.nil? ? TheInfinity : to 756 [x, y] 757 end
Produces the superclasses of the given class, including the class
# File lib/puppet/pops/types/type_calculator.rb 478 def superclasses(c) 479 result = [c] 480 while s = c.superclass #rubocop:disable Lint/AssignmentInCondition 481 result << s 482 c = s 483 end 484 result 485 end
Debugging to_s
to reduce the amount of output
# File lib/puppet/pops/types/type_calculator.rb 792 def to_s 793 '[a TypeCalculator]' 794 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/type_calculator.rb 779 def tuple_entry_at(tuple_t, from, to, index) 780 regular = (tuple_t.types.size - 1) 781 if index < regular 782 tuple_t.types[index] 783 elsif index < regular + to 784 # in the varargs part 785 tuple_t.types[-1] 786 else 787 nil 788 end 789 end
Answers 'what is the Puppet
Type
corresponding to the given Ruby class' @param c [Module] the class for which a puppet type is wanted @api public
# File lib/puppet/pops/types/type_calculator.rb 209 def type(c) 210 raise ArgumentError, 'Argument must be a Module' unless c.is_a? Module 211 212 # Can't use a visitor here since we don't have an instance of the class 213 case 214 when c <= Integer 215 type = PIntegerType::DEFAULT 216 when c == Float 217 type = PFloatType::DEFAULT 218 when c == Numeric 219 type = PNumericType::DEFAULT 220 when c == String 221 type = PStringType::DEFAULT 222 when c == Regexp 223 type = PRegexpType::DEFAULT 224 when c == NilClass 225 type = PUndefType::DEFAULT 226 when c == FalseClass, c == TrueClass 227 type = PBooleanType::DEFAULT 228 when c == Class 229 type = PTypeType::DEFAULT 230 when c == Array 231 # Assume array of any 232 type = PArrayType::DEFAULT 233 when c == Hash 234 # Assume hash of any 235 type = PHashType::DEFAULT 236 else 237 type = PRuntimeType.new(:ruby, c.name) 238 end 239 type 240 end
# File lib/puppet/pops/types/type_calculator.rb 737 def unwrap_single_variant(possible_variant) 738 if possible_variant.is_a?(PVariantType) && possible_variant.types.size == 1 739 possible_variant.types[0] 740 else 741 possible_variant 742 end 743 end
Private Instance Methods
# File lib/puppet/pops/types/type_calculator.rb 803 def common_data?(t1, t2) 804 d = TypeFactory.data 805 d.assignable?(t1) && d.assignable?(t2) 806 end
# File lib/puppet/pops/types/type_calculator.rb 816 def common_numeric?(t1, t2) 817 PNumericType::DEFAULT.assignable?(t1) && PNumericType::DEFAULT.assignable?(t2) 818 end
# File lib/puppet/pops/types/type_calculator.rb 798 def common_rich_data?(t1, t2) 799 d = TypeFactory.rich_data 800 d.assignable?(t1) && d.assignable?(t2) 801 end
# File lib/puppet/pops/types/type_calculator.rb 812 def common_scalar?(t1, t2) 813 PScalarType::DEFAULT.assignable?(t1) && PScalarType::DEFAULT.assignable?(t2) 814 end
# File lib/puppet/pops/types/type_calculator.rb 808 def common_scalar_data?(t1, t2) 809 PScalarDataType::DEFAULT.assignable?(t1) && PScalarDataType::DEFAULT.assignable?(t2) 810 end