puppet 4.4.2 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (218) hide show
  1. data/CONTRIBUTING.md +5 -5
  2. data/Gemfile +2 -2
  3. data/LICENSE +2 -2
  4. data/README.md +5 -0
  5. data/ext/project_data.yaml +2 -0
  6. data/lib/hiera_puppet.rb +6 -14
  7. data/lib/puppet/application/agent.rb +2 -3
  8. data/lib/puppet/data_providers/hiera_config.rb +2 -4
  9. data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
  10. data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
  11. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
  12. data/lib/puppet/defaults.rb +70 -7
  13. data/lib/puppet/functions.rb +69 -0
  14. data/lib/puppet/functions/dig.rb +39 -0
  15. data/lib/puppet/functions/lest.rb +53 -0
  16. data/lib/puppet/functions/lookup.rb +40 -27
  17. data/lib/puppet/functions/new.rb +502 -0
  18. data/lib/puppet/functions/regsubst.rb +11 -10
  19. data/lib/puppet/functions/then.rb +74 -0
  20. data/lib/puppet/functions/type.rb +4 -4
  21. data/lib/puppet/functions/with.rb +1 -1
  22. data/lib/puppet/indirector/catalog/compiler.rb +2 -0
  23. data/lib/puppet/indirector/resource_type/parser.rb +5 -0
  24. data/lib/puppet/indirector/rest.rb +5 -1
  25. data/lib/puppet/loaders.rb +2 -0
  26. data/lib/puppet/metatype/manager.rb +19 -2
  27. data/lib/puppet/module_tool/applications/application.rb +1 -1
  28. data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
  29. data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
  30. data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
  31. data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
  32. data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
  33. data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
  34. data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
  35. data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
  36. data/lib/puppet/parser/environment_compiler.rb +2 -2
  37. data/lib/puppet/parser/resource.rb +14 -5
  38. data/lib/puppet/parser/scope.rb +18 -15
  39. data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
  40. data/lib/puppet/pops.rb +6 -0
  41. data/lib/puppet/pops/adapters.rb +5 -1
  42. data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
  43. data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
  44. data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
  45. data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
  46. data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
  47. data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
  48. data/lib/puppet/pops/functions/dispatcher.rb +1 -1
  49. data/lib/puppet/pops/issues.rb +18 -2
  50. data/lib/puppet/pops/loader/base_loader.rb +48 -7
  51. data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
  52. data/lib/puppet/pops/loader/loader.rb +12 -0
  53. data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
  54. data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
  55. data/lib/puppet/pops/loader/static_loader.rb +92 -5
  56. data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
  57. data/lib/puppet/pops/loaders.rb +84 -14
  58. data/lib/puppet/pops/lookup/explainer.rb +38 -1
  59. data/lib/puppet/pops/lookup/interpolation.rb +115 -0
  60. data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
  61. data/lib/puppet/pops/model/ast_transformer.rb +8 -1
  62. data/lib/puppet/pops/model/factory.rb +31 -8
  63. data/lib/puppet/pops/model/model.rb +8 -0
  64. data/lib/puppet/pops/model/model_label_provider.rb +1 -0
  65. data/lib/puppet/pops/model/model_meta.rb +7 -1
  66. data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
  67. data/lib/puppet/pops/parser/egrammar.ra +24 -7
  68. data/lib/puppet/pops/parser/eparser.rb +863 -798
  69. data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
  70. data/lib/puppet/pops/parser/locator.rb +8 -4
  71. data/lib/puppet/pops/pcore.rb +30 -0
  72. data/lib/puppet/pops/types/class_loader.rb +2 -4
  73. data/lib/puppet/pops/types/implementation_registry.rb +146 -0
  74. data/lib/puppet/pops/types/iterable.rb +4 -4
  75. data/lib/puppet/pops/types/p_object_type.rb +846 -0
  76. data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
  77. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
  78. data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
  79. data/lib/puppet/pops/types/puppet_object.rb +21 -0
  80. data/lib/puppet/pops/types/ruby_generator.rb +258 -0
  81. data/lib/puppet/pops/types/string_converter.rb +922 -0
  82. data/lib/puppet/pops/types/type_calculator.rb +29 -5
  83. data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
  84. data/lib/puppet/pops/types/type_factory.rb +49 -16
  85. data/lib/puppet/pops/types/type_formatter.rb +335 -112
  86. data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
  87. data/lib/puppet/pops/types/type_parser.rb +205 -197
  88. data/lib/puppet/pops/types/types.rb +481 -103
  89. data/lib/puppet/pops/validation.rb +1 -1
  90. data/lib/puppet/pops/validation/checker4_0.rb +66 -4
  91. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  92. data/lib/puppet/pops/visitor.rb +3 -1
  93. data/lib/puppet/property.rb +1 -1
  94. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  95. data/lib/puppet/provider/package/pip.rb +64 -20
  96. data/lib/puppet/provider/package/rpm.rb +112 -0
  97. data/lib/puppet/provider/package/yum.rb +7 -68
  98. data/lib/puppet/provider/service/daemontools.rb +3 -3
  99. data/lib/puppet/provider/service/init.rb +4 -2
  100. data/lib/puppet/provider/service/runit.rb +3 -3
  101. data/lib/puppet/provider/service/smf.rb +6 -3
  102. data/lib/puppet/provider/service/systemd.rb +59 -73
  103. data/lib/puppet/reference/providers.rb +1 -2
  104. data/lib/puppet/resource.rb +54 -37
  105. data/lib/puppet/resource/catalog.rb +31 -29
  106. data/lib/puppet/resource/type_collection.rb +23 -8
  107. data/lib/puppet/settings.rb +4 -2
  108. data/lib/puppet/settings/base_setting.rb +9 -3
  109. data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
  110. data/lib/puppet/test/test_helper.rb +0 -1
  111. data/lib/puppet/type.rb +9 -3
  112. data/lib/puppet/type/exec.rb +17 -17
  113. data/lib/puppet/type/file.rb +12 -0
  114. data/lib/puppet/type/file/content.rb +6 -6
  115. data/lib/puppet/type/file/ensure.rb +4 -4
  116. data/lib/puppet/type/file/source.rb +4 -4
  117. data/lib/puppet/type/file/target.rb +2 -2
  118. data/lib/puppet/type/mount.rb +18 -1
  119. data/lib/puppet/type/package.rb +3 -3
  120. data/lib/puppet/type/schedule.rb +4 -4
  121. data/lib/puppet/type/service.rb +15 -0
  122. data/lib/puppet/type/sshkey.rb +5 -3
  123. data/lib/puppet/type/tidy.rb +3 -3
  124. data/lib/puppet/type/zone.rb +5 -5
  125. data/lib/puppet/util/feature.rb +1 -1
  126. data/lib/puppet/util/monkey_patches.rb +8 -0
  127. data/lib/puppet/util/network_device/cisco/device.rb +16 -6
  128. data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
  129. data/lib/puppet/util/plist.rb +3 -3
  130. data/lib/puppet/version.rb +1 -1
  131. data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
  132. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
  133. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
  134. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
  135. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
  136. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
  137. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
  138. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
  139. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
  140. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
  141. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
  142. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
  145. data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
  146. data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
  147. data/spec/integration/parser/catalog_spec.rb +14 -2
  148. data/spec/integration/parser/compiler_spec.rb +94 -3
  149. data/spec/integration/parser/resource_expressions_spec.rb +1 -1
  150. data/spec/integration/resource/type_collection_spec.rb +8 -0
  151. data/spec/lib/puppet_spec/compiler.rb +11 -4
  152. data/spec/shared_contexts/types_setup.rb +4 -0
  153. data/spec/unit/application/lookup_spec.rb +91 -9
  154. data/spec/unit/appmgmt_spec.rb +44 -35
  155. data/spec/unit/capability_spec.rb +33 -53
  156. data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
  157. data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
  158. data/spec/unit/defaults_spec.rb +18 -0
  159. data/spec/unit/functions/assert_type_spec.rb +1 -1
  160. data/spec/unit/functions/dig_spec.rb +58 -0
  161. data/spec/unit/functions/lest_spec.rb +34 -0
  162. data/spec/unit/functions/lookup_spec.rb +108 -2
  163. data/spec/unit/functions/new_spec.rb +543 -0
  164. data/spec/unit/functions/regsubst_spec.rb +8 -0
  165. data/spec/unit/functions/then_spec.rb +40 -0
  166. data/spec/unit/functions4_spec.rb +78 -10
  167. data/spec/unit/hiera_puppet_spec.rb +49 -8
  168. data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
  169. data/spec/unit/indirector/rest_spec.rb +12 -0
  170. data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
  171. data/spec/unit/node/environment_spec.rb +10 -0
  172. data/spec/unit/parser/compiler_spec.rb +20 -1
  173. data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
  174. data/spec/unit/parser/functions/shared.rb +1 -1
  175. data/spec/unit/parser/resource_spec.rb +8 -1
  176. data/spec/unit/parser/scope_spec.rb +45 -0
  177. data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
  178. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
  179. data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
  180. data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
  181. data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
  182. data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
  183. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
  184. data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
  185. data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
  186. data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
  187. data/spec/unit/pops/types/enumeration_spec.rb +13 -12
  188. data/spec/unit/pops/types/iterable_spec.rb +2 -2
  189. data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
  190. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
  191. data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
  192. data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
  193. data/spec/unit/pops/types/string_converter_spec.rb +904 -0
  194. data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
  195. data/spec/unit/pops/types/type_factory_spec.rb +119 -104
  196. data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
  197. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
  198. data/spec/unit/pops/types/type_parser_spec.rb +54 -15
  199. data/spec/unit/pops/types/types_spec.rb +113 -8
  200. data/spec/unit/pops/validator/validator_spec.rb +84 -10
  201. data/spec/unit/provider/package/pip3_spec.rb +9 -270
  202. data/spec/unit/provider/package/pip_spec.rb +85 -30
  203. data/spec/unit/provider/package/rpm_spec.rb +160 -3
  204. data/spec/unit/provider/package/yum_spec.rb +23 -134
  205. data/spec/unit/provider/service/smf_spec.rb +14 -2
  206. data/spec/unit/provider/service/systemd_spec.rb +33 -41
  207. data/spec/unit/resource/capability_finder_spec.rb +10 -2
  208. data/spec/unit/settings/file_setting_spec.rb +6 -0
  209. data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
  210. data/spec/unit/type/mount_spec.rb +51 -10
  211. data/spec/unit/type/service_spec.rb +16 -0
  212. data/spec/unit/type_spec.rb +14 -0
  213. data/spec/unit/util/feature_spec.rb +1 -1
  214. data/spec/unit/util/monkey_patches_spec.rb +60 -0
  215. data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
  216. metadata +63 -11
  217. data/lib/puppet/pops/types/types_meta.rb +0 -0
  218. data/spec/integration/provider/package_spec.rb +0 -35
