class Puppet::Pops::Evaluator::AccessOperator
AccessOperator
handles operator [] This operator is part of evaluation.
Constants
- NS
Attributes
Public Class Methods
Initialize with AccessExpression to enable reporting issues @param access_expression [Model::AccessExpression] the semantic object being evaluated @return [void]
# File lib/puppet/pops/evaluator/access_operator.rb 18 def initialize(access_expression) 19 @@access_visitor ||= Visitor.new(self, "access", 2, nil) 20 @semantic = access_expression 21 end
Public Instance Methods
# File lib/puppet/pops/evaluator/access_operator.rb 23 def access(o, scope, *keys) 24 @@access_visitor.visit_this_2(self, o, scope, keys) 25 end
Protected Instance Methods
Evaluates <ary>[] with 1 or 2 arguments. One argument is an index lookup, two arguments is a slice from/to.
# File lib/puppet/pops/evaluator/access_operator.rb 93 def access_Array(o, scope, keys) 94 keys.flatten! 95 case keys.size 96 when 0 97 fail(Issues::BAD_ARRAY_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size}) 98 when 1 99 key = coerce_numeric(keys[0], @semantic.keys[0], scope) 100 unless key.is_a?(Integer) 101 bad_access_key_type(o, 0, key, Integer) 102 end 103 o[key] 104 when 2 105 # A slice [from, to] with support for -1 to mean start, or end respectively. 106 k1 = coerce_numeric(keys[0], @semantic.keys[0], scope) 107 k2 = coerce_numeric(keys[1], @semantic.keys[1], scope) 108 109 [k1, k2].each_with_index { |k,i| bad_access_key_type(o, i, k, Integer) unless k.is_a?(Integer) } 110 111 # Help confused Ruby do the right thing (it truncates to the right, but negative index + length can never overlap 112 # the available range. 113 k1 = k1 < 0 ? o.length + k1 : k1 # abs pos (negative is count from end) 114 k2 = k2 < 0 ? o.length - k1 + k2 + 1 : k2 # abs length (negative k2 is length from pos to end count) 115 # if k1 is outside, adjust to first position, and adjust length 116 if k1 < 0 117 k2 = k2 + k1 118 k1 = 0 119 end 120 # Help ruby always return empty array when asking for a sub array 121 result = o[ k1, k2 ] 122 result.nil? ? [] : result 123 else 124 fail(Issues::BAD_ARRAY_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size}) 125 end 126 end
# File lib/puppet/pops/evaluator/access_operator.rb 38 def access_Binary(o, scope, keys) 39 Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(access_String(o.binary_buffer, scope, keys)) 40 end
Evaluates <hsh>[] with support for one or more arguments. If more than one argument is used, the result is an array with each lookup. @note
Does not flatten its keys to enable looking up with a structure
# File lib/puppet/pops/evaluator/access_operator.rb 134 def access_Hash(o, scope, keys) 135 # Look up key in hash, if key is nil, try alternate form (:undef) before giving up. 136 # This is done because the hash may have been produced by 3x logic and may thus contain :undef. 137 result = keys.collect do |k| 138 o.fetch(k) { |key| key.nil? ? o[:undef] : nil } 139 end 140 case result.size 141 when 0 142 fail(Issues::BAD_HASH_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size}) 143 when 1 144 result.pop 145 else 146 # remove nil elements and return 147 result.compact! 148 result 149 end 150 end
# File lib/puppet/pops/evaluator/access_operator.rb 29 def access_Object(o, scope, keys) 30 type = Puppet::Pops::Types::TypeCalculator.infer_callable_methods_t(o) 31 if type.is_a?(Puppet::Pops::Types::TypeWithMembers) 32 access_func = type['[]'] 33 return access_func.invoke(o, scope, keys) unless access_func.nil? 34 end 35 fail(Issues::OPERATOR_NOT_APPLICABLE, @semantic.left_expr, :operator=>'[]', :left_value => o) 36 end
An Array can create a new Array type. It is not possible to create a collection of Array types.
# File lib/puppet/pops/evaluator/access_operator.rb 509 def access_PArrayType(o, scope, keys) 510 keys.flatten! 511 case keys.size 512 when 1 513 unless keys[0].is_a?(Types::PAnyType) 514 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Array-Type', :actual => keys[0].class}) 515 end 516 type = keys[0] 517 size_t = nil 518 when 2 519 if keys[0].is_a?(Types::PAnyType) 520 size_t = collection_size_t(1, keys[1]) 521 type = keys[0] 522 else 523 size_t = collection_size_t(0, keys[0], keys[1]) 524 type = nil 525 end 526 when 3 527 if keys[0].is_a?(Types::PAnyType) 528 size_t = collection_size_t(1, keys[1], keys[2]) 529 type = keys[0] 530 else 531 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Array-Type', :actual => keys[0].class}) 532 end 533 else 534 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, 535 {:base_type => 'Array-Type', :min => 1, :max => 3, :actual => keys.size}) 536 end 537 Types::PArrayType.new(type, size_t) 538 end
# File lib/puppet/pops/evaluator/access_operator.rb 152 def access_PBooleanType(o, scope, keys) 153 keys.flatten! 154 assert_keys(keys, o, 1, 1, TrueClass, FalseClass) 155 Types::TypeFactory.boolean(keys[0]) 156 end
# File lib/puppet/pops/evaluator/access_operator.rb 207 def access_PCallableType(o, scope, keys) 208 if keys.size > 0 && keys[0].is_a?(Array) 209 unless keys.size == 2 210 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, :base_type => o, :min=>2, :max => 2, :actual => keys.size) 211 end 212 unless keys[1].is_a?(Types::PAnyType) 213 bad_type_specialization_key_type(o, 1, k, Types::PAnyType) 214 end 215 end 216 Types::TypeFactory.callable(*keys) 217 end
# File lib/puppet/pops/evaluator/access_operator.rb 662 def access_PClassType(o, scope, keys) 663 blamed = keys.size == 0 ? @semantic : @semantic.keys[0] 664 keys_orig_size = keys.size 665 666 if keys_orig_size == 0 667 fail(Issues::BAD_TYPE_SLICE_ARITY, blamed, 668 :base_type => o.to_s, :min => 1, :max => -1, :actual => 0) 669 end 670 671 # The result is an array if multiple classnames are given, or if classnames are specified with an array 672 # (possibly multiple arrays, and nested arrays). 673 result_type_array = keys.size > 1 || keys[0].is_a?(Array) 674 675 keys.flatten! 676 keys.compact! 677 678 # If given keys that were just a mix of empty/nil with empty array as a result. 679 # As opposed to calling the function the wrong way (without any arguments), (configurable issue), 680 # Return an empty array 681 # 682 if keys.empty? && keys_orig_size > 0 683 optionally_fail(Issues::EMPTY_RESOURCE_SPECIALIZATION, blamed) 684 return result_type_array ? [] : nil 685 end 686 687 if o.class_name.nil? 688 result = keys.each_with_index.map do |c, i| 689 fail(Issues::ILLEGAL_HOSTCLASS_NAME, @semantic.keys[i], {:name => c}) unless c.is_a?(String) 690 name = c.downcase 691 # Remove leading '::' since all references are global, and 3x runtime does the wrong thing 692 name = name[2..-1] if name[0,2] == NS 693 694 fail(Issues::ILLEGAL_NAME, @semantic.keys[i], {:name=>c}) unless name =~ Patterns::NAME 695 Types::PClassType.new(name) 696 end 697 else 698 # lookup class resource and return one or more parameter values 699 resource = find_resource(scope, 'class', o.class_name) 700 if resource 701 result = keys.map do |k| 702 if is_parameter_of_resource?(scope, resource, k) 703 get_resource_parameter_value(scope, resource, k) 704 else 705 fail(Issues::UNKNOWN_RESOURCE_PARAMETER, @semantic, 706 {:type_name => 'Class', :title => o.class_name, :param_name=>k}) 707 end 708 end 709 else 710 fail(Issues::UNKNOWN_RESOURCE, @semantic, {:type_name => 'Class', :title => o.class_name}) 711 end 712 end 713 714 # returns single type as type, else an array of types 715 return result_type_array ? result : result.pop 716 end
CollectionType is parameterized with a range
# File lib/puppet/pops/evaluator/access_operator.rb 493 def access_PCollectionType(o, scope, keys) 494 keys.flatten! 495 case keys.size 496 when 1 497 size_t = collection_size_t(0, keys[0]) 498 when 2 499 size_t = collection_size_t(0, keys[0], keys[1]) 500 else 501 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, 502 {:base_type => 'Collection-Type', :min => 1, :max => 2, :actual => keys.size}) 503 end 504 Types::PCollectionType.new(size_t) 505 end
# File lib/puppet/pops/evaluator/access_operator.rb 158 def access_PEnumType(o, scope, keys) 159 keys.flatten! 160 last = keys.last 161 case_insensitive = false 162 if last == true || last == false 163 keys = keys[0...-1] 164 case_insensitive = last 165 end 166 assert_keys(keys, o, 1, Float::INFINITY, String) 167 Types::PEnumType.new(keys, case_insensitive) 168 end
# File lib/puppet/pops/evaluator/access_operator.rb 446 def access_PFloatType(o, scope, keys) 447 keys.flatten! 448 unless keys.size.between?(1, 2) 449 fail(Issues::BAD_FLOAT_SLICE_ARITY, @semantic, {:actual => keys.size}) 450 end 451 keys.each_with_index do |x, index| 452 fail(Issues::BAD_FLOAT_SLICE_TYPE, @semantic.keys[index], 453 {:actual => x.class}) unless (x.is_a?(Float) || x.is_a?(Integer) || x == :default) 454 end 455 from, to = keys 456 from = from == :default || from.nil? ? nil : Float(from) 457 to = to == :default || to.nil? ? nil : Float(to) 458 Types::PFloatType.new(from, to) 459 end
A Hash can create a new Hash type, one arg sets value type, two args sets key and value type in new type. With 3 or 4 arguments, these are used to create a size constraint. It is not possible to create a collection of Hash types directly.
# File lib/puppet/pops/evaluator/access_operator.rb 465 def access_PHashType(o, scope, keys) 466 keys.flatten! 467 if keys.size == 2 && keys[0].is_a?(Integer) && keys[1].is_a?(Integer) 468 return Types::PHashType.new(nil, nil, Types::PIntegerType.new(*keys)) 469 end 470 471 keys[0,2].each_with_index do |k, index| 472 unless k.is_a?(Types::PAnyType) 473 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[index], {:base_type => 'Hash-Type', :actual => k.class}) 474 end 475 end 476 case keys.size 477 when 2 478 size_t = nil 479 when 3 480 size_t = keys[2] 481 size_t = Types::PIntegerType.new(size_t) unless size_t.is_a?(Types::PIntegerType) 482 when 4 483 size_t = collection_size_t(2, keys[2], keys[3]) 484 else 485 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, { 486 :base_type => 'Hash-Type', :min => 2, :max => 4, :actual => keys.size 487 }) 488 end 489 Types::PHashType.new(keys[0], keys[1], size_t) 490 end
# File lib/puppet/pops/evaluator/access_operator.rb 396 def access_PInitType(o, scope, keys) 397 unless keys[0].is_a?(Types::PAnyType) 398 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Init-Type', :actual => keys[0].class}) 399 end 400 Types::TypeFactory.init(*keys) 401 end
# File lib/puppet/pops/evaluator/access_operator.rb 434 def access_PIntegerType(o, scope, keys) 435 keys.flatten! 436 unless keys.size.between?(1, 2) 437 fail(Issues::BAD_INTEGER_SLICE_ARITY, @semantic, {:actual => keys.size}) 438 end 439 keys.each_with_index do |x, index| 440 fail(Issues::BAD_INTEGER_SLICE_TYPE, @semantic.keys[index], 441 {:actual => x.class}) unless (x.is_a?(Integer) || x == :default) 442 end 443 Types::PIntegerType.new(*keys) 444 end
# File lib/puppet/pops/evaluator/access_operator.rb 403 def access_PIterableType(o, scope, keys) 404 keys.flatten! 405 if keys.size == 1 406 unless keys[0].is_a?(Types::PAnyType) 407 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Iterable-Type', :actual => keys[0].class}) 408 end 409 Types::PIterableType.new(keys[0]) 410 else 411 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Iterable-Type', :min => 1, :actual => keys.size}) 412 end 413 end
# File lib/puppet/pops/evaluator/access_operator.rb 415 def access_PIteratorType(o, scope, keys) 416 keys.flatten! 417 if keys.size == 1 418 unless keys[0].is_a?(Types::PAnyType) 419 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Iterator-Type', :actual => keys[0].class}) 420 end 421 Types::PIteratorType.new(keys[0]) 422 else 423 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Iterator-Type', :min => 1, :actual => keys.size}) 424 end 425 end
# File lib/puppet/pops/evaluator/access_operator.rb 363 def access_PNotUndefType(o, scope, keys) 364 keys.flatten! 365 case keys.size 366 when 0 367 Types::TypeFactory.not_undef 368 when 1 369 type = keys[0] 370 case type 371 when String 372 type = Types::TypeFactory.string(type) 373 when Types::PAnyType 374 type = nil if type.class == Types::PAnyType 375 else 376 fail(Issues::BAD_NOT_UNDEF_SLICE_TYPE, @semantic.keys[0], {:base_type => 'NotUndef-Type', :actual => type.class}) 377 end 378 Types::TypeFactory.not_undef(type) 379 else 380 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'NotUndef-Type', :min => 0, :max => 1, :actual => keys.size}) 381 end 382 end
# File lib/puppet/pops/evaluator/access_operator.rb 341 def access_PObjectType(o, scope, keys) 342 keys.flatten! 343 if o.resolved? && !o.name.nil? 344 Types::PObjectTypeExtension.create(o, keys) 345 else 346 if keys.size == 1 347 Types::TypeFactory.object(keys[0]) 348 else 349 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Object-Type', :min => 1, :actual => keys.size}) 350 end 351 end 352 end
# File lib/puppet/pops/evaluator/access_operator.rb 311 def access_POptionalType(o, scope, keys) 312 keys.flatten! 313 if keys.size == 1 314 type = keys[0] 315 unless type.is_a?(Types::PAnyType) 316 if type.is_a?(String) 317 type = Types::TypeFactory.string(type) 318 else 319 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Optional-Type', :actual => type.class}) 320 end 321 end 322 Types::POptionalType.new(type) 323 else 324 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Optional-Type', :min => 1, :actual => keys.size}) 325 end 326 end
# File lib/puppet/pops/evaluator/access_operator.rb 292 def access_PPatternType(o, scope, keys) 293 keys.flatten! 294 assert_keys(keys, o, 1, Float::INFINITY, String, Regexp, Types::PPatternType, Types::PRegexpType) 295 Types::TypeFactory.pattern(*keys) 296 end
Parameterizes a PRegexp Type
with a pattern string or r ruby egexp
# File lib/puppet/pops/evaluator/access_operator.rb 81 def access_PRegexpType(o, scope, keys) 82 keys.flatten! 83 unless keys.size == 1 84 blamed = keys.size == 0 ? @semantic : @semantic.keys[1] 85 fail(Issues::BAD_TYPE_SLICE_ARITY, blamed, :base_type => o, :min=>1, :actual => keys.size) 86 end 87 assert_keys(keys, o, 1, 1, String, Regexp) 88 Types::TypeFactory.regexp(*keys) 89 end
A Resource
can create a new more specific Resource
type, and/or an array of resource types If the given type has title set, it can not be specified further. @example
Resource[File] # => File Resource[File, 'foo'] # => File[foo] Resource[File. 'foo', 'bar'] # => [File[foo], File[bar]] File['foo', 'bar'] # => [File[foo], File[bar]] File['foo']['bar'] # => Value of the 'bar' parameter in the File['foo'] resource Resource[File]['foo', 'bar'] # => [File[Foo], File[bar]] Resource[File, 'foo', 'bar'] # => [File[foo], File[bar]] Resource[File, 'foo']['bar'] # => Value of the 'bar' parameter in the File['foo'] resource
# File lib/puppet/pops/evaluator/access_operator.rb 581 def access_PResourceType(o, scope, keys) 582 blamed = keys.size == 0 ? @semantic : @semantic.keys[0] 583 584 if keys.size == 0 585 fail(Issues::BAD_TYPE_SLICE_ARITY, blamed, 586 :base_type => o.to_s, :min => 1, :max => -1, :actual => 0) 587 end 588 589 # Must know which concrete resource type to operate on in all cases. 590 # It is not allowed to specify the type in an array arg - e.g. Resource[[File, 'foo']] 591 # type_name is LHS type_name if set, else the first given arg 592 type_name = o.type_name || Types::TypeFormatter.singleton.capitalize_segments(keys.shift) 593 type_name = case type_name 594 when Types::PResourceType 595 type_name.type_name 596 when String 597 type_name 598 else 599 # blame given left expression if it defined the type, else the first given key expression 600 blame = o.type_name.nil? ? @semantic.keys[0] : @semantic.left_expr 601 fail(Issues::ILLEGAL_RESOURCE_SPECIALIZATION, blame, {:actual => bad_key_type_name(type_name)}) 602 end 603 604 # type name must conform 605 if type_name !~ Patterns::CLASSREF_EXT 606 fail(Issues::ILLEGAL_CLASSREF, blamed, {:name=>type_name}) 607 end 608 609 # The result is an array if multiple titles are given, or if titles are specified with an array 610 # (possibly multiple arrays, and nested arrays). 611 result_type_array = keys.size > 1 || keys[0].is_a?(Array) 612 keys_orig_size = keys.size 613 614 keys.flatten! 615 keys.compact! 616 617 # If given keys that were just a mix of empty/nil with empty array as a result. 618 # As opposed to calling the function the wrong way (without any arguments), (configurable issue), 619 # Return an empty array 620 # 621 if keys.empty? && keys_orig_size > 0 622 optionally_fail(Issues::EMPTY_RESOURCE_SPECIALIZATION, blamed) 623 return result_type_array ? [] : nil 624 end 625 626 if !o.title.nil? 627 # lookup resource and return one or more parameter values 628 resource = find_resource(scope, o.type_name, o.title) 629 unless resource 630 fail(Issues::UNKNOWN_RESOURCE, @semantic, {:type_name => o.type_name, :title => o.title}) 631 end 632 633 result = keys.map do |k| 634 unless is_parameter_of_resource?(scope, resource, k) 635 fail(Issues::UNKNOWN_RESOURCE_PARAMETER, @semantic, 636 {:type_name => o.type_name, :title => o.title, :param_name=>k}) 637 end 638 get_resource_parameter_value(scope, resource, k) 639 end 640 return result_type_array ? result : result.pop 641 end 642 643 644 keys = [:no_title] if keys.size < 1 # if there was only a type_name and it was consumed 645 result = keys.each_with_index.map do |t, i| 646 unless t.is_a?(String) || t == :no_title 647 index = keys_orig_size != keys.size ? i+1 : i 648 fail(Issues::BAD_TYPE_SPECIALIZATION, @semantic.keys[index], { 649 :type => o, 650 :message => "Cannot use #{bad_key_type_name(t)} where a resource title String is expected" 651 }) 652 end 653 654 Types::PResourceType.new(type_name, t == :no_title ? nil : t) 655 end 656 # returns single type if request was for a single entity, else an array of types (possibly empty) 657 return result_type_array ? result : result.pop 658 end
# File lib/puppet/pops/evaluator/access_operator.rb 427 def access_PRuntimeType(o, scope, keys) 428 keys.flatten! 429 assert_keys(keys, o, 2, 2, String, String) 430 # create runtime type based on runtime and name of class, (not inference of key's type) 431 Types::TypeFactory.runtime(*keys) 432 end
# File lib/puppet/pops/evaluator/access_operator.rb 176 def access_PSemVerType(o, scope, keys) 177 keys.flatten! 178 assert_keys(keys, o, 1, Float::INFINITY, String, SemanticPuppet::VersionRange) 179 Types::TypeFactory.sem_ver(*keys) 180 end
# File lib/puppet/pops/evaluator/access_operator.rb 328 def access_PSensitiveType(o, scope, keys) 329 keys.flatten! 330 if keys.size == 1 331 type = keys[0] 332 unless type.is_a?(Types::PAnyType) 333 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Sensitive-Type', :actual => type.class}) 334 end 335 Types::PSensitiveType.new(type) 336 else 337 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Sensitive-Type', :min => 1, :actual => keys.size}) 338 end 339 end
# File lib/puppet/pops/evaluator/access_operator.rb 224 def access_PStringType(o, scope, keys) 225 keys.flatten! 226 case keys.size 227 when 1 228 size_t = collection_size_t(0, keys[0]) 229 when 2 230 size_t = collection_size_t(0, keys[0], keys[1]) 231 else 232 fail(Issues::BAD_STRING_SLICE_ARITY, @semantic, {:actual => keys.size}) 233 end 234 Types::TypeFactory.string(size_t) 235 end
# File lib/puppet/pops/evaluator/access_operator.rb 219 def access_PStructType(o, scope, keys) 220 assert_keys(keys, o, 1, 1, Hash) 221 Types::TypeFactory.struct(keys[0]) 222 end
# File lib/puppet/pops/evaluator/access_operator.rb 188 def access_PTimespanType(o, scope, keys) 189 keys.flatten! 190 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, :base_type => o, :min=>0, :max => 2, :actual => keys.size) if keys.size > 2 191 Types::TypeFactory.timespan(*keys) 192 end
# File lib/puppet/pops/evaluator/access_operator.rb 182 def access_PTimestampType(o, scope, keys) 183 keys.flatten! 184 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, :base_type => o, :min=>0, :max => 2, :actual => keys.size) if keys.size > 2 185 Types::TypeFactory.timestamp(*keys) 186 end
# File lib/puppet/pops/evaluator/access_operator.rb 194 def access_PTupleType(o, scope, keys) 195 keys.flatten! 196 if Types::TypeFactory.is_range_parameter?(keys[-2]) && Types::TypeFactory.is_range_parameter?(keys[-1]) 197 size_type = Types::TypeFactory.range(keys[-2], keys[-1]) 198 keys = keys[0, keys.size - 2] 199 elsif Types::TypeFactory.is_range_parameter?(keys[-1]) 200 size_type = Types::TypeFactory.range(keys[-1], :default) 201 keys = keys[0, keys.size - 1] 202 end 203 assert_keys(keys, o, 1, Float::INFINITY, Types::PAnyType) 204 Types::TypeFactory.tuple(keys, size_type) 205 end
If a type reference is encountered here, it's an error
# File lib/puppet/pops/evaluator/access_operator.rb 565 def access_PTypeReferenceType(o, scope, keys) 566 fail(Issues::UNKNOWN_RESOURCE_TYPE, @semantic, {:type_name => o.type_string }) 567 end
# File lib/puppet/pops/evaluator/access_operator.rb 354 def access_PTypeSetType(o, scope, keys) 355 keys.flatten! 356 if keys.size == 1 357 Types::TypeFactory.type_set(keys[0]) 358 else 359 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'TypeSet-Type', :min => 1, :actual => keys.size}) 360 end 361 end
# File lib/puppet/pops/evaluator/access_operator.rb 384 def access_PTypeType(o, scope, keys) 385 keys.flatten! 386 if keys.size == 1 387 unless keys[0].is_a?(Types::PAnyType) 388 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Type-Type', :actual => keys[0].class}) 389 end 390 Types::PTypeType.new(keys[0]) 391 else 392 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Type-Type', :min => 1, :actual => keys.size}) 393 end 394 end
# File lib/puppet/pops/evaluator/access_operator.rb 298 def access_PURIType(o, scope, keys) 299 keys.flatten! 300 if keys.size == 1 301 param = keys[0] 302 unless Types::PURIType::TYPE_URI_PARAM_TYPE.instance?(param) 303 fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'URI-Type', :actual => param.class}) 304 end 305 Types::PURIType.new(param) 306 else 307 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'URI-Type', :min => 1, :actual => keys.size}) 308 end 309 end
# File lib/puppet/pops/evaluator/access_operator.rb 170 def access_PVariantType(o, scope, keys) 171 keys.flatten! 172 assert_keys(keys, o, 1, Float::INFINITY, Types::PAnyType) 173 Types::TypeFactory.variant(*keys) 174 end
A Puppet::Resource
represents either just a type (no title), or is a fully qualified type/title.
# File lib/puppet/pops/evaluator/access_operator.rb 555 def access_Resource(o, scope, keys) 556 # To access a Puppet::Resource as if it was a PResourceType, simply infer it, and take the type of 557 # the parameterized meta type (i.e. Type[Resource[the_resource_type, the_resource_title]]) 558 t = Types::TypeCalculator.infer(o).type 559 # must map "undefined title" from resource to nil 560 t.title = nil if t.title == EMPTY_STRING 561 access(t, scope, *keys) 562 end
# File lib/puppet/pops/evaluator/access_operator.rb 42 def access_String(o, scope, keys) 43 keys.flatten! 44 result = case keys.size 45 when 0 46 fail(Issues::BAD_STRING_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size}) 47 when 1 48 # Note that Ruby 1.8.7 requires a length of 1 to produce a String 49 k1 = Utils.to_n(keys[0]) 50 bad_string_access_key_type(o, 0, k1.nil? ? keys[0] : k1) unless k1.is_a?(Integer) 51 k2 = 1 52 k1 = k1 < 0 ? o.length + k1 : k1 # abs pos 53 # if k1 is outside, a length of 1 always produces an empty string 54 if k1 < 0 55 EMPTY_STRING 56 else 57 o[ k1, k2 ] 58 end 59 when 2 60 k1 = Utils.to_n(keys[0]) 61 k2 = Utils.to_n(keys[1]) 62 [k1, k2].each_with_index { |k,i| bad_string_access_key_type(o, i, k.nil? ? keys[i] : k) unless k.is_a?(Integer) } 63 64 k1 = k1 < 0 ? o.length + k1 : k1 # abs pos (negative is count from end) 65 k2 = k2 < 0 ? o.length - k1 + k2 + 1 : k2 # abs length (negative k2 is length from pos to end count) 66 # if k1 is outside, adjust to first position, and adjust length 67 if k1 < 0 68 k2 = k2 + k1 69 k1 = 0 70 end 71 o[ k1, k2 ] 72 else 73 fail(Issues::BAD_STRING_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size}) 74 end 75 # Specified as: an index outside of range, or empty result == empty string 76 (result.nil? || result.empty?) ? EMPTY_STRING : result 77 end
Asserts type of each key and calls fail with BAD_TYPE_SPECIFICATION @param keys [Array<Object>] the evaluated keys @param o [Object] evaluated LHS reported as :base_type @param min [Integer] the minimum number of keys (typically 1) @param max [Numeric] the maximum number of keys (use same as min, specific number, or Float::INFINITY) @param allowed_classes [Class] a variable number of classes that each key must be an instance of (any) @api private
# File lib/puppet/pops/evaluator/access_operator.rb 245 def assert_keys(keys, o, min, max, *allowed_classes) 246 size = keys.size 247 unless size.between?(min, max || Float::INFINITY) 248 fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, :base_type => o, :min=>1, :max => max, :actual => keys.size) 249 end 250 keys.each_with_index do |k, i| 251 unless allowed_classes.any? {|clazz| k.is_a?(clazz) } 252 bad_type_specialization_key_type(o, i, k, *allowed_classes) 253 end 254 end 255 end
# File lib/puppet/pops/evaluator/access_operator.rb 257 def bad_access_key_type(lhs, key_index, actual, *expected_classes) 258 fail(Issues::BAD_SLICE_KEY_TYPE, @semantic.keys[key_index], { 259 :left_value => lhs, 260 :actual => bad_key_type_name(actual), 261 :expected_classes => expected_classes 262 }) 263 end
# File lib/puppet/pops/evaluator/access_operator.rb 272 def bad_key_type_name(actual) 273 case actual 274 when nil 275 'Undef' 276 when :default 277 'Default' 278 else 279 Types::TypeCalculator.generalize(Types::TypeCalculator.infer(actual)).to_s 280 end 281 end
# File lib/puppet/pops/evaluator/access_operator.rb 265 def bad_string_access_key_type(lhs, key_index, actual) 266 fail(Issues::BAD_STRING_SLICE_KEY_TYPE, @semantic.keys[key_index], { 267 :left_value => lhs, 268 :actual_type => bad_key_type_name(actual), 269 }) 270 end
# File lib/puppet/pops/evaluator/access_operator.rb 283 def bad_type_specialization_key_type(type, key_index, actual, *expected_classes) 284 label_provider = Model::ModelLabelProvider.new() 285 expected = expected_classes.map {|c| label_provider.label(c) }.join(' or ') 286 fail(Issues::BAD_TYPE_SPECIALIZATION, @semantic.keys[key_index], { 287 :type => type, 288 :message => _("Cannot use %{key} where %{expected} is expected") % { key: bad_key_type_name(actual), expected: expected } 289 }) 290 end
Produces an PIntegerType (range) given one or two keys.
# File lib/puppet/pops/evaluator/access_operator.rb 541 def collection_size_t(start_index, *keys) 542 if keys.size == 1 && keys[0].is_a?(Types::PIntegerType) 543 keys[0] 544 else 545 keys.each_with_index do |x, index| 546 fail(Issues::BAD_COLLECTION_SLICE_TYPE, @semantic.keys[start_index + index], 547 {:actual => x.class}) unless (x.is_a?(Integer) || x == :default) 548 end 549 Types::PIntegerType.new(*keys) 550 end 551 end