puppet 4.2.3 → 4.3.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.
- data/Gemfile +3 -0
- data/README.md +1 -1
- data/ext/debian/puppet.init +0 -1
- data/ext/debian/puppet.logrotate +14 -5
- data/ext/osx/puppet.plist +0 -2
- data/ext/redhat/client.init +13 -5
- data/ext/redhat/logrotate +15 -3
- data/ext/redhat/puppet.spec.erb +5 -1
- data/ext/redhat/server.init +1 -1
- data/ext/systemd/puppet.service +1 -0
- data/lib/puppet.rb +12 -0
- data/lib/puppet/agent.rb +4 -4
- data/lib/puppet/agent/locker.rb +11 -2
- data/lib/puppet/application/agent.rb +5 -1
- data/lib/puppet/application/apply.rb +4 -0
- data/lib/puppet/application/filebucket.rb +78 -4
- data/lib/puppet/application/lookup.rb +356 -0
- data/lib/puppet/application/master.rb +3 -0
- data/lib/puppet/configurer.rb +9 -5
- data/lib/puppet/context.rb +16 -1
- data/lib/puppet/context/trusted_information.rb +21 -1
- data/lib/puppet/daemon.rb +17 -13
- data/lib/puppet/data_binding.rb +4 -2
- data/lib/puppet/data_providers.rb +12 -13
- data/lib/puppet/data_providers/data_adapter.rb +7 -68
- data/lib/puppet/data_providers/data_function_support.rb +5 -26
- data/lib/puppet/data_providers/function_env_data_provider.rb +0 -10
- data/lib/puppet/data_providers/function_module_data_provider.rb +0 -22
- data/lib/puppet/data_providers/hiera_config.rb +106 -0
- data/lib/puppet/data_providers/hiera_env_data_provider.rb +18 -0
- data/lib/puppet/data_providers/hiera_interpolate.rb +97 -0
- data/lib/puppet/data_providers/hiera_module_data_provider.rb +23 -0
- data/lib/puppet/data_providers/hiera_support.rb +37 -0
- data/lib/puppet/data_providers/json_data_provider_factory.rb +31 -0
- data/lib/puppet/data_providers/lookup_adapter.rb +200 -0
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +32 -0
- data/lib/puppet/defaults.rb +12 -2
- data/lib/puppet/error.rb +4 -0
- data/lib/puppet/face/module/changes.rb +2 -1
- data/lib/puppet/feature/cfacter.rb +1 -0
- data/lib/puppet/file_bucket/dipper.rb +58 -2
- data/lib/puppet/functions.rb +2 -4
- data/lib/puppet/functions/assert_type.rb +48 -12
- data/lib/puppet/functions/defined.rb +79 -48
- data/lib/puppet/functions/each.rb +85 -27
- data/lib/puppet/functions/filter.rb +58 -23
- data/lib/puppet/functions/hiera.rb +76 -3
- data/lib/puppet/functions/hiera_array.rb +65 -3
- data/lib/puppet/functions/hiera_hash.rb +74 -2
- data/lib/puppet/functions/hiera_include.rb +75 -2
- data/lib/puppet/functions/lookup.rb +19 -17
- data/lib/puppet/functions/map.rb +56 -21
- data/lib/puppet/functions/match.rb +29 -12
- data/lib/puppet/functions/reduce.rb +95 -58
- data/lib/puppet/functions/versioncmp.rb +36 -0
- data/lib/puppet/functions/with.rb +15 -7
- data/lib/puppet/indirector/catalog/compiler.rb +3 -3
- data/lib/puppet/indirector/catalog/static_compiler.rb +46 -30
- data/lib/puppet/indirector/data_binding/none.rb +4 -1
- data/lib/puppet/indirector/file_bucket_file/file.rb +58 -1
- data/lib/puppet/indirector/hiera.rb +4 -0
- data/lib/puppet/indirector/json.rb +1 -1
- data/lib/puppet/indirector/msgpack.rb +1 -1
- data/lib/puppet/indirector/request.rb +7 -8
- data/lib/puppet/indirector/resource_type/parser.rb +5 -3
- data/lib/puppet/info_service.rb +7 -0
- data/lib/puppet/info_service/class_information_service.rb +111 -0
- data/lib/puppet/module_tool/metadata.rb +32 -9
- data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +42 -38
- data/lib/puppet/network/authconfig.rb +21 -1
- data/lib/puppet/network/authorization.rb +8 -1
- data/lib/puppet/network/http/api/master/v3.rb +7 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +59 -0
- data/lib/puppet/node/environment.rb +9 -2
- data/lib/puppet/parser.rb +3 -0
- data/lib/puppet/parser/ast/pops_bridge.rb +39 -1
- data/lib/puppet/parser/compiler.rb +302 -12
- data/lib/puppet/parser/compiler/catalog_validator.rb +33 -0
- data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +64 -0
- data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +38 -0
- data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +20 -0
- data/lib/puppet/parser/environment_compiler.rb +165 -0
- data/lib/puppet/parser/functions/assert_type.rb +46 -16
- data/lib/puppet/parser/functions/defined.rb +105 -68
- data/lib/puppet/parser/functions/each.rb +85 -27
- data/lib/puppet/parser/functions/filter.rb +59 -23
- data/lib/puppet/parser/functions/hiera.rb +83 -27
- data/lib/puppet/parser/functions/hiera_array.rb +71 -28
- data/lib/puppet/parser/functions/hiera_hash.rb +81 -30
- data/lib/puppet/parser/functions/hiera_include.rb +81 -40
- data/lib/puppet/parser/functions/map.rb +55 -20
- data/lib/puppet/parser/functions/match.rb +27 -12
- data/lib/puppet/parser/functions/reduce.rb +97 -60
- data/lib/puppet/parser/functions/with.rb +16 -8
- data/lib/puppet/parser/resource.rb +98 -19
- data/lib/puppet/plugins/configuration.rb +3 -2
- data/lib/puppet/plugins/data_providers.rb +12 -60
- data/lib/puppet/plugins/data_providers/data_provider.rb +283 -0
- data/lib/puppet/plugins/data_providers/registry.rb +84 -0
- data/lib/puppet/pops.rb +19 -17
- data/lib/puppet/pops/adapters.rb +12 -0
- data/lib/puppet/pops/binder/binder.rb +2 -2
- data/lib/puppet/pops/binder/bindings_checker.rb +1 -1
- data/lib/puppet/pops/binder/bindings_label_provider.rb +3 -1
- data/lib/puppet/pops/binder/bindings_loader.rb +6 -2
- data/lib/puppet/pops/binder/bindings_model_meta.rb +2 -2
- data/lib/puppet/pops/binder/config/binder_config.rb +1 -1
- data/lib/puppet/pops/binder/injector.rb +4 -4
- data/lib/puppet/pops/binder/key_factory.rb +3 -9
- data/lib/puppet/pops/binder/scheme_handler/module_scheme.rb +68 -9
- data/lib/puppet/pops/evaluator/access_operator.rb +27 -60
- data/lib/puppet/pops/evaluator/closure.rb +8 -8
- data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +1 -1
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -5
- data/lib/puppet/pops/evaluator/literal_evaluator.rb +87 -0
- data/lib/puppet/pops/evaluator/relationship_operator.rb +7 -1
- data/lib/puppet/pops/functions/dispatcher.rb +3 -3
- data/lib/puppet/pops/issues.rb +1 -1
- data/lib/puppet/pops/label_provider.rb +1 -1
- data/lib/puppet/pops/lookup.rb +25 -47
- data/lib/puppet/pops/lookup/explainer.rb +402 -0
- data/lib/puppet/pops/lookup/invocation.rb +117 -0
- data/lib/puppet/pops/merge_strategy.rb +73 -5
- data/lib/puppet/pops/model/factory.rb +34 -0
- data/lib/puppet/pops/model/model_label_provider.rb +10 -1
- data/lib/puppet/pops/model/model_meta.rb +15 -0
- data/lib/puppet/pops/model/model_tree_dumper.rb +18 -0
- data/lib/puppet/pops/parser/code_merger.rb +13 -1
- data/lib/puppet/pops/parser/egrammar.ra +56 -3
- data/lib/puppet/pops/parser/eparser.rb +1549 -1352
- data/lib/puppet/pops/parser/lexer2.rb +31 -6
- data/lib/puppet/pops/parser/locator.rb +1 -1
- data/lib/puppet/pops/parser/parser_support.rb +25 -13
- data/lib/puppet/pops/types/enumeration.rb +1 -2
- data/lib/puppet/pops/types/type_asserter.rb +16 -15
- data/lib/puppet/pops/types/type_assertion_error.rb +1 -0
- data/lib/puppet/pops/types/type_calculator.rb +171 -1020
- data/lib/puppet/pops/types/type_factory.rb +87 -148
- data/lib/puppet/pops/types/type_mismatch_describer.rb +743 -0
- data/lib/puppet/pops/types/type_parser.rb +116 -127
- data/lib/puppet/pops/types/types.rb +1394 -255
- data/lib/puppet/pops/types/types_meta.rb +0 -234
- data/lib/puppet/pops/validation.rb +7 -2
- data/lib/puppet/pops/validation/checker4_0.rb +28 -0
- data/lib/puppet/provider/augeas/augeas.rb +50 -0
- data/lib/puppet/provider/group/directoryservice.rb +10 -0
- data/lib/puppet/provider/package/dnf.rb +41 -0
- data/lib/puppet/provider/package/gem.rb +7 -2
- data/lib/puppet/provider/package/rpm.rb +1 -0
- data/lib/puppet/provider/package/windows/exe_package.rb +10 -8
- data/lib/puppet/provider/package/windows/msi_package.rb +4 -3
- data/lib/puppet/provider/package/windows/package.rb +9 -1
- data/lib/puppet/provider/package/yum.rb +14 -9
- data/lib/puppet/provider/service/bsd.rb +1 -1
- data/lib/puppet/provider/service/debian.rb +21 -0
- data/lib/puppet/provider/service/init.rb +6 -0
- data/lib/puppet/provider/service/rcng.rb +51 -0
- data/lib/puppet/provider/service/redhat.rb +2 -1
- data/lib/puppet/provider/service/smf.rb +43 -2
- data/lib/puppet/provider/service/src.rb +27 -0
- data/lib/puppet/provider/service/systemd.rb +15 -3
- data/lib/puppet/provider/sshkey/parsed.rb +19 -9
- data/lib/puppet/reference/report.rb +9 -12
- data/lib/puppet/reports.rb +5 -1
- data/lib/puppet/resource.rb +50 -73
- data/lib/puppet/resource/capability_finder.rb +95 -0
- data/lib/puppet/resource/catalog.rb +47 -7
- data/lib/puppet/resource/status.rb +0 -2
- data/lib/puppet/resource/type.rb +238 -44
- data/lib/puppet/resource/type_collection.rb +60 -2
- data/lib/puppet/settings.rb +2 -2
- data/lib/puppet/ssl/certificate_authority/interface.rb +2 -2
- data/lib/puppet/ssl/oids.rb +9 -1
- data/lib/puppet/transaction.rb +4 -1
- data/lib/puppet/transaction/additional_resource_generator.rb +71 -8
- data/lib/puppet/transaction/resource_harness.rb +9 -4
- data/lib/puppet/type.rb +74 -3
- data/lib/puppet/type/augeas.rb +8 -0
- data/lib/puppet/type/file/source.rb +14 -12
- data/lib/puppet/type/user.rb +4 -2
- data/lib/puppet/util/windows/security.rb +4 -1
- data/lib/puppet/util/windows/taskscheduler.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +3 -0
- data/spec/fixtures/unit/application/environments/production/environment.conf +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/data/bad.json +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/manifests/site.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/data/bad.yaml +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/manifests/site.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/data/common.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/manifests/site.pp +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/data/common.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/manifests/init.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/metadata.json +9 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/first.json +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/name.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/second.json +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/single.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data2/single.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/hiera.yaml +18 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_env_config/manifests/site.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/data/common.yaml +46 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/manifests/site.pp +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/data/common.yaml +30 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/manifests/init.pp +13 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/metadata.json +9 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/manifests/site.pp +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/first.json +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/name.yaml +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/second.json +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/single.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data2/single.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/hiera.yaml +18 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/manifests/init.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/metadata.json +9 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_env_data.rb +1 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_module_data.rb +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/data/first.json +3 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/hiera.yaml +8 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/manifests/init.pp +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/lib/puppet/functions/meta/data.rb +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/manifests/init.pp +3 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet/bindings/metawcp/default.rb +10 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet_x/thallgren/sample_module_data.rb +23 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/manifests/init.pp +3 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/metadata.json +9 -0
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-security.txt +184 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_get/should_yield_to_the_block.yml +24 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_head/should_yield_to_the_block.yml +24 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_post/should_yield_to_the_block.yml +24 -0
- data/spec/integration/data_binding_spec.rb +229 -0
- data/spec/integration/file_bucket/file_spec.rb +2 -2
- data/spec/integration/parser/compiler_spec.rb +23 -19
- data/spec/integration/parser/resource_expressions_spec.rb +4 -4
- data/spec/integration/parser/undef_param_spec.rb +1 -1
- data/spec/integration/resource/catalog_spec.rb +1 -1
- data/spec/integration/type/package_spec.rb +2 -0
- data/spec/integration/util/windows/security_spec.rb +18 -0
- data/spec/lib/matchers/include_in_order.rb +2 -2
- data/spec/shared_behaviours/iterative_functions.rb +8 -8
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/agent/locker_spec.rb +4 -4
- data/spec/unit/agent_spec.rb +0 -8
- data/spec/unit/application/agent_spec.rb +5 -0
- data/spec/unit/application/apply_spec.rb +8 -0
- data/spec/unit/application/filebucket_spec.rb +87 -1
- data/spec/unit/application/lookup_spec.rb +195 -0
- data/spec/unit/appmgmt_spec.rb +657 -0
- data/spec/unit/capability_spec.rb +414 -0
- data/spec/unit/configurer_spec.rb +7 -1
- data/spec/unit/context/trusted_information_spec.rb +24 -1
- data/spec/unit/daemon_spec.rb +18 -8
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +201 -0
- data/spec/unit/file_bucket/dipper_spec.rb +210 -1
- data/spec/unit/functions/assert_type_spec.rb +5 -7
- data/spec/unit/functions/defined_spec.rb +2 -2
- data/spec/unit/functions/epp_spec.rb +2 -2
- data/spec/unit/functions/lookup_spec.rb +200 -9
- data/spec/unit/functions/regsubst_spec.rb +17 -8
- data/spec/unit/functions/scanf_spec.rb +1 -1
- data/spec/unit/functions/split_spec.rb +2 -2
- data/spec/unit/functions/versioncmp_spec.rb +36 -0
- data/spec/unit/functions4_spec.rb +58 -72
- data/spec/unit/indirector/catalog/compiler_spec.rb +28 -8
- data/spec/unit/indirector/catalog/static_compiler_spec.rb +38 -20
- data/spec/unit/indirector/data_binding/none_spec.rb +2 -2
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +52 -1
- data/spec/unit/indirector/request_spec.rb +8 -8
- data/spec/unit/info_service_spec.rb +236 -0
- data/spec/unit/module_tool/metadata_spec.rb +31 -2
- data/spec/unit/network/authconfig_spec.rb +62 -32
- data/spec/unit/network/authorization_spec.rb +30 -2
- data/spec/unit/network/http/connection_spec.rb +14 -19
- data/spec/unit/parser/compiler_spec.rb +86 -2
- data/spec/unit/parser/functions/create_resources_spec.rb +1 -1
- data/spec/unit/parser/resource_spec.rb +2 -20
- data/spec/unit/pops/binder/config/binder_config_spec.rb +1 -1
- data/spec/unit/pops/binder/injector_spec.rb +3 -3
- data/spec/unit/pops/evaluator/access_ops_spec.rb +13 -11
- data/spec/unit/pops/evaluator/basic_expressions_spec.rb +1 -2
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +19 -11
- data/spec/unit/pops/evaluator/literal_evaluator_spec.rb +43 -0
- data/spec/unit/pops/label_provider_spec.rb +5 -1
- data/spec/unit/pops/parser/lexer2_spec.rb +33 -7
- data/spec/unit/pops/parser/parse_application_spec.rb +40 -0
- data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +4 -0
- data/spec/unit/pops/parser/parse_capabilities_spec.rb +47 -0
- data/spec/unit/pops/parser/parse_site_spec.rb +38 -0
- data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
- data/spec/unit/pops/parser/parser_spec.rb +18 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +427 -444
- data/spec/unit/pops/types/type_factory_spec.rb +12 -12
- data/spec/unit/pops/types/type_parser_spec.rb +7 -12
- data/spec/unit/pops/validator/validator_spec.rb +25 -0
- data/spec/unit/provider/augeas/augeas_spec.rb +50 -0
- data/spec/unit/provider/group/directoryservice_spec.rb +33 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +3 -0
- data/spec/unit/provider/package/dnf_spec.rb +92 -0
- data/spec/unit/provider/package/gem_spec.rb +7 -0
- data/spec/unit/provider/package/rpm_spec.rb +25 -2
- data/spec/unit/provider/package/windows/package_spec.rb +41 -0
- data/spec/unit/provider/package/yum_spec.rb +21 -13
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +10 -0
- data/spec/unit/provider/service/debian_spec.rb +27 -0
- data/spec/unit/provider/service/rcng_spec.rb +41 -0
- data/spec/unit/provider/service/redhat_spec.rb +8 -1
- data/spec/unit/provider/service/smf_spec.rb +30 -5
- data/spec/unit/provider/service/src_spec.rb +19 -4
- data/spec/unit/provider/service/systemd_spec.rb +78 -29
- data/spec/unit/provider/sshkey/parsed_spec.rb +23 -0
- data/spec/unit/reports_spec.rb +10 -0
- data/spec/unit/resource/capability_finder_spec.rb +56 -0
- data/spec/unit/resource/catalog_spec.rb +31 -8
- data/spec/unit/resource/type_collection_spec.rb +23 -2
- data/spec/unit/resource/type_spec.rb +1 -1
- data/spec/unit/resource_spec.rb +22 -4
- data/spec/unit/settings_spec.rb +90 -1
- data/spec/unit/ssl/certificate_authority/interface_spec.rb +4 -3
- data/spec/unit/ssl/oids_spec.rb +8 -0
- data/spec/unit/transaction/additional_resource_generator_spec.rb +78 -5
- data/spec/unit/transaction/report_spec.rb +24 -1
- data/spec/unit/type/package_spec.rb +1 -0
- data/spec/unit/type/user_spec.rb +14 -7
- data/spec/unit/type_spec.rb +1 -1
- metadata +169 -5
- data/lib/puppet/pops/evaluator/callable_mismatch_describer.rb +0 -175
- data/spec/integration/data_binding.rb +0 -104
@@ -11,9 +11,8 @@ class Puppet::Pops::Types::TypeParser
|
|
11
11
|
|
12
12
|
# @api public
|
13
13
|
def initialize
|
14
|
-
@parser = Puppet::Pops::Parser::Parser.new
|
15
|
-
@type_transformer = Puppet::Pops::Visitor.new(nil,
|
16
|
-
@undef_t = TYPES.undef
|
14
|
+
@parser = Puppet::Pops::Parser::Parser.new
|
15
|
+
@type_transformer = Puppet::Pops::Visitor.new(nil, 'interpret', 0, 0)
|
17
16
|
end
|
18
17
|
|
19
18
|
# Produces a *puppet type* based on the given string.
|
@@ -113,87 +112,87 @@ class Puppet::Pops::Types::TypeParser
|
|
113
112
|
# @api private
|
114
113
|
def interpret_QualifiedReference(name_ast)
|
115
114
|
case name_ast.value
|
116
|
-
when
|
115
|
+
when 'integer'
|
117
116
|
TYPES.integer
|
118
117
|
|
119
|
-
when
|
118
|
+
when 'float'
|
120
119
|
TYPES.float
|
121
120
|
|
122
|
-
when
|
121
|
+
when 'numeric'
|
123
122
|
TYPES.numeric
|
124
123
|
|
125
|
-
when
|
124
|
+
when 'string'
|
126
125
|
TYPES.string
|
127
126
|
|
128
|
-
when
|
127
|
+
when 'enum'
|
129
128
|
TYPES.enum
|
130
129
|
|
131
|
-
when
|
130
|
+
when 'boolean'
|
132
131
|
TYPES.boolean
|
133
132
|
|
134
|
-
when
|
133
|
+
when 'pattern'
|
135
134
|
TYPES.pattern
|
136
135
|
|
137
|
-
when
|
136
|
+
when 'regexp'
|
138
137
|
TYPES.regexp
|
139
138
|
|
140
|
-
when
|
139
|
+
when 'data'
|
141
140
|
TYPES.data
|
142
141
|
|
143
|
-
when
|
142
|
+
when 'array'
|
144
143
|
TYPES.array_of_data
|
145
144
|
|
146
|
-
when
|
145
|
+
when 'hash'
|
147
146
|
TYPES.hash_of_data
|
148
147
|
|
149
|
-
when
|
150
|
-
TYPES.host_class
|
148
|
+
when 'class'
|
149
|
+
TYPES.host_class
|
151
150
|
|
152
|
-
when
|
153
|
-
TYPES.resource
|
151
|
+
when 'resource'
|
152
|
+
TYPES.resource
|
154
153
|
|
155
|
-
when
|
156
|
-
TYPES.collection
|
154
|
+
when 'collection'
|
155
|
+
TYPES.collection
|
157
156
|
|
158
|
-
when
|
159
|
-
TYPES.scalar
|
157
|
+
when 'scalar'
|
158
|
+
TYPES.scalar
|
160
159
|
|
161
|
-
when
|
162
|
-
TYPES.catalog_entry
|
160
|
+
when 'catalogentry'
|
161
|
+
TYPES.catalog_entry
|
163
162
|
|
164
|
-
when
|
165
|
-
TYPES.undef
|
163
|
+
when 'undef'
|
164
|
+
TYPES.undef
|
166
165
|
|
167
|
-
when
|
166
|
+
when 'notundef'
|
168
167
|
TYPES.not_undef()
|
169
168
|
|
170
|
-
when
|
169
|
+
when 'default'
|
171
170
|
TYPES.default()
|
171
|
+
|
172
|
+
when 'any'
|
173
|
+
TYPES.any
|
172
174
|
|
173
|
-
when
|
174
|
-
TYPES.
|
175
|
+
when 'variant'
|
176
|
+
TYPES.variant
|
175
177
|
|
176
|
-
when
|
177
|
-
TYPES.
|
178
|
+
when 'optional'
|
179
|
+
TYPES.optional
|
178
180
|
|
179
|
-
when
|
180
|
-
TYPES.
|
181
|
+
when 'runtime'
|
182
|
+
TYPES.runtime
|
181
183
|
|
182
|
-
when
|
183
|
-
TYPES.
|
184
|
+
when 'type'
|
185
|
+
TYPES.type_type
|
184
186
|
|
185
|
-
when
|
186
|
-
TYPES.
|
187
|
+
when 'tuple'
|
188
|
+
TYPES.tuple
|
187
189
|
|
188
|
-
when
|
189
|
-
TYPES.
|
190
|
+
when 'struct'
|
191
|
+
TYPES.struct
|
190
192
|
|
191
|
-
when
|
192
|
-
TYPES.struct()
|
193
|
-
|
194
|
-
when "callable"
|
193
|
+
when 'callable'
|
195
194
|
# A generic callable as opposed to one that does not accept arguments
|
196
|
-
TYPES.all_callables
|
195
|
+
TYPES.all_callables
|
197
196
|
|
198
197
|
else
|
199
198
|
TYPES.resource(name_ast.value)
|
@@ -209,118 +208,112 @@ class Puppet::Pops::Types::TypeParser
|
|
209
208
|
end
|
210
209
|
|
211
210
|
case parameterized_ast.left_expr.value
|
212
|
-
when
|
211
|
+
when 'array'
|
213
212
|
case parameters.size
|
214
213
|
when 1
|
215
214
|
when 2
|
216
215
|
size_type =
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
216
|
+
if parameters[1].is_a?(Puppet::Pops::Types::PIntegerType)
|
217
|
+
parameters[1]
|
218
|
+
else
|
219
|
+
assert_range_parameter(parameters[1])
|
220
|
+
TYPES.range(parameters[1], :default)
|
221
|
+
end
|
223
222
|
when 3
|
224
223
|
assert_range_parameter(parameters[1])
|
225
224
|
assert_range_parameter(parameters[2])
|
226
225
|
size_type = TYPES.range(parameters[1], parameters[2])
|
227
226
|
else
|
228
|
-
raise_invalid_parameters_error(
|
227
|
+
raise_invalid_parameters_error('Array', '1 to 3', parameters.size)
|
229
228
|
end
|
230
229
|
assert_type(parameters[0])
|
231
|
-
|
232
|
-
t.size_type = size_type if size_type
|
233
|
-
t
|
230
|
+
TYPES.array_of(parameters[0], size_type)
|
234
231
|
|
235
|
-
when
|
236
|
-
|
232
|
+
when 'hash'
|
233
|
+
case parameters.size
|
237
234
|
when 2
|
238
235
|
assert_type(parameters[0])
|
239
236
|
assert_type(parameters[1])
|
240
237
|
TYPES.hash_of(parameters[1], parameters[0])
|
241
238
|
when 3
|
242
239
|
size_type =
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
240
|
+
if parameters[2].is_a?(Puppet::Pops::Types::PIntegerType)
|
241
|
+
parameters[2]
|
242
|
+
else
|
243
|
+
assert_range_parameter(parameters[2])
|
244
|
+
TYPES.range(parameters[2], :default)
|
245
|
+
end
|
249
246
|
assert_type(parameters[0])
|
250
247
|
assert_type(parameters[1])
|
251
|
-
TYPES.hash_of(parameters[1], parameters[0])
|
248
|
+
TYPES.hash_of(parameters[1], parameters[0], size_type)
|
252
249
|
when 4
|
253
250
|
assert_range_parameter(parameters[2])
|
254
251
|
assert_range_parameter(parameters[3])
|
255
|
-
size_type = TYPES.range(parameters[2], parameters[3])
|
256
252
|
assert_type(parameters[0])
|
257
253
|
assert_type(parameters[1])
|
258
|
-
TYPES.hash_of(parameters[1], parameters[0])
|
254
|
+
TYPES.hash_of(parameters[1], parameters[0], TYPES.range(parameters[2], parameters[3]))
|
259
255
|
else
|
260
|
-
raise_invalid_parameters_error(
|
256
|
+
raise_invalid_parameters_error('Hash', '2 to 4', parameters.size)
|
261
257
|
end
|
262
|
-
result.size_type = size_type if size_type
|
263
|
-
result
|
264
258
|
|
265
|
-
when
|
259
|
+
when 'collection'
|
266
260
|
size_type = case parameters.size
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
261
|
+
when 1
|
262
|
+
if parameters[0].is_a?(Puppet::Pops::Types::PIntegerType)
|
263
|
+
parameters[0]
|
264
|
+
else
|
265
|
+
assert_range_parameter(parameters[0])
|
266
|
+
TYPES.range(parameters[0], :default)
|
267
|
+
end
|
268
|
+
when 2
|
271
269
|
assert_range_parameter(parameters[0])
|
272
|
-
|
270
|
+
assert_range_parameter(parameters[1])
|
271
|
+
TYPES.range(parameters[0], parameters[1])
|
272
|
+
else
|
273
|
+
raise_invalid_parameters_error('Collection', '1 to 2', parameters.size)
|
273
274
|
end
|
274
|
-
|
275
|
-
assert_range_parameter(parameters[0])
|
276
|
-
assert_range_parameter(parameters[1])
|
277
|
-
TYPES.range(parameters[0], parameters[1])
|
278
|
-
else
|
279
|
-
raise_invalid_parameters_error("Collection", "1 to 2", parameters.size)
|
280
|
-
end
|
281
|
-
result = TYPES.collection
|
282
|
-
result.size_type = size_type
|
283
|
-
result
|
275
|
+
TYPES.collection(size_type)
|
284
276
|
|
285
|
-
when
|
277
|
+
when 'class'
|
286
278
|
if parameters.size != 1
|
287
|
-
raise_invalid_parameters_error(
|
279
|
+
raise_invalid_parameters_error('Class', 1, parameters.size)
|
288
280
|
end
|
289
281
|
TYPES.host_class(parameters[0])
|
290
282
|
|
291
|
-
when
|
283
|
+
when 'resource'
|
292
284
|
if parameters.size == 1
|
293
285
|
TYPES.resource(parameters[0])
|
294
286
|
elsif parameters.size != 2
|
295
|
-
raise_invalid_parameters_error(
|
287
|
+
raise_invalid_parameters_error('Resource', '1 or 2', parameters.size)
|
296
288
|
else
|
297
289
|
TYPES.resource(parameters[0], parameters[1])
|
298
290
|
end
|
299
291
|
|
300
|
-
when
|
292
|
+
when 'regexp'
|
301
293
|
# 1 parameter being a string, or regular expression
|
302
|
-
raise_invalid_parameters_error(
|
294
|
+
raise_invalid_parameters_error('Regexp', '1', parameters.size) unless parameters.size == 1
|
303
295
|
TYPES.regexp(parameters[0])
|
304
296
|
|
305
|
-
when
|
297
|
+
when 'enum'
|
306
298
|
# 1..m parameters being strings
|
307
|
-
raise_invalid_parameters_error(
|
299
|
+
raise_invalid_parameters_error('Enum', '1 or more', parameters.size) unless parameters.size >= 1
|
308
300
|
TYPES.enum(*parameters)
|
309
301
|
|
310
|
-
when
|
302
|
+
when 'pattern'
|
311
303
|
# 1..m parameters being strings or regular expressions
|
312
|
-
raise_invalid_parameters_error(
|
304
|
+
raise_invalid_parameters_error('Pattern', '1 or more', parameters.size) unless parameters.size >= 1
|
313
305
|
TYPES.pattern(*parameters)
|
314
306
|
|
315
|
-
when
|
307
|
+
when 'variant'
|
316
308
|
# 1..m parameters being strings or regular expressions
|
317
|
-
raise_invalid_parameters_error(
|
309
|
+
raise_invalid_parameters_error('Variant', '1 or more', parameters.size) unless parameters.size >= 1
|
318
310
|
TYPES.variant(*parameters)
|
319
311
|
|
320
|
-
when
|
312
|
+
when 'tuple'
|
321
313
|
# 1..m parameters being types (last two optionally integer or literal default
|
322
|
-
raise_invalid_parameters_error(
|
314
|
+
raise_invalid_parameters_error('Tuple', '1 or more', parameters.size) unless parameters.size >= 1
|
323
315
|
length = parameters.size
|
316
|
+
size_type = nil
|
324
317
|
if TYPES.is_range_parameter?(parameters[-2])
|
325
318
|
# min, max specification
|
326
319
|
min = parameters[-2]
|
@@ -329,30 +322,28 @@ class Puppet::Pops::Types::TypeParser
|
|
329
322
|
max = parameters[-1]
|
330
323
|
max = max == :default ? nil : max
|
331
324
|
parameters = parameters[0, length-2]
|
325
|
+
size_type = TYPES.range(min, max)
|
332
326
|
elsif TYPES.is_range_parameter?(parameters[-1])
|
333
327
|
min = parameters[-1]
|
334
328
|
min = (min == :default || min == 'default') ? 0 : min
|
335
329
|
max = nil
|
336
330
|
parameters = parameters[0, length-1]
|
331
|
+
size_type = TYPES.range(min, max)
|
337
332
|
end
|
338
|
-
|
339
|
-
if min || max
|
340
|
-
TYPES.constrain_size(t, min, max)
|
341
|
-
end
|
342
|
-
t
|
333
|
+
TYPES.tuple(parameters, size_type)
|
343
334
|
|
344
|
-
when
|
335
|
+
when 'callable'
|
345
336
|
# 1..m parameters being types (last three optionally integer or literal default, and a callable)
|
346
337
|
TYPES.callable(*parameters)
|
347
338
|
|
348
|
-
when
|
339
|
+
when 'struct'
|
349
340
|
# 1..m parameters being types (last two optionally integer or literal default
|
350
|
-
raise_invalid_parameters_error(
|
341
|
+
raise_invalid_parameters_error('Struct', '1', parameters.size) unless parameters.size == 1
|
351
342
|
h = parameters[0]
|
352
343
|
raise_invalid_type_specification_error unless h.is_a?(Hash)
|
353
344
|
TYPES.struct(h)
|
354
345
|
|
355
|
-
when
|
346
|
+
when 'integer'
|
356
347
|
if parameters.size == 1
|
357
348
|
case parameters[0]
|
358
349
|
when Integer
|
@@ -361,12 +352,12 @@ class Puppet::Pops::Types::TypeParser
|
|
361
352
|
TYPES.integer # unbound
|
362
353
|
end
|
363
354
|
elsif parameters.size != 2
|
364
|
-
raise_invalid_parameters_error(
|
355
|
+
raise_invalid_parameters_error('Integer', '1 or 2', parameters.size)
|
365
356
|
else
|
366
357
|
TYPES.range(parameters[0] == :default ? nil : parameters[0], parameters[1] == :default ? nil : parameters[1])
|
367
358
|
end
|
368
359
|
|
369
|
-
when
|
360
|
+
when 'float'
|
370
361
|
if parameters.size == 1
|
371
362
|
case parameters[0]
|
372
363
|
when Integer, Float
|
@@ -375,17 +366,17 @@ class Puppet::Pops::Types::TypeParser
|
|
375
366
|
TYPES.float # unbound
|
376
367
|
end
|
377
368
|
elsif parameters.size != 2
|
378
|
-
raise_invalid_parameters_error(
|
369
|
+
raise_invalid_parameters_error('Float', '1 or 2', parameters.size)
|
379
370
|
else
|
380
371
|
TYPES.float_range(parameters[0] == :default ? nil : parameters[0], parameters[1] == :default ? nil : parameters[1])
|
381
372
|
end
|
382
373
|
|
383
|
-
when
|
374
|
+
when 'string'
|
384
375
|
size_type =
|
385
376
|
case parameters.size
|
386
377
|
when 1
|
387
378
|
if parameters[0].is_a?(Puppet::Pops::Types::PIntegerType)
|
388
|
-
parameters[0]
|
379
|
+
parameters[0]
|
389
380
|
else
|
390
381
|
assert_range_parameter(parameters[0])
|
391
382
|
TYPES.range(parameters[0], :default)
|
@@ -395,24 +386,22 @@ class Puppet::Pops::Types::TypeParser
|
|
395
386
|
assert_range_parameter(parameters[1])
|
396
387
|
TYPES.range(parameters[0], parameters[1])
|
397
388
|
else
|
398
|
-
raise_invalid_parameters_error(
|
389
|
+
raise_invalid_parameters_error('String', '1 to 2', parameters.size)
|
399
390
|
end
|
400
|
-
|
401
|
-
result.size_type = size_type
|
402
|
-
result
|
391
|
+
TYPES.string(size_type)
|
403
392
|
|
404
|
-
when
|
393
|
+
when 'optional'
|
405
394
|
if parameters.size != 1
|
406
|
-
raise_invalid_parameters_error(
|
395
|
+
raise_invalid_parameters_error('Optional', 1, parameters.size)
|
407
396
|
end
|
408
397
|
param = parameters[0]
|
409
398
|
assert_type(param) unless param.is_a?(String)
|
410
399
|
TYPES.optional(param)
|
411
400
|
|
412
|
-
when
|
401
|
+
when 'any', 'data', 'catalogentry', 'boolean', 'scalar', 'undef', 'numeric', 'default'
|
413
402
|
raise_unparameterized_type_error(parameterized_ast.left_expr)
|
414
403
|
|
415
|
-
when
|
404
|
+
when 'notundef'
|
416
405
|
case parameters.size
|
417
406
|
when 0
|
418
407
|
TYPES.not_undef
|
@@ -424,15 +413,15 @@ class Puppet::Pops::Types::TypeParser
|
|
424
413
|
raise_invalid_parameters_error("NotUndef", "0 to 1", parameters.size)
|
425
414
|
end
|
426
415
|
|
427
|
-
when
|
416
|
+
when 'type'
|
428
417
|
if parameters.size != 1
|
429
|
-
raise_invalid_parameters_error(
|
418
|
+
raise_invalid_parameters_error('Type', 1, parameters.size)
|
430
419
|
end
|
431
420
|
assert_type(parameters[0])
|
432
421
|
TYPES.type_type(parameters[0])
|
433
422
|
|
434
|
-
when
|
435
|
-
raise_invalid_parameters_error(
|
423
|
+
when 'runtime'
|
424
|
+
raise_invalid_parameters_error('Runtime', '2', parameters.size) unless parameters.size == 2
|
436
425
|
TYPES.runtime(*parameters)
|
437
426
|
|
438
427
|
else
|
@@ -476,6 +465,6 @@ class Puppet::Pops::Types::TypeParser
|
|
476
465
|
|
477
466
|
def original_text_of(ast)
|
478
467
|
position = Puppet::Pops::Adapters::SourcePosAdapter.adapt(ast)
|
479
|
-
position.extract_text
|
468
|
+
position.extract_text
|
480
469
|
end
|
481
470
|
end
|
@@ -1,415 +1,1554 @@
|
|
1
1
|
require 'rgen/metamodel_builder'
|
2
2
|
|
3
3
|
# The Types model is a model of Puppet Language types.
|
4
|
-
#
|
5
|
-
#
|
4
|
+
#
|
5
|
+
# The exact relationship between types is not visible in this model wrt. the PDataType which is an abstraction
|
6
|
+
# of Scalar, Array[Data], and Hash[Scalar, Data] nested to any depth. This means it is not possible to
|
7
|
+
# infer the type by simply looking at the inheritance hierarchy. The {Puppet::Pops::Types::TypeCalculator} should
|
8
|
+
# be used to answer questions about types. The {Puppet::Pops::Types::TypeFactory} should be used to create an instance
|
9
|
+
# of a type whenever one is needed.
|
10
|
+
#
|
11
|
+
# The implementation of the Types model contains methods that are required for the type objects to behave as
|
12
|
+
# expected when comparing them and using them as keys in hashes. (No other logic is, or should be included directly in
|
13
|
+
# the model's classes).
|
6
14
|
#
|
7
15
|
# @api public
|
8
16
|
#
|
9
17
|
module Puppet::Pops
|
10
|
-
require 'puppet/pops/types/types_meta'
|
11
|
-
|
12
18
|
# TODO: See PUP-2978 for possible performance optimization
|
13
|
-
|
14
|
-
# Mix in implementation part of the Bindings Module
|
15
19
|
module Types
|
16
|
-
class
|
20
|
+
class TypedModelObject < Object
|
17
21
|
include Puppet::Pops::Visitable
|
18
22
|
include Puppet::Pops::Adaptable
|
19
|
-
include Puppet::Pops::Containment
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
# Base type for all types
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
class PAnyType < TypedModelObject
|
29
|
+
# Checks if _o_ is a type that is assignable to this type.
|
30
|
+
# If _o_ is a `Class` then it is first converted to a type.
|
31
|
+
# If _o_ is a Variant, then it is considered assignable when all its types are assignable
|
32
|
+
# @return [Boolean] `true` when _o_ is assignable to this type
|
33
|
+
# @api public
|
34
|
+
def assignable?(o)
|
35
|
+
case o
|
36
|
+
when Class
|
37
|
+
# Safe to call _assignable directly since a Class never is a Unit or Variant
|
38
|
+
_assignable?(Puppet::Pops::Types::TypeCalculator.singleton.type(o))
|
39
|
+
when PUnitType
|
40
|
+
true
|
41
|
+
when PVariantType
|
42
|
+
# Assignable if all contained types are assignable
|
43
|
+
o.types.all? { |vt| assignable?(vt) }
|
44
|
+
when PNotUndefType
|
45
|
+
if !(o.type.nil? || o.type.assignable?(PUndefType::DEFAULT))
|
46
|
+
assignable?(o.type)
|
47
|
+
else
|
48
|
+
_assignable?(o)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
_assignable?(o)
|
27
52
|
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns `true` if this instance is a callable that accepts the given _args_
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
def callable?(args)
|
59
|
+
args.is_a?(PAnyType) && kind_of_callable? && args.callable_args?(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns `true` if this instance is considered valid as arguments to _callable_
|
63
|
+
# @return [Boolean]
|
64
|
+
# @api private
|
65
|
+
def callable_args?(callable)
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
# Subclasses that are enumerable will override this method to return `true`
|
70
|
+
# @return [Boolean] false#
|
71
|
+
def enumerable?
|
72
|
+
is_a?(Enumerable)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generalizes value specific types. Types that are not value specific will return `self` otherwize
|
76
|
+
# the generalized type is returned.
|
77
|
+
#
|
78
|
+
# @return [PAnyType] The generalized type
|
79
|
+
# @api public
|
80
|
+
def generalize
|
81
|
+
# Applicable to all types that have no variables
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# Responds `true` for all callables, variants of callables and unless _optional_ is
|
86
|
+
# false, all optional callables.
|
87
|
+
# @return [Boolean] `true`if this type is considered callable
|
88
|
+
# @api private
|
89
|
+
def kind_of_callable?(optional=true)
|
90
|
+
false
|
91
|
+
end
|
92
|
+
|
93
|
+
def hash
|
94
|
+
self.class.hash
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns true if the given argument _o_ is an instance of this type
|
98
|
+
# @return [Boolean]
|
99
|
+
def instance?(o)
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def ==(o)
|
104
|
+
self.class == o.class
|
105
|
+
end
|
106
|
+
|
107
|
+
alias eql? ==
|
108
|
+
|
109
|
+
# Strips the class name from all module prefixes, the leading 'P' and the ending 'Type'. I.e.
|
110
|
+
# an instance of Puppet::Pops::Types::PVariantType will return 'Variant'
|
111
|
+
# @return [String] the simple name of this type
|
112
|
+
def simple_name
|
113
|
+
n = self.class.name
|
114
|
+
n[n.rindex('::')+3..n.size-5]
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_s
|
118
|
+
Puppet::Pops::Types::TypeCalculator.string(self)
|
119
|
+
end
|
120
|
+
|
121
|
+
# The default instance of this type. Each type in the type system has this constant
|
122
|
+
# declared.
|
123
|
+
#
|
124
|
+
DEFAULT = PAnyType.new
|
125
|
+
|
126
|
+
protected
|
127
|
+
|
128
|
+
# @api private
|
129
|
+
def _assignable?(o)
|
130
|
+
o.is_a?(PAnyType)
|
131
|
+
end
|
28
132
|
|
29
|
-
|
30
|
-
|
133
|
+
NAME_SEGMENT_SEPARATOR = '::'.freeze
|
134
|
+
|
135
|
+
# @api private
|
136
|
+
def class_from_string(str)
|
137
|
+
begin
|
138
|
+
str.split(NAME_SEGMENT_SEPARATOR).reduce(Object) do |memo, name_segment|
|
139
|
+
memo.const_get(name_segment)
|
140
|
+
end
|
141
|
+
rescue NameError
|
142
|
+
return nil
|
31
143
|
end
|
144
|
+
end
|
32
145
|
|
33
|
-
|
34
|
-
|
146
|
+
# Produces the tuple entry at the given index given a tuple type, its from/to constraints on the last
|
147
|
+
# type, and an index.
|
148
|
+
# Produces nil if the index is out of bounds
|
149
|
+
# from must be less than to, and from may not be less than 0
|
150
|
+
#
|
151
|
+
# @api private
|
152
|
+
#
|
153
|
+
def tuple_entry_at(tuple_t, from, to, index)
|
154
|
+
regular = (tuple_t.types.size - 1)
|
155
|
+
if index < regular
|
156
|
+
tuple_t.types[index]
|
157
|
+
elsif index < regular + to
|
158
|
+
# in the varargs part
|
159
|
+
tuple_t.types[-1]
|
160
|
+
else
|
161
|
+
nil
|
35
162
|
end
|
163
|
+
end
|
36
164
|
|
37
|
-
alias eql? ==
|
38
165
|
|
39
|
-
|
40
|
-
|
166
|
+
# Transform size_type to min, max
|
167
|
+
# if size_type == nil the constraint is 1,1
|
168
|
+
# if size_type.from == nil min size = 1
|
169
|
+
# if size_type.to == nil max size == Infinity
|
170
|
+
#
|
171
|
+
# @api private
|
172
|
+
def type_to_range(size_type)
|
173
|
+
return [1,1] if size_type.nil?
|
174
|
+
from = size_type.from
|
175
|
+
to = size_type.to
|
176
|
+
[from.nil? ? 1 : from, to.nil? ? Float::INFINITY : to]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# The type of types.
|
181
|
+
# @api public
|
182
|
+
#
|
183
|
+
class PType < PAnyType
|
184
|
+
attr_reader :type
|
185
|
+
|
186
|
+
def initialize(type)
|
187
|
+
@type = type
|
188
|
+
end
|
189
|
+
|
190
|
+
def instance?(o)
|
191
|
+
if o.is_a?(PAnyType)
|
192
|
+
type.nil? || type.assignable?(o)
|
193
|
+
else
|
194
|
+
assignable?(TypeCalculator.infer(o))
|
41
195
|
end
|
42
196
|
end
|
197
|
+
|
198
|
+
def generalize
|
199
|
+
@type.nil? ? DEFAULT : PType.new(type.generalize)
|
200
|
+
end
|
201
|
+
|
202
|
+
def hash
|
203
|
+
31 * @type.hash
|
204
|
+
end
|
205
|
+
|
206
|
+
def ==(o)
|
207
|
+
self.class == o.class && @type == o.type
|
208
|
+
end
|
209
|
+
|
210
|
+
def simple_name
|
211
|
+
# since this the class is inconsistently named PType and not PTypeType
|
212
|
+
'Type'
|
213
|
+
end
|
214
|
+
|
215
|
+
DEFAULT = PType.new(nil)
|
216
|
+
|
217
|
+
protected
|
218
|
+
|
219
|
+
# @api private
|
220
|
+
def _assignable?(o)
|
221
|
+
return false unless o.is_a?(PType)
|
222
|
+
return true if @type.nil? # wide enough to handle all types
|
223
|
+
return false if o.type.nil? # wider than t
|
224
|
+
@type.assignable?(o.type)
|
225
|
+
end
|
43
226
|
end
|
44
227
|
|
45
228
|
class PNotUndefType < PAnyType
|
46
|
-
|
47
|
-
def hash
|
48
|
-
[self.class, type].hash
|
49
|
-
end
|
229
|
+
attr_reader :type
|
50
230
|
|
51
|
-
|
52
|
-
|
53
|
-
|
231
|
+
def initialize(type = nil)
|
232
|
+
@type = type.class == PAnyType ? nil : type
|
233
|
+
end
|
234
|
+
|
235
|
+
def instance?(o)
|
236
|
+
!(o.nil? || o == :undef) && (@type.nil? || @type.instance?(o))
|
237
|
+
end
|
238
|
+
|
239
|
+
def generalize
|
240
|
+
@type.nil? ? DEFAULT : PNotUndefType.new(type.generalize)
|
241
|
+
end
|
242
|
+
|
243
|
+
def hash
|
244
|
+
31 * @type.hash
|
245
|
+
end
|
246
|
+
|
247
|
+
def ==(o)
|
248
|
+
self.class == o.class && @type == o.type
|
249
|
+
end
|
250
|
+
|
251
|
+
DEFAULT = PNotUndefType.new
|
252
|
+
|
253
|
+
protected
|
254
|
+
|
255
|
+
# @api private
|
256
|
+
def _assignable?(o)
|
257
|
+
o.is_a?(PAnyType) && !o.assignable?(PUndefType::DEFAULT) && (@type.nil? || @type.assignable?(o))
|
54
258
|
end
|
55
259
|
end
|
56
260
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
261
|
+
# @api public
|
262
|
+
#
|
263
|
+
class PUndefType < PAnyType
|
264
|
+
def instance?(o)
|
265
|
+
o.nil? || o == :undef
|
266
|
+
end
|
62
267
|
|
63
|
-
|
64
|
-
|
65
|
-
|
268
|
+
# @api private
|
269
|
+
def callable_args?(callable_t)
|
270
|
+
# if callable_t is Optional (or indeed PUndefType), this means that 'missing callable' is accepted
|
271
|
+
callable_t.assignable?(DEFAULT)
|
272
|
+
end
|
273
|
+
|
274
|
+
DEFAULT = PUndefType.new
|
275
|
+
|
276
|
+
protected
|
277
|
+
# @api private
|
278
|
+
def _assignable?(o)
|
279
|
+
o.is_a?(PUndefType)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# A type private to the type system that describes "ignored type" - i.e. "I am what you are"
|
284
|
+
# @api private
|
285
|
+
#
|
286
|
+
class PUnitType < PAnyType
|
287
|
+
def instance?(o)
|
288
|
+
true
|
289
|
+
end
|
290
|
+
|
291
|
+
DEFAULT = PUnitType.new
|
292
|
+
|
293
|
+
protected
|
294
|
+
# @api private
|
295
|
+
def _assignable?(o)
|
296
|
+
true
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# @api public
|
301
|
+
#
|
302
|
+
class PDefaultType < PAnyType
|
303
|
+
def instance?(o)
|
304
|
+
o == :default
|
305
|
+
end
|
306
|
+
|
307
|
+
DEFAULT = PDefaultType.new
|
308
|
+
|
309
|
+
protected
|
310
|
+
# @api private
|
311
|
+
def _assignable?(o)
|
312
|
+
o.is_a?(PDefaultType)
|
66
313
|
end
|
67
314
|
end
|
68
315
|
|
316
|
+
# A flexible data type, being assignable to its subtypes as well as PArrayType and PHashType with element type assignable to PDataType.
|
317
|
+
#
|
318
|
+
# @api public
|
319
|
+
#
|
69
320
|
class PDataType < PAnyType
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
321
|
+
def ==(o)
|
322
|
+
self.class == o.class || o.class == PVariantType && o == PVariantType::DATA
|
323
|
+
end
|
324
|
+
|
325
|
+
def instance?(o)
|
326
|
+
PVariantType::DATA.instance?(o)
|
327
|
+
end
|
328
|
+
|
329
|
+
DEFAULT = PDataType.new
|
330
|
+
|
331
|
+
protected
|
332
|
+
|
333
|
+
# Data is assignable by other Data and by Array[Data] and Hash[Scalar, Data]
|
334
|
+
# @api private
|
335
|
+
def _assignable?(o)
|
336
|
+
# We cannot put the NotUndefType[Data] in the @data_variant_t since that causes an endless recursion
|
337
|
+
case o
|
338
|
+
when Types::PDataType
|
339
|
+
true
|
340
|
+
when Types::PNotUndefType
|
341
|
+
assignable?(o.type || PUndefType::DEFAULT)
|
342
|
+
else
|
343
|
+
PVariantType::DATA.assignable?(o)
|
74
344
|
end
|
75
345
|
end
|
76
346
|
end
|
77
347
|
|
78
|
-
|
79
|
-
|
348
|
+
# Type that is PDataType compatible, but is not a PCollectionType.
|
349
|
+
# @api public
|
350
|
+
#
|
351
|
+
class PScalarType < PAnyType
|
80
352
|
|
81
|
-
|
82
|
-
|
83
|
-
|
353
|
+
def instance?(o)
|
354
|
+
assignable?(TypeCalculator.infer(o))
|
355
|
+
end
|
84
356
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
357
|
+
DEFAULT = PScalarType.new
|
358
|
+
|
359
|
+
protected
|
360
|
+
|
361
|
+
# @api private
|
362
|
+
def _assignable?(o)
|
363
|
+
o.is_a?(PScalarType)
|
89
364
|
end
|
90
365
|
end
|
91
366
|
|
367
|
+
# A string type describing the set of strings having one of the given values
|
368
|
+
# @api public
|
369
|
+
#
|
92
370
|
class PEnumType < PScalarType
|
93
|
-
|
94
|
-
def hash
|
95
|
-
[self.class, Set.new(self.values)].hash
|
96
|
-
end
|
371
|
+
include Enumerable
|
97
372
|
|
98
|
-
|
99
|
-
|
100
|
-
|
373
|
+
attr_reader :values
|
374
|
+
|
375
|
+
def initialize(values)
|
376
|
+
@values = values.sort.freeze
|
101
377
|
end
|
102
|
-
end
|
103
378
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
return Float::INFINITY if from.nil? || to.nil?
|
112
|
-
1+(to-from).abs
|
113
|
-
end
|
114
|
-
|
115
|
-
# Returns the range as an array ordered so the smaller number is always first.
|
116
|
-
# The number may be Infinity or -Infinity.
|
117
|
-
def range
|
118
|
-
f = from || -Float::INFINITY
|
119
|
-
t = to || Float::INFINITY
|
120
|
-
if f < t
|
121
|
-
[f, t]
|
122
|
-
else
|
123
|
-
[t,f]
|
124
|
-
end
|
379
|
+
# Returns Enumerator if no block is given, otherwise, calls the given
|
380
|
+
# block with each of the strings for this enum
|
381
|
+
def each
|
382
|
+
if block_given?
|
383
|
+
values.each { |x| yield x }
|
384
|
+
else
|
385
|
+
values.to_enum
|
125
386
|
end
|
387
|
+
end
|
126
388
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
389
|
+
def hash
|
390
|
+
@values.hash
|
391
|
+
end
|
392
|
+
|
393
|
+
def ==(o)
|
394
|
+
self.class == o.class && @values == o.values
|
395
|
+
end
|
396
|
+
|
397
|
+
DEFAULT = PEnumType.new([])
|
398
|
+
|
399
|
+
protected
|
400
|
+
|
401
|
+
# @api private
|
402
|
+
def _assignable?(o)
|
403
|
+
return true if self == o
|
404
|
+
svalues = values
|
405
|
+
if svalues.empty?
|
406
|
+
return true if o.is_a?(PStringType) || o.is_a?(PEnumType) || o.is_a?(PPatternType)
|
407
|
+
end
|
408
|
+
case o
|
409
|
+
when PStringType
|
410
|
+
# if the set of strings are all found in the set of enums
|
411
|
+
!o.values.empty? && o.values.all? { |s| svalues.any? { |e| e == s }}
|
412
|
+
when PEnumType
|
413
|
+
!o.values.empty? && o.values.all? { |s| svalues.any? {|e| e == s }}
|
134
414
|
else
|
135
|
-
|
136
|
-
end
|
415
|
+
false
|
137
416
|
end
|
417
|
+
end
|
418
|
+
end
|
138
419
|
|
139
|
-
|
140
|
-
|
420
|
+
# @api public
|
421
|
+
#
|
422
|
+
class PNumericType < PScalarType
|
423
|
+
def initialize(from, to = Float::INFINITY)
|
424
|
+
from = -Float::INFINITY if from.nil? || from == :default
|
425
|
+
to = Float::INFINITY if to.nil? || to == :default
|
426
|
+
|
427
|
+
# Always create in right order
|
428
|
+
if from <= to
|
429
|
+
@from = from
|
430
|
+
@to = to
|
431
|
+
else
|
432
|
+
@to = from
|
433
|
+
@from = to
|
141
434
|
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# Returns the lower bound of the numeric range or `nil` if no lower bound is set.
|
438
|
+
# @return [Float,Integer]
|
439
|
+
def from
|
440
|
+
@from == -Float::INFINITY ? nil : @from
|
441
|
+
end
|
442
|
+
|
443
|
+
# Returns the upper bound of the numeric range or `nil` if no upper bound is set.
|
444
|
+
# @return [Float,Integer]
|
445
|
+
def to
|
446
|
+
@to == Float::INFINITY ? nil : @to
|
447
|
+
end
|
448
|
+
|
449
|
+
# Same as #from but will return `-Float::Infinity` instead of `nil` if no lower bound is set.
|
450
|
+
# @return [Float,Integer]
|
451
|
+
def numeric_from
|
452
|
+
@from
|
453
|
+
end
|
454
|
+
|
455
|
+
# Same as #to but will return `Float::Infinity` instead of `nil` if no lower bound is set.
|
456
|
+
# @return [Float,Integer]
|
457
|
+
def numeric_to
|
458
|
+
@to
|
459
|
+
end
|
460
|
+
|
461
|
+
def hash
|
462
|
+
@from.hash * 31 + @to.hash
|
463
|
+
end
|
464
|
+
|
465
|
+
def ==(o)
|
466
|
+
self.class == o.class && @from == o.numeric_from && @to == o.numeric_to
|
467
|
+
end
|
468
|
+
|
469
|
+
def instance?(o)
|
470
|
+
o.is_a?(Numeric) && o >= @from && o <= @to
|
471
|
+
end
|
472
|
+
|
473
|
+
def unbounded?
|
474
|
+
@from == -Float::INFINITY && @to == Float::INFINITY
|
475
|
+
end
|
476
|
+
|
477
|
+
DEFAULT = PNumericType.new(-Float::INFINITY)
|
478
|
+
|
479
|
+
protected
|
480
|
+
|
481
|
+
# @api_private
|
482
|
+
def _assignable?(o)
|
483
|
+
return false unless o.is_a?(self.class)
|
484
|
+
# If o min and max are within the range of t
|
485
|
+
@from <= o.numeric_from && @to >= o.numeric_to
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
# @api public
|
490
|
+
#
|
491
|
+
class PIntegerType < PNumericType
|
492
|
+
# The integer type is enumerable when it defines a range
|
493
|
+
include Enumerable
|
494
|
+
|
495
|
+
def enumerable?
|
496
|
+
@from != -Float::INFINITY && @to != Float::INFINITY
|
497
|
+
end
|
498
|
+
|
499
|
+
def generalize
|
500
|
+
DEFAULT
|
501
|
+
end
|
502
|
+
|
503
|
+
def instance?(o)
|
504
|
+
o.is_a?(Integer) && o >= numeric_from && o <= numeric_to
|
505
|
+
end
|
506
|
+
|
507
|
+
# Returns Float.Infinity if one end of the range is unbound
|
508
|
+
def size
|
509
|
+
return Float::INFINITY if @from == -Float::INFINITY || @to == Float::INFINITY
|
510
|
+
1+(to-from).abs
|
511
|
+
end
|
512
|
+
|
513
|
+
# Returns the range as an array ordered so the smaller number is always first.
|
514
|
+
# The number may be Infinity or -Infinity.
|
515
|
+
def range
|
516
|
+
[@from, @to]
|
517
|
+
end
|
142
518
|
|
143
|
-
|
144
|
-
|
519
|
+
# Returns Enumerator if no block is given
|
520
|
+
# Returns nil if size is infinity (does not yield)
|
521
|
+
def each
|
522
|
+
if block_given?
|
523
|
+
enumerable? ? @from.upto(@to) { |x| yield x } : nil
|
524
|
+
else
|
525
|
+
to_enum
|
145
526
|
end
|
146
527
|
end
|
528
|
+
|
529
|
+
# Returns a range where both to and from are positive numbers. Negative
|
530
|
+
# numbers are converted to zero
|
531
|
+
# @return [PIntegerType] a positive range
|
532
|
+
def to_size
|
533
|
+
@from >= 0 ? self : PIntegerType.new(0, @to < 0 ? 0 : @to)
|
534
|
+
end
|
535
|
+
|
536
|
+
DEFAULT = PIntegerType.new(-Float::INFINITY)
|
147
537
|
end
|
148
538
|
|
539
|
+
# @api public
|
540
|
+
#
|
149
541
|
class PFloatType < PNumericType
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
542
|
+
def generalize
|
543
|
+
DEFAULT
|
544
|
+
end
|
545
|
+
|
546
|
+
def instance?(o)
|
547
|
+
o.is_a?(Float) && o >= numeric_from && o <= numeric_to
|
548
|
+
end
|
549
|
+
|
550
|
+
DEFAULT = PFloatType.new(-Float::INFINITY)
|
551
|
+
end
|
552
|
+
|
553
|
+
# @api public
|
554
|
+
#
|
555
|
+
class PCollectionType < PAnyType
|
556
|
+
attr_reader :element_type, :size_type
|
557
|
+
|
558
|
+
def initialize(element_type, size_type = nil)
|
559
|
+
@element_type = element_type
|
560
|
+
@size_type = size_type
|
561
|
+
end
|
154
562
|
|
155
|
-
|
156
|
-
|
563
|
+
def generalize
|
564
|
+
@element_type.nil? ? DEFAULT : PCollectionType.new(element_type.generalize, nil)
|
565
|
+
end
|
566
|
+
|
567
|
+
def instance?(o)
|
568
|
+
assignable?(TypeCalculator.infer(o))
|
569
|
+
end
|
570
|
+
|
571
|
+
# Returns an array with from (min) size to (max) size
|
572
|
+
def size_range
|
573
|
+
(@size_type || DEFAULT_SIZE).range
|
574
|
+
end
|
575
|
+
|
576
|
+
def hash
|
577
|
+
@element_type.hash * 31 + @size_type.hash
|
578
|
+
end
|
579
|
+
|
580
|
+
def ==(o)
|
581
|
+
self.class == o.class && @element_type == o.element_type && @size_type == o.size_type
|
582
|
+
end
|
583
|
+
|
584
|
+
|
585
|
+
DEFAULT_SIZE = PIntegerType.new(0)
|
586
|
+
ZERO_SIZE = PIntegerType.new(0, 0)
|
587
|
+
DEFAULT = PCollectionType.new(nil)
|
588
|
+
|
589
|
+
protected
|
590
|
+
|
591
|
+
# @api private
|
592
|
+
#
|
593
|
+
def _assignable?(o)
|
594
|
+
case o
|
595
|
+
when PCollectionType
|
596
|
+
(@size_type || DEFAULT_SIZE).assignable?(o.size_type || DEFAULT_SIZE)
|
597
|
+
when PTupleType
|
598
|
+
# compute the tuple's min/max size, and check if that size matches
|
599
|
+
from, to = type_to_range(o.size_type)
|
600
|
+
from = o.types.size - 1 + from
|
601
|
+
to = o.types.size - 1 + to
|
602
|
+
(@size_type || DEFAULT_SIZE).assignable?(PIntegerType.new(from, to))
|
603
|
+
when PStructType
|
604
|
+
from = to = o.elements.size
|
605
|
+
(@size_type || DEFAULT_SIZE).assignable?(PIntegerType.new(from, to))
|
606
|
+
else
|
607
|
+
false
|
157
608
|
end
|
158
609
|
end
|
159
610
|
end
|
160
611
|
|
612
|
+
# @api public
|
613
|
+
#
|
161
614
|
class PStringType < PScalarType
|
162
|
-
|
615
|
+
attr_reader :size_type, :values
|
163
616
|
|
164
|
-
|
165
|
-
|
617
|
+
def generalize
|
618
|
+
DEFAULT
|
619
|
+
end
|
620
|
+
|
621
|
+
def initialize(size_type, values = [])
|
622
|
+
@size_type = size_type
|
623
|
+
@values = values.sort.freeze
|
624
|
+
end
|
625
|
+
|
626
|
+
def hash
|
627
|
+
@size_type.hash * 31 + @values.hash
|
628
|
+
end
|
629
|
+
|
630
|
+
def ==(o)
|
631
|
+
self.class == o.class && @size_type == o.size_type && @values == o.values
|
632
|
+
end
|
633
|
+
|
634
|
+
def instance?(o)
|
635
|
+
# true if size compliant
|
636
|
+
if o.is_a?(String) && (@size_type.nil? || @size_type.instance?(o.size))
|
637
|
+
@values.empty? || @values.include?(o)
|
638
|
+
else
|
639
|
+
false
|
166
640
|
end
|
641
|
+
end
|
167
642
|
|
168
|
-
|
169
|
-
|
643
|
+
DEFAULT = PStringType.new(nil)
|
644
|
+
NON_EMPTY = PStringType.new(PIntegerType.new(1))
|
645
|
+
|
646
|
+
protected
|
647
|
+
|
648
|
+
# @api private
|
649
|
+
def _assignable?(o)
|
650
|
+
if values.empty?
|
651
|
+
# A general string is assignable by any other string or pattern restricted string
|
652
|
+
# if the string has a size constraint it does not match since there is no reasonable way
|
653
|
+
# to compute the min/max length a pattern will match. For enum, it is possible to test that
|
654
|
+
# each enumerator value is within range
|
655
|
+
case o
|
656
|
+
when PStringType
|
657
|
+
# true if size compliant
|
658
|
+
(@size_type || PCollectionType::DEFAULT_SIZE).assignable?(o.size_type || PCollectionType::DEFAULT_SIZE)
|
659
|
+
|
660
|
+
when PPatternType
|
661
|
+
# true if size constraint is at least 0 to +Infinity (which is the same as the default)
|
662
|
+
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE)
|
663
|
+
|
664
|
+
when PEnumType
|
665
|
+
if o.values.empty?
|
666
|
+
# enum represents all enums, and thus all strings, a sized constrained string can thus not
|
667
|
+
# be assigned any enum (unless it is max size).
|
668
|
+
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE)
|
669
|
+
else
|
670
|
+
# true if all enum values are within range
|
671
|
+
orange = o.values.map(&:size).minmax
|
672
|
+
srange = (@size_type || PCollectionType::DEFAULT_SIZE).range
|
673
|
+
# If o min and max are within the range of t
|
674
|
+
srange[0] <= orange[0] && srange[1] >= orange[1]
|
675
|
+
end
|
676
|
+
else
|
677
|
+
# no other type matches string
|
678
|
+
false
|
679
|
+
end
|
680
|
+
elsif o.is_a?(PStringType)
|
681
|
+
# A specific string acts as a set of strings - must have exactly the same strings
|
682
|
+
# In this case, size does not matter since the definition is very precise anyway
|
683
|
+
values == o.values
|
684
|
+
else
|
685
|
+
# All others are false, since no other type describes the same set of specific strings
|
686
|
+
false
|
170
687
|
end
|
171
688
|
end
|
172
689
|
end
|
173
690
|
|
691
|
+
# @api public
|
692
|
+
#
|
174
693
|
class PRegexpType < PScalarType
|
175
|
-
|
176
|
-
def regexp_derived
|
177
|
-
pattern_or_blank = pattern || ''
|
178
|
-
@_regexp = Regexp.new(pattern_or_blank) unless @_regexp && @_regexp.source == pattern_or_blank
|
179
|
-
@_regexp
|
180
|
-
end
|
694
|
+
attr_reader :pattern
|
181
695
|
|
182
|
-
|
183
|
-
|
184
|
-
|
696
|
+
def initialize(pattern)
|
697
|
+
@pattern = pattern
|
698
|
+
end
|
185
699
|
|
186
|
-
|
187
|
-
|
188
|
-
|
700
|
+
def regexp
|
701
|
+
@regexp ||= Regexp.new(@pattern || '')
|
702
|
+
end
|
703
|
+
|
704
|
+
def hash
|
705
|
+
@pattern.hash
|
706
|
+
end
|
707
|
+
|
708
|
+
def ==(o)
|
709
|
+
self.class == o.class && @pattern == o.pattern
|
710
|
+
end
|
711
|
+
|
712
|
+
DEFAULT = PRegexpType.new(nil)
|
713
|
+
|
714
|
+
protected
|
715
|
+
|
716
|
+
# @api private
|
717
|
+
#
|
718
|
+
def _assignable?(o)
|
719
|
+
o.is_a?(PRegexpType) && (@pattern.nil? || @pattern == o.pattern)
|
189
720
|
end
|
190
721
|
end
|
191
722
|
|
723
|
+
# Represents a subtype of String that narrows the string to those matching the patterns
|
724
|
+
# If specified without a pattern it is basically the same as the String type.
|
725
|
+
#
|
726
|
+
# @api public
|
727
|
+
#
|
192
728
|
class PPatternType < PScalarType
|
193
|
-
|
729
|
+
attr_reader :patterns
|
194
730
|
|
195
|
-
|
196
|
-
|
197
|
-
|
731
|
+
def initialize(patterns)
|
732
|
+
@patterns = patterns.freeze
|
733
|
+
end
|
198
734
|
|
199
|
-
|
200
|
-
|
201
|
-
end
|
735
|
+
def hash
|
736
|
+
@patterns.hash
|
202
737
|
end
|
203
|
-
end
|
204
738
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
739
|
+
def ==(o)
|
740
|
+
self.class == o.class && (@patterns | o.patterns).size == @patterns.size
|
741
|
+
end
|
742
|
+
|
743
|
+
DEFAULT = PPatternType.new([])
|
744
|
+
|
745
|
+
protected
|
746
|
+
|
747
|
+
# @api private
|
748
|
+
#
|
749
|
+
def _assignable?(o)
|
750
|
+
return true if self == o
|
751
|
+
case o
|
752
|
+
when PStringType, PEnumType
|
753
|
+
if o.values.empty?
|
754
|
+
# Strings / Enums (unknown which ones) cannot all match a pattern, but if there is no pattern it is ok
|
755
|
+
# (There should really always be a pattern, but better safe than sorry).
|
756
|
+
@patterns.empty?
|
214
757
|
else
|
215
|
-
|
758
|
+
# all strings in String/Enum type must match one of the patterns in Pattern type,
|
759
|
+
# or Pattern represents all Patterns == all Strings
|
760
|
+
regexps = @patterns.map { |p| p.regexp }
|
761
|
+
regexps.empty? || o.values.all? { |v| regexps.any? {|re| re.match(v) } }
|
216
762
|
end
|
763
|
+
when PPatternType
|
764
|
+
@patterns.empty?
|
765
|
+
else
|
766
|
+
false
|
217
767
|
end
|
768
|
+
end
|
769
|
+
end
|
218
770
|
|
219
|
-
|
220
|
-
|
221
|
-
|
771
|
+
# @api public
|
772
|
+
#
|
773
|
+
class PBooleanType < PScalarType
|
222
774
|
|
223
|
-
|
224
|
-
|
225
|
-
end
|
775
|
+
def instance?(o)
|
776
|
+
o == true || o == false
|
226
777
|
end
|
227
|
-
end
|
228
778
|
|
229
|
-
|
230
|
-
module ClassModule
|
231
|
-
def hash
|
232
|
-
[self.class, value_type, key_type].hash
|
233
|
-
end
|
779
|
+
DEFAULT = PBooleanType.new
|
234
780
|
|
235
|
-
|
236
|
-
k = key_type
|
237
|
-
k = k.optional_type if k.is_a?(POptionalType)
|
238
|
-
k.values[0]
|
239
|
-
end
|
781
|
+
protected
|
240
782
|
|
241
|
-
|
242
|
-
|
243
|
-
|
783
|
+
# @api private
|
784
|
+
#
|
785
|
+
def _assignable?(o)
|
786
|
+
o.is_a?(PBooleanType)
|
244
787
|
end
|
245
788
|
end
|
246
789
|
|
790
|
+
# @api public
|
791
|
+
#
|
792
|
+
# @api public
|
793
|
+
#
|
794
|
+
class PStructElement < TypedModelObject
|
795
|
+
attr_accessor :key_type, :value_type
|
796
|
+
|
797
|
+
def hash
|
798
|
+
value_type.hash * 31 + key_type.hash
|
799
|
+
end
|
800
|
+
|
801
|
+
def name
|
802
|
+
k = key_type
|
803
|
+
k = k.optional_type if k.is_a?(POptionalType)
|
804
|
+
k.values[0]
|
805
|
+
end
|
806
|
+
|
807
|
+
def initialize(key_type, value_type)
|
808
|
+
@key_type = key_type
|
809
|
+
@value_type = value_type
|
810
|
+
end
|
811
|
+
|
812
|
+
def generalize
|
813
|
+
PStructElement.new(@key_type, @value_type.generalize)
|
814
|
+
end
|
815
|
+
|
816
|
+
def <=>(o)
|
817
|
+
self.name <=> o.name
|
818
|
+
end
|
819
|
+
|
820
|
+
def ==(o)
|
821
|
+
self.class == o.class && value_type == o.value_type && key_type == o.key_type
|
822
|
+
end
|
823
|
+
end
|
247
824
|
|
825
|
+
# @api public
|
826
|
+
#
|
248
827
|
class PStructType < PAnyType
|
249
|
-
|
250
|
-
def hashed_elements_derived
|
251
|
-
@_hashed ||= elements.reduce({}) {|memo, e| memo[e.name] = e; memo }
|
252
|
-
@_hashed
|
253
|
-
end
|
828
|
+
include Enumerable
|
254
829
|
|
255
|
-
|
256
|
-
|
257
|
-
|
830
|
+
def initialize(elements)
|
831
|
+
@elements = elements.sort.freeze
|
832
|
+
end
|
258
833
|
|
259
|
-
|
260
|
-
|
834
|
+
def each
|
835
|
+
if block_given?
|
836
|
+
elements.each { |elem| yield elem }
|
837
|
+
else
|
838
|
+
elements.to_enum
|
261
839
|
end
|
840
|
+
end
|
262
841
|
|
263
|
-
|
264
|
-
|
842
|
+
def generalize
|
843
|
+
@elements.empty? ? DEFAULT : PStructType.new(@elements.map { |se| se.generalize })
|
844
|
+
end
|
845
|
+
|
846
|
+
def hashed_elements
|
847
|
+
@hashed ||= @elements.reduce({}) {|memo, e| memo[e.name] = e; memo }
|
848
|
+
end
|
849
|
+
|
850
|
+
def hash
|
851
|
+
@elements.hash
|
852
|
+
end
|
853
|
+
|
854
|
+
def ==(o)
|
855
|
+
self.class == o.class && @elements == o.elements
|
856
|
+
end
|
857
|
+
|
858
|
+
def elements
|
859
|
+
@elements
|
860
|
+
end
|
861
|
+
|
862
|
+
def instance?(o)
|
863
|
+
return false unless o.is_a?(Hash)
|
864
|
+
matched = 0
|
865
|
+
@elements.all? do |e|
|
866
|
+
key = e.name
|
867
|
+
v = o[key]
|
868
|
+
if v.nil? && !o.include?(key)
|
869
|
+
# Entry is missing. Only OK when key is optional
|
870
|
+
e.key_type.assignable?(PUndefType::DEFAULT)
|
871
|
+
else
|
872
|
+
matched += 1
|
873
|
+
e.value_type.instance?(v)
|
874
|
+
end
|
875
|
+
end && matched == o.size
|
876
|
+
end
|
877
|
+
|
878
|
+
DEFAULT = PStructType.new([])
|
879
|
+
|
880
|
+
protected
|
881
|
+
|
882
|
+
# @api private
|
883
|
+
def _assignable?(o)
|
884
|
+
if o.is_a?(Types::PStructType)
|
885
|
+
h2 = o.hashed_elements
|
886
|
+
matched = 0
|
887
|
+
elements.all? do |e1|
|
888
|
+
e2 = h2[e1.name]
|
889
|
+
if e2.nil?
|
890
|
+
e1.key_type.assignable?(PUndefType::DEFAULT)
|
891
|
+
else
|
892
|
+
matched += 1
|
893
|
+
e1.key_type.assignable?(e2.key_type) && e1.value_type.assignable?(e2.value_type)
|
894
|
+
end
|
895
|
+
end && matched == h2.size
|
896
|
+
elsif o.is_a?(Types::PHashType)
|
897
|
+
required = 0
|
898
|
+
required_elements_assignable = elements.all? do |e|
|
899
|
+
if e.key_type.assignable?(PUndefType::DEFAULT)
|
900
|
+
true
|
901
|
+
else
|
902
|
+
required += 1
|
903
|
+
e.value_type.assignable?(o.element_type)
|
904
|
+
end
|
905
|
+
end
|
906
|
+
if required_elements_assignable
|
907
|
+
size_o = o.size_type || collection_default_size_t
|
908
|
+
PIntegerType.new(required, elements.size).assignable?(size_o)
|
909
|
+
end
|
910
|
+
else
|
911
|
+
false
|
265
912
|
end
|
266
913
|
end
|
267
914
|
end
|
268
915
|
|
916
|
+
# @api public
|
917
|
+
#
|
269
918
|
class PTupleType < PAnyType
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
919
|
+
include Enumerable
|
920
|
+
|
921
|
+
# If set, describes min and max required of the given types - if max > size of
|
922
|
+
# types, the last type entry repeats
|
923
|
+
#
|
924
|
+
attr_reader :size_type
|
925
|
+
|
926
|
+
attr_reader :types
|
927
|
+
|
928
|
+
# @api private
|
929
|
+
def callable_args?(callable_t)
|
930
|
+
unless size_type.nil?
|
931
|
+
raise ArgumentError, 'Callable tuple may not have a size constraint when used as args'
|
932
|
+
end
|
933
|
+
|
934
|
+
params_tuple = callable_t.param_types
|
935
|
+
param_block_t = callable_t.block_type
|
936
|
+
arg_types = @types
|
937
|
+
arg_block_t = arg_types.last
|
938
|
+
if arg_block_t.kind_of_callable?
|
939
|
+
# Can't pass a block to a callable that doesn't accept one
|
940
|
+
return false if param_block_t.nil?
|
941
|
+
|
942
|
+
# Check that the block is of the right tyṕe
|
943
|
+
return false unless param_block_t.assignable?(arg_block_t)
|
944
|
+
|
945
|
+
# Check other arguments
|
946
|
+
arg_count = arg_types.size - 1
|
947
|
+
params_size_t = params_tuple.size_type || PIntegerType.new(*params_tuple.size_range)
|
948
|
+
return false unless params_size_t.assignable?(PIntegerType.new(arg_count, arg_count))
|
949
|
+
|
950
|
+
ctypes = params_tuple.types
|
951
|
+
arg_count.times do |index|
|
952
|
+
return false unless (ctypes[index] || ctypes[-1]).assignable?(arg_types[index])
|
284
953
|
end
|
285
|
-
|
286
|
-
min = from - (types_size-1)
|
287
|
-
min = min <= 0 ? 0 : min
|
288
|
-
max = to - (types_size-1)
|
289
|
-
[min, max]
|
954
|
+
return true
|
290
955
|
end
|
291
956
|
|
292
|
-
|
293
|
-
|
957
|
+
# Check that tuple is assignable and that the block (if declared) is optional
|
958
|
+
params_tuple.assignable?(self) && (param_block_t.nil? || param_block_t.assignable?(PUndefType::DEFAULT))
|
959
|
+
end
|
960
|
+
|
961
|
+
def initialize(types, size_type = nil)
|
962
|
+
@types = types
|
963
|
+
@size_type = size_type.nil? ? nil : size_type.to_size
|
964
|
+
end
|
965
|
+
|
966
|
+
# Returns Enumerator for the types if no block is given, otherwise, calls the given
|
967
|
+
# block with each of the types in this tuple
|
968
|
+
def each
|
969
|
+
if block_given?
|
970
|
+
types.each { |x| yield x }
|
971
|
+
else
|
972
|
+
types.to_enum
|
294
973
|
end
|
974
|
+
end
|
295
975
|
|
296
|
-
|
297
|
-
|
976
|
+
def generalize
|
977
|
+
self == DEFAULT ? self : PTupleType.new(@types.map {|t| t.generalize })
|
978
|
+
end
|
979
|
+
|
980
|
+
def instance?(o)
|
981
|
+
return false unless o.is_a?(Array)
|
982
|
+
# compute the tuple's min/max size, and check if that size matches
|
983
|
+
size_t = size_type || PIntegerType.new(*size_range)
|
984
|
+
|
985
|
+
return false unless size_t.instance?(o.size)
|
986
|
+
o.each_with_index do |element, index|
|
987
|
+
return false unless (types[index] || types[-1]).instance?(element)
|
298
988
|
end
|
989
|
+
true
|
299
990
|
end
|
300
|
-
end
|
301
991
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
992
|
+
# Returns the number of elements accepted [min, max] in the tuple
|
993
|
+
def size_range
|
994
|
+
if @size_type.nil?
|
995
|
+
types_size = @types.size
|
996
|
+
[types_size, types_size]
|
997
|
+
else
|
998
|
+
@size_type.range
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
# Returns the number of accepted occurrences [min, max] of the last type in the tuple
|
1003
|
+
# The defaults is [1,1]
|
1004
|
+
#
|
1005
|
+
def repeat_last_range
|
1006
|
+
if @size_type.nil?
|
1007
|
+
return [1, 1]
|
1008
|
+
end
|
1009
|
+
types_size = @types.size
|
1010
|
+
from, to = @size_type.range
|
1011
|
+
min = from - (types_size-1)
|
1012
|
+
min = min <= 0 ? 0 : min
|
1013
|
+
max = to - (types_size-1)
|
1014
|
+
[min, max]
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
def hash
|
1018
|
+
@size_type.hash * 31 + @types.hash
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def ==(o)
|
1022
|
+
self.class == o.class && @types == o.types && @size_type == o.size_type
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
DATA = PTupleType.new([PDataType::DEFAULT], PCollectionType::DEFAULT_SIZE)
|
1026
|
+
DEFAULT = PTupleType.new([])
|
1027
|
+
|
1028
|
+
protected
|
1029
|
+
|
1030
|
+
# @api private
|
1031
|
+
def _assignable?(o)
|
1032
|
+
return true if self == o
|
1033
|
+
s_types = types
|
1034
|
+
return true if s_types.empty? && (o.is_a?(PArrayType))
|
1035
|
+
size_s = size_type || PIntegerType.new(*size_range)
|
1036
|
+
|
1037
|
+
if o.is_a?(PTupleType)
|
1038
|
+
size_o = o.size_type || PIntegerType.new(*o.size_range)
|
1039
|
+
|
1040
|
+
# not assignable if the number of types in o is outside number of types in t1
|
1041
|
+
if size_s.assignable?(size_o)
|
1042
|
+
o_types = o.types
|
1043
|
+
o_types.size.times do |index|
|
1044
|
+
return false unless (s_types[index] || s_types[-1]).assignable?(o_types[index])
|
1045
|
+
end
|
1046
|
+
return true
|
323
1047
|
else
|
324
|
-
|
1048
|
+
return false
|
325
1049
|
end
|
1050
|
+
elsif o.is_a?(PArrayType)
|
1051
|
+
o_entry = o.element_type
|
1052
|
+
# Array of anything can not be assigned (unless tuple is tuple of anything) - this case
|
1053
|
+
# was handled at the top of this method.
|
1054
|
+
#
|
1055
|
+
return false if o_entry.nil?
|
1056
|
+
size_o = o.size_type || PCollectionType::DEFAULT_SIZE
|
1057
|
+
return false unless size_s.assignable?(size_o)
|
1058
|
+
[s_types.size, size_o.range[1]].min.times { |index| return false unless (s_types[index] || s_types[-1]).assignable?(o_entry) }
|
1059
|
+
true
|
1060
|
+
else
|
1061
|
+
false
|
326
1062
|
end
|
1063
|
+
end
|
1064
|
+
end
|
327
1065
|
|
328
|
-
|
329
|
-
|
330
|
-
|
1066
|
+
# @api public
|
1067
|
+
#
|
1068
|
+
class PCallableType < PAnyType
|
1069
|
+
# Types of parameters as a Tuple with required/optional count, or an Integer with min (required), max count
|
1070
|
+
# @return [PTupleType] the tuple representing the parameter types
|
1071
|
+
attr_reader :param_types
|
1072
|
+
|
1073
|
+
# Although being an abstract type reference, only Callable, or all Callables wrapped in
|
1074
|
+
# Optional or Variant are supported
|
1075
|
+
# If not set, the meaning is that block is not supported.
|
1076
|
+
# @return [PAnyType|nil] the block type
|
1077
|
+
attr_reader :block_type
|
1078
|
+
|
1079
|
+
# @param param_types [PTupleType]
|
1080
|
+
# @param block_type [PAnyType|nil]
|
1081
|
+
def initialize(param_types, block_type = nil)
|
1082
|
+
@param_types = param_types
|
1083
|
+
@block_type = block_type
|
1084
|
+
end
|
331
1085
|
|
332
|
-
|
333
|
-
|
1086
|
+
def generalize
|
1087
|
+
return self if self == DEFAULT
|
1088
|
+
params_t = @param_types.nil? ? nil : @param_types.generalize
|
1089
|
+
block_t = @block_type.nil? ? nil : @block_type.generalize
|
1090
|
+
PCallableType.new(params_t, block_t)
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
def instance?(o)
|
1094
|
+
assignable?(TypeCalculator.infer(o))
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
# @api private
|
1098
|
+
def callable_args?(required_callable_t)
|
1099
|
+
# If the required callable is euqal or more specific than self, self is acceptable arguments
|
1100
|
+
required_callable_t.assignable?(self)
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
def kind_of_callable?(optional=true)
|
1104
|
+
true
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
# Returns the number of accepted arguments [min, max]
|
1108
|
+
def size_range
|
1109
|
+
@param_types.nil? ? nil : @param_types.size_range
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
# Returns the number of accepted arguments for the last parameter type [min, max]
|
1113
|
+
#
|
1114
|
+
def last_range
|
1115
|
+
@param_types.nil? ? nil : @param_types.repeat_last_range
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
# Range [0,0], [0,1], or [1,1] for the block
|
1119
|
+
#
|
1120
|
+
def block_range
|
1121
|
+
case block_type
|
1122
|
+
when POptionalType
|
1123
|
+
[0,1]
|
1124
|
+
when PVariantType, PCallableType
|
1125
|
+
[1,1]
|
1126
|
+
else
|
1127
|
+
[0,0]
|
334
1128
|
end
|
335
1129
|
end
|
1130
|
+
|
1131
|
+
def hash
|
1132
|
+
@param_types.hash * 31 + @block_type.hash
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
def ==(o)
|
1136
|
+
self.class == o.class && @param_types == o.param_types && @block_type == o.block_type
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
DEFAULT = PCallableType.new(nil)
|
1140
|
+
|
1141
|
+
protected
|
1142
|
+
|
1143
|
+
# @api private
|
1144
|
+
def _assignable?(o)
|
1145
|
+
return false unless o.is_a?(PCallableType)
|
1146
|
+
# nil param_types means, any other Callable is assignable
|
1147
|
+
return true if @param_types.nil?
|
1148
|
+
|
1149
|
+
# NOTE: these tests are made in reverse as it is calling the callable that is constrained
|
1150
|
+
# (it's lower bound), not its upper bound
|
1151
|
+
return false unless o.param_types.assignable?(@param_types)
|
1152
|
+
# names are ignored, they are just information
|
1153
|
+
# Blocks must be compatible
|
1154
|
+
this_block_t = @block_type || PUndefType::DEFAULT
|
1155
|
+
that_block_t = o.block_type || PUndefType::DEFAULT
|
1156
|
+
that_block_t.assignable?(this_block_t)
|
1157
|
+
end
|
336
1158
|
end
|
337
1159
|
|
1160
|
+
# @api public
|
1161
|
+
#
|
338
1162
|
class PArrayType < PCollectionType
|
339
|
-
|
340
|
-
|
341
|
-
|
1163
|
+
|
1164
|
+
# @api private
|
1165
|
+
def callable_args?(callable)
|
1166
|
+
param_t = callable.param_types
|
1167
|
+
block_t = callable.block_type
|
1168
|
+
# does not support calling with a block, but have to check that callable is ok with missing block
|
1169
|
+
(param_t.nil? || param_t.assignable?(self)) && (block_t.nil? || block_t.assignable(PUndefType::DEFAULT))
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
def generalize
|
1173
|
+
if self == DEFAULT
|
1174
|
+
self
|
1175
|
+
else
|
1176
|
+
PArrayType.new(element_type.nil? ? nil : element_type.generalize)
|
342
1177
|
end
|
1178
|
+
end
|
343
1179
|
|
344
|
-
|
345
|
-
|
1180
|
+
def instance?(o)
|
1181
|
+
return false unless o.is_a?(Array)
|
1182
|
+
element_t = element_type
|
1183
|
+
return false unless element_t.nil? || o.all? {|element| element_t.instance?(element) }
|
1184
|
+
size_t = size_type
|
1185
|
+
size_t.nil? || size_t.instance?(o.size)
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
DATA = PArrayType.new(PDataType::DEFAULT, PCollectionType::DEFAULT_SIZE)
|
1189
|
+
DEFAULT = PArrayType.new(nil)
|
1190
|
+
EMPTY = PArrayType.new(PUnitType::DEFAULT, PCollectionType::ZERO_SIZE)
|
1191
|
+
|
1192
|
+
protected
|
1193
|
+
|
1194
|
+
# Array is assignable if o is an Array and o's element type is assignable, or if o is a Tuple
|
1195
|
+
# @api private
|
1196
|
+
def _assignable?(o)
|
1197
|
+
s_entry = element_type
|
1198
|
+
if o.is_a?(PTupleType)
|
1199
|
+
|
1200
|
+
# Tuple of anything can not be assigned (unless array is tuple of anything) - this case
|
1201
|
+
# was handled at the top of this method.
|
1202
|
+
#
|
1203
|
+
return false if s_entry.nil?
|
1204
|
+
|
1205
|
+
return false unless o.types.all? {|o_element_t| s_entry.assignable?(o_element_t) }
|
1206
|
+
o_regular = o.types[0..-2]
|
1207
|
+
o_ranged = o.types[-1]
|
1208
|
+
o_from, o_to = type_to_range(o.size_type)
|
1209
|
+
o_required = o_regular.size + o_from
|
1210
|
+
|
1211
|
+
# array type may be size constrained
|
1212
|
+
size_s = size_type || DEFAULT_SIZE
|
1213
|
+
min, max = size_s.range
|
1214
|
+
# Tuple with fewer min entries can not be assigned
|
1215
|
+
return false if o_required < min
|
1216
|
+
# Tuple with more optionally available entries can not be assigned
|
1217
|
+
return false if o_regular.size + o_to > max
|
1218
|
+
# each tuple type must be assignable to the element type
|
1219
|
+
o_required.times do |index|
|
1220
|
+
o_entry = tuple_entry_at(o, o_from, o_to, index)
|
1221
|
+
return false unless s_entry.assignable?(o_entry)
|
1222
|
+
end
|
1223
|
+
# ... and so must the last, possibly optional (ranged) type
|
1224
|
+
s_entry.assignable?(o_ranged)
|
1225
|
+
elsif o.is_a?(PArrayType)
|
1226
|
+
super && (s_entry.nil? || s_entry.assignable?(o.element_type))
|
1227
|
+
else
|
1228
|
+
false
|
346
1229
|
end
|
347
1230
|
end
|
348
1231
|
end
|
349
1232
|
|
1233
|
+
# @api public
|
1234
|
+
#
|
350
1235
|
class PHashType < PCollectionType
|
351
|
-
|
352
|
-
|
353
|
-
|
1236
|
+
attr_accessor :key_type
|
1237
|
+
|
1238
|
+
def initialize(key_type, value_type, size_type = nil)
|
1239
|
+
super(value_type, size_type)
|
1240
|
+
@key_type = key_type
|
1241
|
+
end
|
1242
|
+
|
1243
|
+
def generalize
|
1244
|
+
if self == DEFAULT || self == EMPTY
|
1245
|
+
self
|
1246
|
+
else
|
1247
|
+
key_t = @key_type
|
1248
|
+
key_t = key_t.generalize unless key_t.nil?
|
1249
|
+
value_t = element_type
|
1250
|
+
value_t = value_t.generalize unless value_t.nil?
|
1251
|
+
PHashType.new(key_t, value_t)
|
354
1252
|
end
|
1253
|
+
end
|
355
1254
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
1255
|
+
def hash
|
1256
|
+
@key_type.hash * 31 + super
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def instance?(o)
|
1260
|
+
return false unless o.is_a?(Hash)
|
1261
|
+
key_t = key_type
|
1262
|
+
element_t = element_type
|
1263
|
+
if (key_t.nil? || o.keys.all? {|key| key_t.instance?(key) }) &&
|
1264
|
+
(element_t.nil? || o.values.all? {|value| element_t.instance?(value) })
|
1265
|
+
size_t = size_type
|
1266
|
+
size_t.nil? || size_t.instance?(o.size)
|
1267
|
+
else
|
1268
|
+
false
|
361
1269
|
end
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
def ==(o)
|
1273
|
+
super && @key_type == o.key_type
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
def is_the_empty_hash?
|
1277
|
+
self == EMPTY
|
1278
|
+
end
|
362
1279
|
|
363
|
-
|
364
|
-
|
1280
|
+
DEFAULT = PHashType.new(nil, nil)
|
1281
|
+
DATA = PHashType.new(PScalarType::DEFAULT, PDataType::DEFAULT, DEFAULT_SIZE)
|
1282
|
+
EMPTY = PHashType.new(PUndefType::DEFAULT, PUndefType::DEFAULT, PIntegerType.new(0, 0))
|
1283
|
+
|
1284
|
+
protected
|
1285
|
+
|
1286
|
+
# Hash is assignable if o is a Hash and o's key and element types are assignable
|
1287
|
+
# @api private
|
1288
|
+
def _assignable?(o)
|
1289
|
+
case o
|
1290
|
+
when PHashType
|
1291
|
+
size_s = size_type
|
1292
|
+
return true if (size_s.nil? || size_s.from == 0) && o.is_the_empty_hash?
|
1293
|
+
return false unless (key_type.nil? || key_type.assignable?(o.key_type)) && (element_type.nil? || element_type.assignable?(o.element_type))
|
1294
|
+
super
|
1295
|
+
when PStructType
|
1296
|
+
# hash must accept String as key type
|
1297
|
+
# hash must accept all value types
|
1298
|
+
# hash must accept the size of the struct
|
1299
|
+
o_elements = o.elements
|
1300
|
+
(size_type || DEFAULT_SIZE).instance?(o_elements.size) &&
|
1301
|
+
o_elements.all? {|e| (key_type.nil? || key_type.instance?(e.name)) && (element_type.nil? || element_type.assignable?(e.value_type)) }
|
1302
|
+
else
|
1303
|
+
false
|
365
1304
|
end
|
366
1305
|
end
|
367
1306
|
end
|
368
1307
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
1308
|
+
# A flexible type describing an any? of other types
|
1309
|
+
# @api public
|
1310
|
+
#
|
1311
|
+
class PVariantType < PAnyType
|
1312
|
+
include Enumerable
|
1313
|
+
|
1314
|
+
attr_reader :types
|
1315
|
+
|
1316
|
+
def initialize(types)
|
1317
|
+
@types = types.freeze
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
def each
|
1321
|
+
if block_given?
|
1322
|
+
types.each { |t| yield t }
|
1323
|
+
else
|
1324
|
+
types.to_enum
|
373
1325
|
end
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
def generalize
|
1329
|
+
(self == DEFAULT || self == DATA) ? self : PVariantType.new(@types.map {|t| t.generalize})
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
def hash
|
1333
|
+
@types.hash
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
def instance?(o)
|
1337
|
+
# instance of variant if o is instance? of any of variant's types
|
1338
|
+
@types.any? { |type| type.instance?(o) }
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
def kind_of_callable?(optional = true)
|
1342
|
+
@types.all? { |type| type.kind_of_callable?(optional) }
|
1343
|
+
end
|
1344
|
+
|
1345
|
+
def ==(o)
|
1346
|
+
# TODO: This special case doesn't look like it belongs here
|
1347
|
+
self.class == o.class && (@types | o.types).size == @types.size ||
|
1348
|
+
o.class == PDataType && self == DATA
|
1349
|
+
end
|
374
1350
|
|
375
|
-
|
376
|
-
|
1351
|
+
# Variant compatible with the Data type.
|
1352
|
+
DATA = PVariantType.new([PHashType::DATA, PArrayType::DATA, PScalarType::DEFAULT, PUndefType::DEFAULT, PTupleType::DATA])
|
1353
|
+
|
1354
|
+
DEFAULT = PVariantType.new([])
|
1355
|
+
|
1356
|
+
protected
|
1357
|
+
|
1358
|
+
# @api private
|
1359
|
+
def _assignable?(o)
|
1360
|
+
# Data is a specific variant
|
1361
|
+
o = DATA if o.is_a?(PDataType)
|
1362
|
+
if o.is_a?(PVariantType)
|
1363
|
+
# A variant is assignable if all of its options are assignable to one of this type's options
|
1364
|
+
return true if self == o
|
1365
|
+
o.types.all? do |other|
|
1366
|
+
# if the other is a Variant, all of its options, but be assignable to one of this type's options
|
1367
|
+
other = other.is_a?(PDataType) ? DATA : other
|
1368
|
+
if other.is_a?(PVariantType)
|
1369
|
+
assignable?(other)
|
1370
|
+
else
|
1371
|
+
types.any? {|option_t| option_t.assignable?(other) }
|
1372
|
+
end
|
1373
|
+
end
|
1374
|
+
else
|
1375
|
+
# A variant is assignable if o is assignable to any of its types
|
1376
|
+
types.any? { |option_t| option_t.assignable?(o) }
|
377
1377
|
end
|
378
1378
|
end
|
379
1379
|
end
|
380
1380
|
|
1381
|
+
# @api public
|
1382
|
+
#
|
1383
|
+
class PRuntimeType < PAnyType
|
1384
|
+
attr_reader :runtime, :runtime_type_name
|
1385
|
+
|
1386
|
+
def initialize(runtime, runtime_type_name = nil)
|
1387
|
+
@runtime = runtime
|
1388
|
+
@runtime_type_name = runtime_type_name
|
1389
|
+
end
|
1390
|
+
|
1391
|
+
def hash
|
1392
|
+
@runtime.hash * 31 + @runtime_type_name.hash
|
1393
|
+
end
|
1394
|
+
|
1395
|
+
def ==(o)
|
1396
|
+
self.class == o.class && @runtime == o.runtime && @runtime_type_name == o.runtime_type_name
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
def instance?(o)
|
1400
|
+
assignable?(TypeCalculator.infer(o))
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
DEFAULT = PRuntimeType.new(nil)
|
1404
|
+
|
1405
|
+
protected
|
1406
|
+
|
1407
|
+
# Assignable if o's has the same runtime and the runtime name resolves to
|
1408
|
+
# a class that is the same or subclass of t1's resolved runtime type name
|
1409
|
+
# @api private
|
1410
|
+
def _assignable?(o)
|
1411
|
+
return false unless o.is_a?(PRuntimeType)
|
1412
|
+
return false unless @runtime == o.runtime
|
1413
|
+
return true if @runtime_type_name.nil? # t1 is wider
|
1414
|
+
return false if o.runtime_type_name.nil? # t1 not nil, so o can not be wider
|
1415
|
+
|
1416
|
+
# NOTE: This only supports Ruby, must change when/if the set of runtimes is expanded
|
1417
|
+
c1 = class_from_string(@runtime_type_name)
|
1418
|
+
c2 = class_from_string(o.runtime_type_name)
|
1419
|
+
return false unless c1.is_a?(Module) && c2.is_a?(Module)
|
1420
|
+
!!(c2 <= c1)
|
1421
|
+
end
|
1422
|
+
end
|
1423
|
+
|
1424
|
+
# Abstract representation of a type that can be placed in a Catalog.
|
1425
|
+
# @api public
|
1426
|
+
#
|
1427
|
+
class PCatalogEntryType < PAnyType
|
1428
|
+
|
1429
|
+
DEFAULT = PCatalogEntryType.new
|
1430
|
+
|
1431
|
+
def instance?(o)
|
1432
|
+
assignable?(TypeCalculator.infer(o))
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
protected
|
1436
|
+
# @api private
|
1437
|
+
def _assignable?(o)
|
1438
|
+
o.is_a?(PCatalogEntryType)
|
1439
|
+
end
|
1440
|
+
end
|
1441
|
+
|
1442
|
+
# Represents a (host-) class in the Puppet Language.
|
1443
|
+
# @api public
|
1444
|
+
#
|
381
1445
|
class PHostClassType < PCatalogEntryType
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
1446
|
+
attr_reader :class_name
|
1447
|
+
|
1448
|
+
def initialize(class_name)
|
1449
|
+
@class_name = class_name
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
def hash
|
1453
|
+
11 * @class_name.hash
|
1454
|
+
end
|
1455
|
+
def ==(o)
|
1456
|
+
self.class == o.class && @class_name == o.class_name
|
1457
|
+
end
|
1458
|
+
|
1459
|
+
DEFAULT = PHostClassType.new(nil)
|
1460
|
+
|
1461
|
+
protected
|
1462
|
+
|
1463
|
+
# @api private
|
1464
|
+
def _assignable?(o)
|
1465
|
+
return false unless o.is_a?(PHostClassType)
|
1466
|
+
# Class = Class[name}, Class[name] != Class
|
1467
|
+
return true if @class_name.nil?
|
1468
|
+
# Class[name] = Class[name]
|
1469
|
+
@class_name == o.class_name
|
389
1470
|
end
|
390
1471
|
end
|
391
1472
|
|
1473
|
+
# Represents a Resource Type in the Puppet Language
|
1474
|
+
# @api public
|
1475
|
+
#
|
392
1476
|
class PResourceType < PCatalogEntryType
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
1477
|
+
attr_reader :type_name, :title
|
1478
|
+
|
1479
|
+
def initialize(type_name, title = nil)
|
1480
|
+
@type_name = type_name
|
1481
|
+
@title = title
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
def hash
|
1485
|
+
@type_name.hash * 31 + @title.hash
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
def ==(o)
|
1489
|
+
self.class == o.class && @type_name == o.type_name && @title == o.title
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
DEFAULT = PResourceType.new(nil)
|
1493
|
+
|
1494
|
+
protected
|
1495
|
+
|
1496
|
+
# @api private
|
1497
|
+
def _assignable?(o)
|
1498
|
+
return false unless o.is_a?(PResourceType)
|
1499
|
+
return true if @type_name.nil?
|
1500
|
+
return false if @type_name != o.type_name
|
1501
|
+
return true if @title.nil?
|
1502
|
+
@title == o.title
|
400
1503
|
end
|
401
1504
|
end
|
402
1505
|
|
1506
|
+
# Represents a type that accept PUndefType instead of the type parameter
|
1507
|
+
# required_type - is a short hand for Variant[T, Undef]
|
1508
|
+
# @api public
|
1509
|
+
#
|
403
1510
|
class POptionalType < PAnyType
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
1511
|
+
attr_reader :optional_type
|
1512
|
+
|
1513
|
+
def initialize(optional_type)
|
1514
|
+
@optional_type = optional_type
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
def generalize
|
1518
|
+
@optional_type.nil? ? self : PType.new(@optional_type.generalize)
|
1519
|
+
end
|
1520
|
+
|
1521
|
+
def hash
|
1522
|
+
7 * @optional_type.hash
|
1523
|
+
end
|
1524
|
+
|
1525
|
+
def kind_of_callable?(optional=true)
|
1526
|
+
optional && !@optional_type.nil? && @optional_type.kind_of_callable?(optional)
|
1527
|
+
end
|
1528
|
+
|
1529
|
+
def ==(o)
|
1530
|
+
self.class == o.class && @optional_type == o.optional_type
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
def instance?(o)
|
1534
|
+
PUndefType::DEFAULT.instance?(o) || (!optional_type.nil? && optional_type.instance?(o))
|
1535
|
+
end
|
408
1536
|
|
409
|
-
|
410
|
-
|
1537
|
+
DEFAULT = POptionalType.new(nil)
|
1538
|
+
|
1539
|
+
protected
|
1540
|
+
|
1541
|
+
# @api private
|
1542
|
+
def _assignable?(o)
|
1543
|
+
return true if o.is_a?(PUndefType)
|
1544
|
+
return true if @optional_type.nil?
|
1545
|
+
if o.is_a?(POptionalType)
|
1546
|
+
@optional_type.assignable?(o.optional_type)
|
1547
|
+
else
|
1548
|
+
@optional_type.assignable?(o)
|
411
1549
|
end
|
412
1550
|
end
|
413
1551
|
end
|
414
1552
|
end
|
415
1553
|
end
|
1554
|
+
|