@@ -4,6 +4,7 @@ require_relative 'recursion_guard'
4
4
  require_relative 'type_acceptor'
5
5
  require_relative 'type_asserter'
6
6
  require_relative 'type_assertion_error'
7
+ require_relative 'type_conversion_error'
7
8
  require_relative 'type_formatter'
8
9
  require_relative 'type_calculator'
9
10
  require_relative 'type_factory'
@@ -11,10 +12,10 @@ require_relative 'type_parser'
11
12
  require_relative 'class_loader'
12
13
  require_relative 'type_mismatch_describer'
13
14
 
14
- require 'rgen/metamodel_builder'
15
-
16
15
  module Puppet::Pops
17
16
  module Types
17
+
18
+ EMPTY_HASH = {}.freeze
18
19
  # The Types model is a model of Puppet Language types.
19
20
  #
20
21
  # The exact relationship between types is not visible in this model wrt. the PDataType which is an abstraction
@@ -115,6 +116,14 @@ class PAnyType < TypedModelObject
115
116
  false
116
117
  end
117
118
 
119
+ # Called from the `PTypeAliasType` when it detects self recursion. The default is to do nothing
120
+ # but some self recursive constructs are illegal such as when a `PObjectType` somehow inherits itself
121
+ # @param originator [PTypeAliasType] the starting point for the check
122
+ # @raise Puppet::Error if an illegal self recursion is detected
123
+ # @api private
124
+ def check_self_recursion(originator)
125
+ end
126
+
118
127
  # Generalizes value specific types. Types that are not value specific will return `self` otherwise
119
128
  # the generalized type is returned.
120
129
  #
@@ -136,6 +145,18 @@ class PAnyType < TypedModelObject
136
145
  self
137
146
  end
138
147
 
148
+ # Called from the TypeParser once it has found a type using the Loader to enable that this type can
149
+ # resolve internal type expressions using a loader. Presently, this method is a no-op for all types
150
+ # except the {{PTypeAliasType}}.
151
+ #
152
+ # @param type_parser [TypeParser] type parser
153
+ # @param loader [Loader::Loader] loader to use
154
+ # @return [PTypeAliasType] the receiver of the call, i.e. `self`
155
+ # @api private
156
+ def resolve(type_parser, loader)
157
+ self
158
+ end
159
+
139
160
  # Responds `true` for all callables, variants of callables and unless _optional_ is
140
161
  # false, all optional callables.
141
162
  # @param optional [Boolean]
@@ -217,6 +238,29 @@ class PAnyType < TypedModelObject
217
238
  TypeFormatter.string(self)
218
239
  end
219
240
 
241
+ # Returns the name of the type, without parameters
242
+ # @return [String] the name of the type
243
+ # @api public
244
+ def name
245
+ simple_name
246
+ end
247
+
248
+ def new_function(loader)
249
+ self.class.new_function(self, loader)
250
+ end
251
+
252
+ # This default implementation of of a new_function raises an Argument Error.
253
+ # Types for which creating a new instance is supported, should create and return
254
+ # a Puppet Function class by using Puppet:Loaders.create_loaded_function(:new, loader)
255
+ # and return that result.
256
+ #
257
+ # @raises ArgumentError
258
+ #
259
+ def self.new_function(instance, loader)
260
+ raise ArgumentError.new("Creation of new instance of type '#{instance.to_s}' is not supported")
261
+ end
262
+
263
+
220
264
  # The default instance of this type. Each type in the type system has this constant
221
265
  # declared.
222
266
  #
@@ -229,19 +273,6 @@ class PAnyType < TypedModelObject
229
273
  o.is_a?(PAnyType)
230
274
  end
231
275
 
232
- NAME_SEGMENT_SEPARATOR = '::'.freeze
233
-
234
- # @api private
235
- def class_from_string(str)
236
- begin
237
- str.split(NAME_SEGMENT_SEPARATOR).reduce(Object) do |memo, name_segment|
238
- memo.const_get(name_segment)
239
- end
240
- rescue NameError
241
- return nil
242
- end
243
- end
244
-
245
276
  # Produces the tuple entry at the given index given a tuple type, its from/to constraints on the last
246
277
  # type, and an index.
247
278
  # Produces nil if the index is out of bounds
@@ -430,6 +461,15 @@ class PNotUndefType < PTypeWithContainedType
430
461
  end
431
462
  end
432
463
 
464
+ def new_function(loader)
465
+ # If only NotUndef, then use Unit's null converter
466
+ if type.nil?
467
+ PUnitType.new_function(self.class, loader)
468
+ else
469
+ type.new_function(loader)
470
+ end
471
+ end
472
+
433
473
  DEFAULT = PNotUndefType.new
434
474
 
435
475
  protected
@@ -470,6 +510,19 @@ class PUnitType < PAnyType
470
510
  true
471
511
  end
472
512
 
513
+ # A "null" implementation - that simply returns the given argument
514
+ def self.new_function(_, loader)
515
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_unit, loader) do
516
+ dispatch :from_args do
517
+ param 'Any', :from
518
+ end
519
+
520
+ def from_args(from)
521
+ from
522
+ end
523
+ end
524
+ end
525
+
473
526
  DEFAULT = PUnitType.new
474
527
 
475
528
  protected
@@ -663,6 +716,56 @@ class PNumericType < PScalarType
663
716
  @from == -Float::INFINITY && @to == Float::INFINITY
664
717
  end
665
718
 
719
+ def self.new_function(_, loader)
720
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_numeric, loader) do
721
+ local_types do
722
+ type 'Convertible = Variant[Undef, Integer, Float, Boolean, String]'
723
+ type 'NamedArgs = Struct[{from => Convertible}]'
724
+ end
725
+
726
+ dispatch :from_args do
727
+ param 'Convertible', :from
728
+ end
729
+
730
+ dispatch :from_hash do
731
+ param 'NamedArgs', :hash_args
732
+ end
733
+ def from_args(from)
734
+ case from
735
+ when NilClass
736
+ throw :undefined_value
737
+ when Float
738
+ from
739
+ when Integer
740
+ from
741
+ when TrueClass
742
+ 1
743
+ when FalseClass
744
+ 0
745
+ when String
746
+ begin
747
+ if from[0] == '0' && (from[1].downcase == 'b' || from[1].downcase == 'x')
748
+ Integer(from)
749
+ else
750
+ Puppet::Pops::Utils.to_n(from)
751
+ end
752
+ rescue TypeError => e
753
+ raise TypeConversionError.new(e.message)
754
+ rescue ArgumentError => e
755
+ raise TypeConversionError.new(e.message)
756
+ end
757
+ else
758
+ t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
759
+ raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Numeric")
760
+ end
761
+ end
762
+
763
+ def from_hash(args_hash)
764
+ from_args(args_hash['from'])
765
+ end
766
+ end
767
+ end
768
+
666
769
  DEFAULT = PNumericType.new(-Float::INFINITY)
667
770
 
668
771
  protected
@@ -753,6 +856,67 @@ class PIntegerType < PNumericType
753
856
  @from >= 0 ? self : PIntegerType.new(0, @to < 0 ? 0 : @to)
754
857
  end
755
858
 
859
+ def new_function(loader)
860
+ @@new_function ||= Puppet::Functions.create_loaded_function(:new, loader) do
861
+ local_types do
862
+ type 'Radix = Variant[Default, Integer[2,2], Integer[8,8], Integer[10,10], Integer[16,16]]'
863
+ type 'Convertible = Variant[Undef, Integer, Float, Boolean, String]'
864
+ type 'NamedArgs = Struct[{from => Convertible, Optional[radix] => Radix}]'
865
+ end
866
+
867
+ dispatch :from_args do
868
+ param 'Convertible', :from
869
+ optional_param 'Radix', :radix
870
+ end
871
+
872
+ dispatch :from_hash do
873
+ param 'NamedArgs', :hash_args
874
+ end
875
+
876
+ def from_args(from, radix = :default)
877
+ case from
878
+ when NilClass
879
+ throw :undefined_value
880
+ when Float
881
+ from.to_i
882
+ when Integer
883
+ from
884
+ when TrueClass
885
+ 1
886
+ when FalseClass
887
+ 0
888
+ when String
889
+ begin
890
+ radix == :default ? Integer(from) : Integer(from, assert_radix(radix))
891
+ rescue TypeError => e
892
+ raise TypeConversionError.new(e.message)
893
+ rescue ArgumentError => e
894
+ raise TypeConversionError.new(e.message)
895
+ end
896
+ else
897
+ t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
898
+ raise TypeConversionError.new("Value of type '#{t}' cannot be converted to an Integer")
899
+ end
900
+ end
901
+
902
+ def from_hash(args_hash)
903
+ from = args_hash['from']
904
+ radix = args_hash['radix'] || :default
905
+ from_args(from, radix)
906
+ end
907
+
908
+ def assert_radix(radix)
909
+ case radix
910
+ when 2, 8, 10, 16, :default
911
+ else
912
+ raise ArgumentError.new("Illegal radix: '#{radix}', expected 2, 8, 10, 16, or default")
913
+ end
914
+ radix
915
+ end
916
+
917
+ end
918
+ end
919
+
756
920
  DEFAULT = PIntegerType.new(-Float::INFINITY)
757
921
  end
758
922
 
@@ -783,6 +947,59 @@ class PFloatType < PNumericType
783
947
  end
784
948
  end
785
949
 
950
+ # Returns a new function that produces a Float value
951
+ #
952
+ def self.new_function(_, loader)
953
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_float, loader) do
954
+ local_types do
955
+ type 'Convertible = Variant[Undef, Integer, Float, Boolean, String]'
956
+ type 'NamedArgs = Struct[{from => Convertible}]'
957
+ end
958
+
959
+ dispatch :from_args do
960
+ param 'Convertible', :from
961
+ end
962
+
963
+ dispatch :from_hash do
964
+ param 'NamedArgs', :hash_args
965
+ end
966
+
967
+ def from_args(from)
968
+ case from
969
+ when NilClass
970
+ throw :undefined_value
971
+ when Float
972
+ from
973
+ when Integer
974
+ Float(from)
975
+ when TrueClass
976
+ 1.0
977
+ when FalseClass
978
+ 0.0
979
+ when String
980
+ begin
981
+ # support a binary as float
982
+ if from[0] == '0' && from[1].downcase == 'b'
983
+ from = Integer(from)
984
+ end
985
+ Float(from)
986
+ rescue TypeError => e
987
+ raise TypeConversionError.new(e.message)
988
+ rescue ArgumentError => e
989
+ raise TypeConversionError.new(e.message)
990
+ end
991
+ else
992
+ t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
993
+ raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Float")
994
+ end
995
+ end
996
+
997
+ def from_hash(args_hash)
998
+ from_args(args_hash['from'])
999
+ end
1000
+ end
1001
+ end
1002
+
786
1003
  DEFAULT = PFloatType.new(-Float::INFINITY)
787
1004
  end
788
1005
 
@@ -792,10 +1009,11 @@ class PCollectionType < PAnyType
792
1009
  attr_reader :element_type, :size_type
793
1010
 
794
1011
  def initialize(element_type, size_type = nil)
795
- @element_type = element_type
796
1012
  @size_type = size_type
797
- if has_empty_range? && !@element_type.is_a?(PUnitType)
798
- raise ArgumentError, 'An empty collection may not specify an element type'
1013
+ if !size_type.nil? && size_type.from == 0 && size_type.to == 0
1014
+ @element_type = PUnitType::DEFAULT
1015
+ else
1016
+ @element_type = element_type
799
1017
  end
800
1018
  end
801
1019
 
@@ -1001,6 +1219,32 @@ class PStringType < PScalarType
1001
1219
  end
1002
1220
  end
1003
1221
 
1222
+ def self.new_function(_, loader)
1223
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_string, loader) do
1224
+ local_types do
1225
+ type 'Format = Pattern[/^%([\s\+\-#0\[\{<\(\|]*)([1-9][0-9]*)?(?:\.([0-9]+))?([a-zA-Z])/]'
1226
+ type 'ContainerFormat = Struct[{
1227
+ Optional[format] => String,
1228
+ Optional[separator] => String,
1229
+ Optional[separator2] => String,
1230
+ Optional[string_formats] => Hash[Type, Format]
1231
+ }]'
1232
+ type 'TypeMap = Hash[Type, Variant[Format, ContainerFormat]]'
1233
+ type 'Convertible = Any'
1234
+ type 'Formats = Variant[Default, String[1], TypeMap]'
1235
+ end
1236
+
1237
+ dispatch :from_args do
1238
+ param 'Convertible', :from
1239
+ optional_param 'Formats', :string_formats
1240
+ end
1241
+
1242
+ def from_args(from, formats = :default)
1243
+ StringConverter.singleton.convert(from, formats)
1244
+ end
1245
+ end
1246
+ end
1247
+
1004
1248
  DEFAULT = PStringType.new(nil)
1005
1249
  NON_EMPTY = PStringType.new(PIntegerType.new(1))
1006
1250
 
@@ -1059,7 +1303,12 @@ class PRegexpType < PScalarType
1059
1303
  attr_reader :pattern
1060
1304
 
1061
1305
  def initialize(pattern)
1062
- @pattern = pattern
1306
+ if pattern.is_a?(Regexp)
1307
+ @regexp = pattern
1308
+ @pattern = pattern.source
1309
+ else
1310
+ @pattern = pattern
1311
+ end
1063
1312
  end
1064
1313
 
1065
1314
  def regexp
@@ -1146,6 +1395,34 @@ class PBooleanType < PScalarType
1146
1395
  o == true || o == false
1147
1396
  end
1148
1397
 
1398
+ def self.new_function(_, loader)
1399
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_boolean, loader) do
1400
+ dispatch :from_args do
1401
+ param 'Variant[Undef, Integer, Float, Boolean, String]', :from
1402
+ end
1403
+
1404
+ def from_args(from)
1405
+ from = from.downcase if from.is_a?(String)
1406
+ case from
1407
+ when NilClass
1408
+ throw :undefined_value
1409
+ when Float
1410
+ from != 0.0
1411
+ when Integer
1412
+ from != 0
1413
+ when true, false
1414
+ from
1415
+ when 'false', 'no', 'n'
1416
+ false
1417
+ when 'true', 'yes', 'y'
1418
+ true
1419
+ else
1420
+ raise TypeConversionError.new("Value '#{from}' of type '#{from.class}' cannot be converted to Boolean")
1421
+ end
1422
+ end
1423
+ end
1424
+ end
1425
+
1149
1426
  DEFAULT = PBooleanType.new
1150
1427
 
1151
1428
  protected
@@ -1264,8 +1541,8 @@ class PStructType < PAnyType
1264
1541
  tc = TypeCalculator.singleton
1265
1542
  PIterableType.new(
1266
1543
  PTupleType.new([
1267
- tc.unwrap_single_variant(PVariantType.new(@elements.map {|se| se.key_type })),
1268
- tc.unwrap_single_variant(PVariantType.new(@elements.map {|se| se.value_type }))],
1544
+ PVariantType.maybe_create(@elements.map {|se| se.key_type }),
1545
+ PVariantType.maybe_create(@elements.map {|se| se.value_type })],
1269
1546
  PHashType::KEY_PAIR_TUPLE_SIZE))
1270
1547
  end
1271
1548
  end
@@ -1294,6 +1571,12 @@ class PStructType < PAnyType
1294
1571
  end && matched == o.size
1295
1572
  end
1296
1573
 
1574
+ def new_function(loader)
1575
+ # Simply delegate to Hash type and let the higher level assertion deal with
1576
+ # compliance with the Struct type regarding the produced result.
1577
+ PHashType.new_function(self, loader)
1578
+ end
1579
+
1297
1580
  DEFAULT = PStructType.new(EMPTY_ARRAY)
1298
1581
 
1299
1582
  protected
@@ -1441,7 +1724,7 @@ class PTupleType < PAnyType
1441
1724
  end
1442
1725
 
1443
1726
  def iterable_type(guard = nil)
1444
- PIterableType.new(TypeCalculator.singleton.unwrap_single_variant(PVariantType.new(types)))
1727
+ PIterableType.new(PVariantType.maybe_create(types))
1445
1728
  end
1446
1729
 
1447
1730
  # Returns the number of elements accepted [min, max] in the tuple
@@ -1477,6 +1760,12 @@ class PTupleType < PAnyType
1477
1760
  self.class == o.class && @types == o.types && @size_type == o.size_type
1478
1761
  end
1479
1762
 
1763
+ def new_function(loader)
1764
+ # Simply delegate to Array type and let the higher level assertion deal with
1765
+ # compliance with the Tuple type regarding the produced result.
1766
+ PArrayType.new_function(self, loader)
1767
+ end
1768
+
1480
1769
  DATA = PTupleType.new([PDataType::DEFAULT], PCollectionType::DEFAULT_SIZE)
1481
1770
  DEFAULT = PTupleType.new(EMPTY_ARRAY)
1482
1771
 
@@ -1666,6 +1955,44 @@ class PArrayType < PCollectionType
1666
1955
  size_t.nil? || size_t.instance?(o.size, guard)
1667
1956
  end
1668
1957
 
1958
+ # Returns a new function that produces an Array
1959
+ #
1960
+ def self.new_function(_, loader)
1961
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_array, loader) do
1962
+
1963
+ dispatch :from_args do
1964
+ param 'Any', :from
1965
+ optional_param 'Boolean', :wrap
1966
+ end
1967
+
1968
+ def from_args(from, wrap = false)
1969
+ case from
1970
+ when NilClass
1971
+ if wrap
1972
+ [nil]
1973
+ else
1974
+ throw :undefined_value
1975
+ end
1976
+ when Array
1977
+ from
1978
+ when Hash
1979
+ wrap ? [from] : from.to_a
1980
+ else
1981
+ if wrap
1982
+ [from]
1983
+ else
1984
+ if PIterableType::DEFAULT.instance?(from)
1985
+ Iterable.on(from).to_a
1986
+ else
1987
+ t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
1988
+ raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Array")
1989
+ end
1990
+ end
1991
+ end
1992
+ end
1993
+ end
1994
+ end
1995
+
1669
1996
  DATA = PArrayType.new(PDataType::DEFAULT, DEFAULT_SIZE)
1670
1997
  DEFAULT = PArrayType.new(nil)
1671
1998
  EMPTY = PArrayType.new(PUnitType::DEFAULT, ZERO_SIZE)
@@ -1716,9 +2043,10 @@ class PHashType < PCollectionType
1716
2043
 
1717
2044
  def initialize(key_type, value_type, size_type = nil)
1718
2045
  super(value_type, size_type)
1719
- @key_type = key_type
1720
- if has_empty_range? && !@key_type.is_a?(PUnitType)
1721
- raise ArgumentError, 'An empty hash may not specify a key type'
2046
+ if !size_type.nil? && size_type.from == 0 && size_type.to == 0
2047
+ @key_type = PUnitType::DEFAULT
2048
+ else
2049
+ @key_type = key_type
1722
2050
  end
1723
2051
  end
1724
2052
 
@@ -1788,6 +2116,53 @@ class PHashType < PCollectionType
1788
2116
  self == EMPTY
1789
2117
  end
1790
2118
 
2119
+ # Returns a new function that produces a Hash
2120
+ #
2121
+ def self.new_function(_, loader)
2122
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_hash, loader) do
2123
+ local_types do
2124
+ type 'KeyValueArray = Array[Tuple[Any,Any],1]'
2125
+ end
2126
+
2127
+ dispatch :from_tuples do
2128
+ param 'KeyValueArray', :from
2129
+ end
2130
+
2131
+ dispatch :from_array do
2132
+ param 'Any', :from
2133
+ end
2134
+
2135
+ def from_tuples(tuple_array)
2136
+ Hash[tuple_array]
2137
+ end
2138
+
2139
+ def from_array(from)
2140
+ case from
2141
+ when NilClass
2142
+ throw :undefined_value
2143
+ when Array
2144
+ if from.size == 0
2145
+ {}
2146
+ else
2147
+ unless from.size % 2 == 0
2148
+ raise TypeConversionError.new("odd number of arguments for Hash")
2149
+ end
2150
+ Hash[*from]
2151
+ end
2152
+ when Hash
2153
+ from
2154
+ else
2155
+ if PIterableType::DEFAULT.instance?(from)
2156
+ Hash[*Iterable.on(from).to_a]
2157
+ else
2158
+ t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
2159
+ raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Hash")
2160
+ end
2161
+ end
2162
+ end
2163
+ end
2164
+ end
2165
+
1791
2166
  DEFAULT = PHashType.new(nil, nil)
1792
2167
  KEY_PAIR_TUPLE_SIZE = PIntegerType.new(2,2)
1793
2168
  DEFAULT_KEY_PAIR_TUPLE = PTupleType.new([PUnitType::DEFAULT, PUnitType::DEFAULT], KEY_PAIR_TUPLE_SIZE)
@@ -1826,9 +2201,21 @@ class PVariantType < PAnyType
1826
2201
 
1827
2202
  attr_reader :types
1828
2203
 
2204
+ # Checks if the number of unique types in the given array is greater than one, and if so
2205
+ # creates a Variant with those types and returns it. If only one unique type is found,
2206
+ # that type is instead returned.
2207
+ #
2208
+ # @param types [Array<PAnyType>] the variants
2209
+ # @return [PAnyType] the resulting type
2210
+ # @api public
2211
+ def self.maybe_create(types)
2212
+ types = types.uniq
2213
+ types.size == 1 ? types[0] : new(types)
2214
+ end
2215
+
1829
2216
  # @param types [Array[PAnyType]] the variants
1830
2217
  def initialize(types)
1831
- @types = types.uniq.freeze
2218
+ @types = types.freeze
1832
2219
  end
1833
2220
 
1834
2221
  def accept(visitor, guard)
@@ -1848,7 +2235,7 @@ class PVariantType < PAnyType
1848
2235
  if self == DEFAULT || self == DATA
1849
2236
  self
1850
2237
  else
1851
- alter_type_array(@types, :generalize) { |altered| PVariantType.new(altered) }
2238
+ alter_type_array(@types, :generalize) { |altered| PVariantType.maybe_create(altered) }
1852
2239
  end
1853
2240
  end
1854
2241
 
@@ -1869,7 +2256,7 @@ class PVariantType < PAnyType
1869
2256
  types[0]
1870
2257
  elsif types.any? { |t| t.is_a?(PUndefType) }
1871
2258
  # Undef entry present. Use an OptionalType with a normalized Variant of all types that are not Undef
1872
- POptionalType.new(PVariantType.new(types.reject { |ot| ot.is_a?(PUndefType) }).normalize(guard)).normalize(guard)
2259
+ POptionalType.new(PVariantType.maybe_create(types.reject { |ot| ot.is_a?(PUndefType) }).normalize(guard)).normalize(guard)
1873
2260
  else
1874
2261
  # Merge all variants into this one
1875
2262
  types = types.map do |t|
@@ -1889,11 +2276,12 @@ class PVariantType < PAnyType
1889
2276
  types = merge_patterns(types)
1890
2277
  types = merge_int_ranges(types)
1891
2278
  types = merge_float_ranges(types)
2279
+ types = merge_version_ranges(types)
1892
2280
 
1893
2281
  if types.size == 1
1894
2282
  types[0]
1895
2283
  else
1896
- modified || types.size != size_before_merge ? PVariantType.new(types) : self
2284
+ modified || types.size != size_before_merge ? PVariantType.maybe_create(types) : self
1897
2285
  end
1898
2286
  end
1899
2287
  end
@@ -1965,7 +2353,7 @@ class PVariantType < PAnyType
1965
2353
  optionals = parts[0]
1966
2354
  if optionals.size > 1
1967
2355
  others = parts[1]
1968
- others << POptionalType.new(PVariantType.new(optionals.map { |optional| optional.type }).normalize)
2356
+ others << POptionalType.new(PVariantType.maybe_create(optionals.map { |optional| optional.type }).normalize)
1969
2357
  array = others
1970
2358
  end
1971
2359
  end
@@ -1979,7 +2367,7 @@ class PVariantType < PAnyType
1979
2367
  not_undefs = parts[0]
1980
2368
  if not_undefs.size > 1
1981
2369
  others = parts[1]
1982
- others << PNotUndefType.new(PVariantType.new(not_undefs.map { |not_undef| not_undef.type }).normalize)
2370
+ others << PNotUndefType.new(PVariantType.maybe_create(not_undefs.map { |not_undef| not_undef.type }).normalize)
1983
2371
  array = others
1984
2372
  end
1985
2373
  end
@@ -2033,6 +2421,15 @@ class PVariantType < PAnyType
2033
2421
  array
2034
2422
  end
2035
2423
 
2424
+ def merge_version_ranges(array)
2425
+ if array.size > 1
2426
+ parts = array.partition {|t| t.is_a?(PSemVerType) }
2427
+ ranges = parts[0]
2428
+ array = [PSemVerType.new(*ranges.map(&:ranges).flatten)] + parts[1] if ranges.size > 1
2429
+ end
2430
+ array
2431
+ end
2432
+
2036
2433
  # @api private
2037
2434
  def merge_ranges(ranges)
2038
2435
  result = []
@@ -2054,58 +2451,6 @@ class PVariantType < PAnyType
2054
2451
  end
2055
2452
  end
2056
2453
 
2057
- # @api public
2058
- #
2059
- class PRuntimeType < PAnyType
2060
- attr_reader :runtime, :runtime_type_name
2061
-
2062
- def initialize(runtime, runtime_type_name = nil)
2063
- @runtime = runtime
2064
- @runtime_type_name = runtime_type_name
2065
- end
2066
-
2067
- def hash
2068
- @runtime.hash ^ @runtime_type_name.hash
2069
- end
2070
-
2071
- def eql?(o)
2072
- self.class == o.class && @runtime == o.runtime && @runtime_type_name == o.runtime_type_name
2073
- end
2074
-
2075
- def instance?(o, guard = nil)
2076
- assignable?(TypeCalculator.infer(o), guard)
2077
- end
2078
-
2079
- def iterable?(guard = nil)
2080
- c = class_from_string(@runtime_type_name)
2081
- c.nil? ? false : c < Iterable
2082
- end
2083
-
2084
- def iterable_type(guard = nil)
2085
- iterable?(guard) ? PIterableType.new(self) : nil
2086
- end
2087
-
2088
- DEFAULT = PRuntimeType.new(nil)
2089
-
2090
- protected
2091
-
2092
- # Assignable if o's has the same runtime and the runtime name resolves to
2093
- # a class that is the same or subclass of t1's resolved runtime type name
2094
- # @api private
2095
- def _assignable?(o, guard)
2096
- return false unless o.is_a?(PRuntimeType)
2097
- return false unless @runtime == o.runtime
2098
- return true if @runtime_type_name.nil? # t1 is wider
2099
- return false if o.runtime_type_name.nil? # t1 not nil, so o can not be wider
2100
-
2101
- # NOTE: This only supports Ruby, must change when/if the set of runtimes is expanded
2102
- c1 = class_from_string(@runtime_type_name)
2103
- c2 = class_from_string(o.runtime_type_name)
2104
- return false unless c1.is_a?(Module) && c2.is_a?(Module)
2105
- !!(c2 <= c1)
2106
- end
2107
- end
2108
-
2109
2454
  # Abstract representation of a type that can be placed in a Catalog.
2110
2455
  # @api public
2111
2456
  #
@@ -2130,6 +2475,8 @@ end
2130
2475
  class PHostClassType < PCatalogEntryType
2131
2476
  attr_reader :class_name
2132
2477
 
2478
+ NAME = 'Class'.freeze
2479
+
2133
2480
  def initialize(class_name)
2134
2481
  @class_name = class_name
2135
2482
  end
@@ -2141,6 +2488,10 @@ class PHostClassType < PCatalogEntryType
2141
2488
  self.class == o.class && @class_name == o.class_name
2142
2489
  end
2143
2490
 
2491
+ def simple_name
2492
+ NAME
2493
+ end
2494
+
2144
2495
  DEFAULT = PHostClassType.new(nil)
2145
2496
 
2146
2497
  protected
@@ -2159,19 +2510,20 @@ end
2159
2510
  # @api public
2160
2511
  #
2161
2512
  class PResourceType < PCatalogEntryType
2162
- attr_reader :type_name, :title
2513
+ attr_reader :type_name, :title, :downcased_name
2163
2514
 
2164
2515
  def initialize(type_name, title = nil)
2165
- @type_name = type_name
2166
- @title = title
2516
+ @type_name = type_name.freeze
2517
+ @title = title.freeze
2518
+ @downcased_name = type_name.nil? ? nil : @type_name.downcase.freeze
2167
2519
  end
2168
2520
 
2169
- def hash
2170
- @type_name.hash ^ @title.hash
2521
+ def eql?(o)
2522
+ self.class == o.class && @downcased_name == o.downcased_name && @title == o.title
2171
2523
  end
2172
2524
 
2173
- def eql?(o)
2174
- self.class == o.class && @type_name == o.type_name && @title == o.title
2525
+ def hash
2526
+ @downcased_name.hash ^ @title.hash
2175
2527
  end
2176
2528
 
2177
2529
  DEFAULT = PResourceType.new(nil)
@@ -2180,11 +2532,7 @@ class PResourceType < PCatalogEntryType
2180
2532
 
2181
2533
  # @api private
2182
2534
  def _assignable?(o, guard)
2183
- return false unless o.is_a?(PResourceType)
2184
- return true if @type_name.nil?
2185
- return false if @type_name != o.type_name
2186
- return true if @title.nil?
2187
- @title == o.title
2535
+ o.is_a?(PResourceType) && (@downcased_name.nil? || @downcased_name == o.downcased_name && (@title.nil? || @title == o.title))
2188
2536
  end
2189
2537
  end
2190
2538
 
@@ -2222,6 +2570,10 @@ class POptionalType < PTypeWithContainedType
2222
2570
  end
2223
2571
  end
2224
2572
 
2573
+ def new_function(loader)
2574
+ optional_type.new_function(loader)
2575
+ end
2576
+
2225
2577
  DEFAULT = POptionalType.new(nil)
2226
2578
 
2227
2579
  protected
@@ -2239,11 +2591,10 @@ class POptionalType < PTypeWithContainedType
2239
2591
  end
2240
2592
 
2241
2593
  class PTypeReferenceType < PAnyType
2242
- attr_reader :name, :parameters
2594
+ attr_reader :type_string
2243
2595
 
2244
- def initialize(name, parameters = nil)
2245
- @name = name
2246
- @parameters = parameters.nil? ? EMPTY_ARRAY : parameters
2596
+ def initialize(type_string)
2597
+ @type_string = type_string
2247
2598
  end
2248
2599
 
2249
2600
  def callable?(args)
@@ -2255,11 +2606,15 @@ class PTypeReferenceType < PAnyType
2255
2606
  end
2256
2607
 
2257
2608
  def hash
2258
- @name.hash ^ @parameters.hash
2609
+ @type_string.hash
2259
2610
  end
2260
2611
 
2261
2612
  def eql?(o)
2262
- super && o.name == @name && o.parameters == @parameters
2613
+ super && o.type_string == @type_string
2614
+ end
2615
+
2616
+ def resolve(type_parser, loader)
2617
+ type_parser.parse(@type_string, loader)
2263
2618
  end
2264
2619
 
2265
2620
  protected
@@ -2278,6 +2633,7 @@ end
2278
2633
  # might contain self recursion. Whether or not that is the case is computed and remembered when the alias
2279
2634
  # is resolved since guarding against self recursive constructs is relatively expensive.
2280
2635
  #
2636
+ # @api public
2281
2637
  class PTypeAliasType < PAnyType
2282
2638
  attr_reader :name
2283
2639
 
@@ -2313,6 +2669,10 @@ class PTypeAliasType < PAnyType
2313
2669
  guarded_recursion(guard, false) { |g| resolved_type.callable_args?(callable, g) }
2314
2670
  end
2315
2671
 
2672
+ def check_self_recursion(originator)
2673
+ resolved_type.check_self_recursion(originator) unless originator.equal?(self)
2674
+ end
2675
+
2316
2676
  def kind_of_callable?(optional=true, guard = nil)
2317
2677
  guarded_recursion(guard, false) { |g| resolved_type.kind_of_callable?(optional, g) }
2318
2678
  end
@@ -2406,6 +2766,10 @@ class PTypeAliasType < PAnyType
2406
2766
  @resolved_type = nil
2407
2767
  raise
2408
2768
  end
2769
+ else
2770
+ # An alias may appoint an Object type that isn't resolved yet. The default type
2771
+ # reference is used to prevent endless recursion and should not be resolved here.
2772
+ @resolved_type.resolve(type_parser, loader) unless @resolved_type.equal?(PTypeReferenceType::DEFAULT)
2409
2773
  end
2410
2774
  self
2411
2775
  end
@@ -2416,7 +2780,7 @@ class PTypeAliasType < PAnyType
2416
2780
 
2417
2781
  def accept(visitor, guard)
2418
2782
  guarded_recursion(guard, nil) do |g|
2419
- super
2783
+ super(visitor, g)
2420
2784
  resolved_type.accept(visitor, g)
2421
2785
  end
2422
2786
  end
@@ -2459,6 +2823,10 @@ class PTypeAliasType < PAnyType
2459
2823
  resolved_type.assignable?(o, guard)
2460
2824
  end
2461
2825
 
2826
+ def new_function(loader)
2827
+ resolved_type.new_function(loader)
2828
+ end
2829
+
2462
2830
  private
2463
2831
 
2464
2832
  def guarded_recursion(guard, dflt)
@@ -2484,7 +2852,7 @@ class PTypeAliasType < PAnyType
2484
2852
  if real_types.size == 1
2485
2853
  @resolved_type = real_types[0]
2486
2854
  else
2487
- @resolved_type = PVariantType.new(real_types)
2855
+ @resolved_type = PVariantType.maybe_create(real_types)
2488
2856
  end
2489
2857
  # Drop self recursion status in case it's not self recursive anymore
2490
2858
  guard = RecursionGuard.new
@@ -2492,9 +2860,19 @@ class PTypeAliasType < PAnyType
2492
2860
  @self_recursion = guard.recursive_this?(self)
2493
2861
  end
2494
2862
  end
2863
+ @resolved_type.check_self_recursion(self) if @self_recursion
2495
2864
  end
2496
2865
 
2497
2866
  DEFAULT = PTypeAliasType.new('UnresolvedAlias', nil, PTypeReferenceType::DEFAULT)
2498
2867
  end
2499
2868
  end
2500
2869
  end
2870
+
2871
+ require 'puppet/pops/pcore'
2872
+
2873
+ require_relative 'puppet_object'
2874
+ require_relative 'p_object_type'
2875
+ require_relative 'p_runtime_type'
2876
+ require_relative 'p_sem_ver_type'
2877
+ require_relative 'p_sem_ver_range_type'
2878
+ require_relative 'implementation_registry'