puppet 4.3.2-x86-mingw32 → 4.4.0-x86-mingw32
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.
- checksums.yaml +4 -4
- data/COMMITTERS.md +2 -2
- data/CONTRIBUTING.md +6 -6
- data/LICENSE +1 -1
- data/README.md +8 -9
- data/conf/auth.conf +2 -2
- data/ext/README.environment +1 -1
- data/ext/debian/README.source +1 -1
- data/ext/debian/control +1 -1
- data/ext/debian/copyright +4 -4
- data/ext/debian/puppetmaster.README.debian +11 -9
- data/ext/emacs/puppet-mode.el +1 -1
- data/ext/envpuppet +2 -2
- data/ext/ips/puppetagent.xml +1 -1
- data/ext/ips/puppetmaster.xml +1 -1
- data/ext/project_data.yaml +8 -0
- data/ext/puppet-test +3 -3
- data/ext/rack/example-passenger-vhost.conf +1 -1
- data/ext/redhat/puppet.spec.erb +2 -2
- data/ext/regexp_nodes/regexp_nodes.rb +1 -1
- data/ext/solaris/pkginfo +1 -1
- data/ext/solaris/smf/puppet.xml +1 -1
- data/ext/suse/puppet.spec +2 -2
- data/ext/upload_facts.rb +1 -1
- data/ext/windows/puppet_interactive.bat +6 -0
- data/ext/windows/puppet_shell.bat +9 -0
- data/ext/windows/run_puppet_interactive.bat +9 -0
- data/ext/yaml_nodes.rb +1 -1
- data/install.rb +30 -20
- data/lib/puppet/agent.rb +1 -1
- data/lib/puppet/application/agent.rb +4 -2
- data/lib/puppet/application/apply.rb +7 -4
- data/lib/puppet/application/cert.rb +1 -1
- data/lib/puppet/application/device.rb +1 -1
- data/lib/puppet/application/filebucket.rb +1 -1
- data/lib/puppet/application/inspect.rb +1 -1
- data/lib/puppet/application/lookup.rb +4 -4
- data/lib/puppet/application/master.rb +2 -2
- data/lib/puppet/application/resource.rb +1 -1
- data/lib/puppet/configurer.rb +100 -22
- data/lib/puppet/data_providers/hiera_config.rb +28 -3
- data/lib/puppet/data_providers/hiera_interpolate.rb +30 -15
- data/lib/puppet/data_providers/hiera_support.rb +1 -1
- data/lib/puppet/data_providers/json_data_provider_factory.rb +2 -2
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -2
- data/lib/puppet/defaults.rb +65 -19
- data/lib/puppet/environments.rb +3 -1
- data/lib/puppet/face/config.rb +1 -1
- data/lib/puppet/face/epp.rb +1 -1
- data/lib/puppet/face/help/man.erb +1 -1
- data/lib/puppet/face/module/install.rb +6 -6
- data/lib/puppet/face/parser.rb +12 -9
- data/lib/puppet/face/status.rb +2 -1
- data/lib/puppet/feature/cfpropertylist.rb +3 -0
- data/lib/puppet/feature/telnet.rb +9 -0
- data/lib/puppet/file_serving/http_metadata.rb +46 -0
- data/lib/puppet/file_serving/metadata.rb +18 -2
- data/lib/puppet/file_serving/terminus_selector.rb +2 -0
- data/lib/puppet/file_system.rb +2 -2
- data/lib/puppet/file_system/file_impl.rb +2 -2
- data/lib/puppet/file_system/memory_impl.rb +1 -1
- data/lib/puppet/file_system/uniquefile.rb +1 -1
- data/lib/puppet/forge.rb +1 -1
- data/lib/puppet/forge/repository.rb +1 -31
- data/lib/puppet/functions.rb +45 -6
- data/lib/puppet/functions/assert_type.rb +9 -9
- data/lib/puppet/functions/each.rb +5 -13
- data/lib/puppet/functions/filter.rb +5 -14
- data/lib/puppet/functions/map.rb +6 -14
- data/lib/puppet/functions/reduce.rb +5 -13
- data/lib/puppet/functions/reverse_each.rb +82 -0
- data/lib/puppet/functions/scanf.rb +15 -18
- data/lib/puppet/functions/slice.rb +22 -36
- data/lib/puppet/functions/split.rb +2 -2
- data/lib/puppet/functions/step.rb +88 -0
- data/lib/puppet/functions/type.rb +70 -0
- data/lib/puppet/graph/rb_tree_map.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +188 -5
- data/lib/puppet/indirector/file_content/http.rb +15 -0
- data/lib/puppet/indirector/file_metadata/http.rb +27 -0
- data/lib/puppet/indirector/generic_http.rb +16 -0
- data/lib/puppet/indirector/node/exec.rb +1 -1
- data/lib/puppet/indirector/node/ldap.rb +1 -1
- data/lib/puppet/indirector/rest.rb +2 -1
- data/lib/puppet/info_service/class_information_service.rb +13 -12
- data/lib/puppet/loaders.rb +1 -0
- data/lib/puppet/module.rb +3 -0
- data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +9 -2
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/tests/init.pp.erb +2 -2
- data/lib/puppet/module_tool/tar/mini.rb +3 -3
- data/lib/puppet/network/http/pool.rb +9 -0
- data/lib/puppet/node.rb +1 -1
- data/lib/puppet/node/environment.rb +11 -2
- data/lib/puppet/parser/ast/pops_bridge.rb +19 -22
- data/lib/puppet/parser/compiler.rb +3 -3
- data/lib/puppet/parser/environment_compiler.rb +0 -1
- data/lib/puppet/parser/functions.rb +28 -16
- data/lib/puppet/parser/functions/fqdn_rand.rb +1 -1
- data/lib/puppet/parser/functions/inline_template.rb +1 -1
- data/lib/puppet/parser/functions/map.rb +1 -1
- data/lib/puppet/parser/functions/scanf.rb +15 -26
- data/lib/puppet/parser/functions/slice.rb +17 -24
- data/lib/puppet/parser/functions/split.rb +1 -1
- data/lib/puppet/parser/resource.rb +19 -17
- data/lib/puppet/parser/scope.rb +176 -5
- data/lib/puppet/plugins/data_providers/data_provider.rb +54 -13
- data/lib/puppet/pops.rb +0 -8
- data/lib/puppet/pops/adaptable.rb +4 -1
- data/lib/puppet/pops/adapters.rb +38 -13
- data/lib/puppet/pops/binder/binder.rb +21 -17
- data/lib/puppet/pops/binder/binder_issues.rb +8 -6
- data/lib/puppet/pops/binder/bindings_checker.rb +12 -8
- data/lib/puppet/pops/binder/bindings_composer.rb +16 -12
- data/lib/puppet/pops/binder/bindings_factory.rb +108 -104
- data/lib/puppet/pops/binder/bindings_model.rb +49 -47
- data/lib/puppet/pops/binder/config/diagnostic_producer.rb +10 -6
- data/lib/puppet/pops/binder/injector.rb +53 -48
- data/lib/puppet/pops/binder/key_factory.rb +10 -6
- data/lib/puppet/pops/binder/producers.rb +67 -62
- data/lib/puppet/pops/evaluator/access_operator.rb +95 -93
- data/lib/puppet/pops/evaluator/closure.rb +84 -68
- data/lib/puppet/pops/evaluator/collector_transformer.rb +18 -14
- data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +0 -1
- data/lib/puppet/pops/evaluator/compare_operator.rb +13 -9
- data/lib/puppet/pops/evaluator/epp_evaluator.rb +9 -8
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +78 -76
- data/lib/puppet/pops/evaluator/json_strict_literal_evaluator.rb +85 -0
- data/lib/puppet/pops/evaluator/relationship_operator.rb +13 -11
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +5 -0
- data/lib/puppet/pops/evaluator/runtime3_support.rb +41 -45
- data/lib/puppet/pops/issue_reporter.rb +6 -4
- data/lib/puppet/pops/issues.rb +34 -11
- data/lib/puppet/pops/loader/base_loader.rb +1 -1
- data/lib/puppet/pops/loader/loader.rb +1 -1
- data/lib/puppet/pops/loader/loader_paths.rb +15 -0
- data/lib/puppet/pops/loader/module_loaders.rb +17 -13
- data/lib/puppet/pops/loader/puppet_function_instantiator.rb +16 -12
- data/lib/puppet/pops/loader/ruby_function_instantiator.rb +16 -3
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +55 -0
- data/lib/puppet/pops/loaders.rb +51 -9
- data/lib/puppet/pops/lookup.rb +14 -12
- data/lib/puppet/pops/merge_strategy.rb +16 -19
- data/lib/puppet/pops/model/factory.rb +26 -2
- data/lib/puppet/pops/model/model.rb +8 -8
- data/lib/puppet/pops/model/model_label_provider.rb +13 -7
- data/lib/puppet/pops/model/model_meta.rb +17 -0
- data/lib/puppet/pops/model/model_tree_dumper.rb +8 -0
- data/lib/puppet/pops/parser/egrammar.ra +38 -14
- data/lib/puppet/pops/parser/eparser.rb +1353 -1276
- data/lib/puppet/pops/parser/epp_support.rb +11 -7
- data/lib/puppet/pops/parser/evaluating_parser.rb +14 -10
- data/lib/puppet/pops/parser/heredoc_support.rb +15 -11
- data/lib/puppet/pops/parser/lexer2.rb +26 -19
- data/lib/puppet/pops/parser/lexer_support.rb +85 -7
- data/lib/puppet/pops/parser/locator.rb +21 -0
- data/lib/puppet/pops/parser/parser_support.rb +19 -16
- data/lib/puppet/pops/parser/slurp_support.rb +11 -7
- data/lib/puppet/pops/types/class_loader.rb +23 -19
- data/lib/puppet/pops/types/enumeration.rb +9 -26
- data/lib/puppet/pops/types/iterable.rb +308 -0
- data/lib/puppet/pops/types/recursion_guard.rb +82 -0
- data/lib/puppet/pops/types/type_acceptor.rb +25 -0
- data/lib/puppet/pops/types/type_asserter.rb +10 -9
- data/lib/puppet/pops/types/type_calculator.rb +138 -381
- data/lib/puppet/pops/types/type_factory.rb +91 -57
- data/lib/puppet/pops/types/type_formatter.rb +334 -0
- data/lib/puppet/pops/types/type_mismatch_describer.rb +226 -59
- data/lib/puppet/pops/types/type_parser.rb +159 -112
- data/lib/puppet/pops/types/types.rb +2057 -1247
- data/lib/puppet/pops/utils.rb +11 -10
- data/lib/puppet/pops/validation.rb +11 -9
- data/lib/puppet/pops/validation/checker4_0.rb +83 -55
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +8 -4
- data/lib/puppet/provider/aixobject.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/cron/crontab.rb +1 -1
- data/lib/puppet/provider/exec/windows.rb +1 -1
- data/lib/puppet/provider/macauthorization/macauthorization.rb +10 -9
- data/lib/puppet/provider/nameservice/directoryservice.rb +35 -50
- data/lib/puppet/provider/package/appdmg.rb +3 -2
- data/lib/puppet/provider/package/dnf.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +5 -8
- data/lib/puppet/provider/package/pip3.rb +1 -1
- data/lib/puppet/provider/package/pkg.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +3 -2
- data/lib/puppet/provider/package/pkgng.rb +13 -4
- data/lib/puppet/provider/package/windows.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/package/zypper.rb +19 -0
- data/lib/puppet/provider/service/debian.rb +2 -2
- data/lib/puppet/provider/service/launchd.rb +6 -18
- data/lib/puppet/provider/service/systemd.rb +9 -2
- data/lib/puppet/provider/sshkey/parsed.rb +1 -1
- data/lib/puppet/provider/user/aix.rb +1 -1
- data/lib/puppet/provider/user/directoryservice.rb +33 -58
- data/lib/puppet/provider/zfs/zfs.rb +1 -1
- data/lib/puppet/provider/zpool/zpool.rb +1 -1
- data/lib/puppet/reference/configuration.rb +1 -1
- data/lib/puppet/reference/providers.rb +1 -1
- data/lib/puppet/resource.rb +15 -12
- data/lib/puppet/resource/capability_finder.rb +20 -13
- data/lib/puppet/resource/catalog.rb +60 -3
- data/lib/puppet/resource/status.rb +11 -2
- data/lib/puppet/resource/type.rb +28 -38
- data/lib/puppet/settings.rb +1 -1
- data/lib/puppet/settings/config_file.rb +1 -1
- data/lib/puppet/settings/environment_conf.rb +13 -5
- data/lib/puppet/ssl/certificate_factory.rb +3 -3
- data/lib/puppet/ssl/certificate_request.rb +4 -4
- data/lib/puppet/ssl/certificate_signer.rb +1 -1
- data/lib/puppet/ssl/validator/default_validator.rb +1 -1
- data/lib/puppet/test/test_helper.rb +16 -4
- data/lib/puppet/transaction.rb +15 -2
- data/lib/puppet/transaction/additional_resource_generator.rb +6 -2
- data/lib/puppet/transaction/report.rb +31 -1
- data/lib/puppet/transaction/resource_harness.rb +0 -25
- data/lib/puppet/type.rb +11 -11
- data/lib/puppet/type/augeas.rb +1 -1
- data/lib/puppet/type/cron.rb +12 -12
- data/lib/puppet/type/file.rb +91 -39
- data/lib/puppet/type/file/checksum_value.rb +53 -0
- data/lib/puppet/type/file/content.rb +26 -111
- data/lib/puppet/type/file/data_sync.rb +84 -0
- data/lib/puppet/type/file/ensure.rb +17 -14
- data/lib/puppet/type/file/selcontext.rb +1 -1
- data/lib/puppet/type/file/source.rb +103 -18
- data/lib/puppet/type/filebucket.rb +1 -1
- data/lib/puppet/type/interface.rb +8 -3
- data/lib/puppet/type/macauthorization.rb +1 -1
- data/lib/puppet/type/package.rb +6 -0
- data/lib/puppet/type/schedule.rb +1 -1
- data/lib/puppet/type/stage.rb +1 -1
- data/lib/puppet/type/user.rb +19 -17
- data/lib/puppet/type/yumrepo.rb +20 -0
- data/lib/puppet/util.rb +109 -22
- data/lib/puppet/util/autoload.rb +16 -11
- data/lib/puppet/util/checksums.rb +74 -31
- data/lib/puppet/util/execution.rb +1 -1
- data/lib/puppet/util/http_proxy.rb +72 -0
- data/lib/puppet/util/log.rb +2 -0
- data/lib/puppet/util/logging.rb +43 -1
- data/lib/puppet/util/monkey_patches.rb +2 -2
- data/lib/puppet/util/multi_match.rb +51 -0
- data/lib/puppet/util/network_device/cisco/device.rb +10 -2
- data/lib/puppet/util/network_device/cisco/interface.rb +21 -8
- data/lib/puppet/util/network_device/transport/ssh.rb +7 -3
- data/lib/puppet/util/network_device/transport/telnet.rb +39 -36
- data/lib/puppet/util/plist.rb +130 -0
- data/lib/puppet/util/resource_template.rb +1 -1
- data/lib/puppet/util/run_mode.rb +2 -2
- data/lib/puppet/util/skip_tags.rb +9 -0
- data/lib/puppet/util/windows/access_control_entry.rb +1 -1
- data/lib/puppet/util/windows/access_control_list.rb +3 -3
- data/lib/puppet/util/windows/adsi.rb +4 -4
- data/lib/puppet/util/windows/api_types.rb +24 -18
- data/lib/puppet/util/windows/com.rb +3 -3
- data/lib/puppet/util/windows/error.rb +1 -1
- data/lib/puppet/util/windows/file.rb +8 -8
- data/lib/puppet/util/windows/principal.rb +23 -14
- data/lib/puppet/util/windows/process.rb +78 -11
- data/lib/puppet/util/windows/registry.rb +1 -1
- data/lib/puppet/util/windows/root_certs.rb +5 -5
- data/lib/puppet/util/windows/security.rb +33 -35
- data/lib/puppet/util/windows/security_descriptor.rb +1 -1
- data/lib/puppet/util/windows/sid.rb +42 -4
- data/lib/puppet/util/windows/taskscheduler.rb +15 -15
- data/lib/puppet/util/windows/user.rb +10 -10
- data/lib/puppet/vendor/deep_merge/deep_merge.gemspec +1 -1
- data/lib/puppet/vendor/pathspec/LICENSE +2 -2
- data/lib/puppet/vendor/pathspec/README.md +1 -1
- data/lib/puppet/vendor/rgen/README.rdoc +1 -1
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +14 -0
- data/lib/puppet/version.rb +1 -1
- data/lib/semver.rb +17 -1
- data/man/man5/puppet.conf.5 +12 -12
- data/man/man8/extlookup2hiera.8 +1 -1
- data/man/man8/puppet-agent.8 +2 -2
- data/man/man8/puppet-apply.8 +2 -2
- data/man/man8/puppet-ca.8 +2 -2
- data/man/man8/puppet-catalog.8 +2 -2
- data/man/man8/puppet-cert.8 +2 -2
- data/man/man8/puppet-certificate.8 +2 -2
- data/man/man8/puppet-certificate_request.8 +2 -2
- data/man/man8/puppet-certificate_revocation_list.8 +2 -2
- data/man/man8/puppet-config.8 +3 -3
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +2 -2
- data/man/man8/puppet-facts.8 +2 -2
- data/man/man8/puppet-file.8 +2 -2
- data/man/man8/puppet-filebucket.8 +2 -2
- data/man/man8/puppet-help.8 +2 -2
- data/man/man8/puppet-inspect.8 +2 -2
- data/man/man8/puppet-key.8 +2 -2
- data/man/man8/puppet-man.8 +2 -2
- data/man/man8/puppet-master.8 +2 -2
- data/man/man8/puppet-module.8 +9 -9
- data/man/man8/puppet-node.8 +2 -2
- data/man/man8/puppet-parser.8 +2 -2
- data/man/man8/puppet-plugin.8 +2 -2
- data/man/man8/puppet-report.8 +2 -2
- data/man/man8/puppet-resource.8 +2 -2
- data/man/man8/puppet-resource_type.8 +2 -2
- data/man/man8/puppet-status.8 +3 -3
- data/man/man8/puppet.8 +1 -1
- data/spec/fixtures/module.tar.gz +0 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/bad_data/lib/puppet/functions/bad_data/data.rb +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/bad_data/manifests/init.pp +0 -1
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_json/data/empty.json +0 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_json/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_json/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/data/first.json +2 -1
- data/spec/fixtures/unit/module/trailing-comma.json +1 -1
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/manifests/init.pp +3 -1
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/types/zero.pp +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/types/withuseeone.pp +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/types/withuseezero.pp +1 -0
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-broken-notices.txt +187 -0
- data/spec/fixtures/unit/provider/sshkey/parsed/sample_with_blank_lines +8 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_fetch_if_not_on_the_local_disk.yml +205 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_not_update_if_content_on_disk_is_up-to-date.yml +213 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +213 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_mtime_is_older_on_disk.yml +205 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +197 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_not_on_the_local_disk.yml +205 -0
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_not_update_if_mtime_is_newer_on_disk.yml +205 -0
- data/spec/integration/defaults_spec.rb +14 -2
- data/spec/integration/file_system/uniquefile_spec.rb +29 -0
- data/spec/integration/module_tool/tar/mini_spec.rb +28 -0
- data/spec/integration/node/environment_spec.rb +13 -0
- data/spec/integration/parser/dynamic_scoping_spec.rb +67 -0
- data/spec/integration/parser/parameter_defaults_spec.rb +336 -0
- data/spec/integration/parser/undef_param_spec.rb +8 -0
- data/spec/integration/provider/yumrepo_spec.rb +1 -1
- data/spec/integration/test/test_helper_spec.rb +28 -0
- data/spec/integration/transaction/report_spec.rb +16 -0
- data/spec/integration/transaction_spec.rb +11 -0
- data/spec/integration/type/file_spec.rb +194 -4
- data/spec/integration/type/package_spec.rb +5 -1
- data/spec/integration/type/tidy_spec.rb +21 -9
- data/spec/integration/util/execution_spec.rb +22 -0
- data/spec/integration/util/windows/principal_spec.rb +90 -4
- data/spec/integration/util/windows/process_spec.rb +31 -0
- data/spec/integration/util/windows/security_spec.rb +6 -6
- data/spec/integration/util/windows/user_spec.rb +1 -1
- data/spec/integration/util_spec.rb +49 -27
- data/spec/lib/puppet_spec/compiler.rb +17 -0
- data/spec/lib/puppet_spec/files.rb +2 -2
- data/spec/lib/puppet_spec/pops.rb +13 -0
- data/spec/shared_behaviours/iterative_functions.rb +1 -1
- data/spec/shared_contexts/types_setup.rb +96 -0
- data/spec/unit/agent_spec.rb +1 -0
- data/spec/unit/application/agent_spec.rb +10 -0
- data/spec/unit/application/apply_spec.rb +9 -0
- data/spec/unit/configurer/downloader_spec.rb +5 -5
- data/spec/unit/configurer_spec.rb +271 -39
- data/spec/unit/data_providers/hiera_interpolation_spec.rb +57 -0
- data/spec/unit/defaults_spec.rb +15 -0
- data/spec/unit/environments_spec.rb +24 -4
- data/spec/unit/face/parser_spec.rb +43 -2
- data/spec/unit/file_serving/http_metadata_spec.rb +85 -0
- data/spec/unit/file_serving/metadata_spec.rb +50 -0
- data/spec/unit/file_serving/terminus_selector_spec.rb +12 -2
- data/spec/unit/file_system_spec.rb +26 -0
- data/spec/unit/functions/assert_type_spec.rb +36 -2
- data/spec/unit/functions/defined_spec.rb +2 -2
- data/spec/unit/functions/epp_spec.rb +11 -3
- data/spec/unit/functions/lookup_spec.rb +58 -13
- data/spec/unit/functions/regsubst_spec.rb +1 -1
- data/spec/unit/functions/reverse_each_spec.rb +108 -0
- data/spec/unit/functions/step_spec.rb +113 -0
- data/spec/unit/functions/type_spec.rb +35 -0
- data/spec/unit/functions4_spec.rb +61 -5
- data/spec/unit/indirector/catalog/compiler_spec.rb +705 -4
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +1 -1
- data/spec/unit/indirector/indirection_spec.rb +1 -1
- data/spec/unit/info_service_spec.rb +94 -32
- data/spec/unit/module_spec.rb +14 -0
- data/spec/unit/module_tool/applications/builder_spec.rb +4 -4
- data/spec/unit/network/authstore_spec.rb +1 -1
- data/spec/unit/network/http/connection_spec.rb +1 -0
- data/spec/unit/network/http/pool_spec.rb +30 -0
- data/spec/unit/node_spec.rb +1 -1
- data/spec/unit/parser/compiler_spec.rb +16 -0
- data/spec/unit/parser/scope_spec.rb +28 -11
- data/spec/unit/pops/evaluator/access_ops_spec.rb +3 -3
- data/spec/unit/pops/evaluator/comparison_ops_spec.rb +3 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +7 -1
- data/spec/unit/pops/evaluator/evaluator_rspec_helper.rb +4 -4
- data/spec/unit/pops/evaluator/json_strict_literal_evaluator_spec.rb +63 -0
- data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +6 -0
- data/spec/unit/pops/loaders/dependency_loader_spec.rb +53 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +44 -1
- data/spec/unit/pops/parser/lexer2_spec.rb +112 -3
- data/spec/unit/pops/parser/parse_calls_spec.rb +8 -0
- data/spec/unit/pops/parser/parser_spec.rb +10 -0
- data/spec/unit/pops/parser/source_pos_adapter_spec.rb +26 -0
- data/spec/unit/pops/types/iterable_spec.rb +262 -0
- data/spec/unit/pops/types/recursion_guard_spec.rb +91 -0
- data/spec/unit/pops/types/type_acceptor_spec.rb +105 -0
- data/spec/unit/pops/types/type_asserter_spec.rb +43 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +275 -373
- data/spec/unit/pops/types/type_formatter_spec.rb +280 -0
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +152 -0
- data/spec/unit/pops/types/type_parser_spec.rb +58 -13
- data/spec/unit/pops/types/types_spec.rb +241 -0
- data/spec/unit/pops/validator/validator_spec.rb +100 -43
- data/spec/unit/provider/cron/parsed_spec.rb +1 -0
- data/spec/unit/provider/macauthorization_spec.rb +5 -2
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +14 -19
- data/spec/unit/provider/package/appdmg_spec.rb +3 -3
- data/spec/unit/provider/package/dnf_spec.rb +16 -0
- data/spec/unit/provider/package/pip3_spec.rb +60 -42
- data/spec/unit/provider/package/pip_spec.rb +47 -34
- data/spec/unit/provider/package/pkgdmg_spec.rb +18 -9
- data/spec/unit/provider/package/pkgng_spec.rb +4 -2
- data/spec/unit/provider/package/yum_spec.rb +11 -0
- data/spec/unit/provider/package/zypper_spec.rb +14 -0
- data/spec/unit/provider/service/launchd_spec.rb +17 -35
- data/spec/unit/provider/service/systemd_spec.rb +7 -0
- data/spec/unit/provider/sshkey/parsed_spec.rb +20 -19
- data/spec/unit/provider/user/directoryservice_spec.rb +40 -59
- data/spec/unit/resource/capability_finder_spec.rb +28 -15
- data/spec/unit/resource/catalog_spec.rb +33 -1
- data/spec/unit/resource/type_spec.rb +149 -7
- data/spec/unit/resource_spec.rb +96 -57
- data/spec/unit/settings/environment_conf_spec.rb +18 -1
- data/spec/unit/ssl/certificate_revocation_list_spec.rb +3 -3
- data/spec/unit/transaction/report_spec.rb +27 -0
- data/spec/unit/transaction/resource_harness_spec.rb +0 -47
- data/spec/unit/transaction_spec.rb +5 -0
- data/spec/unit/type/file/checksum_spec.rb +6 -0
- data/spec/unit/type/file/checksum_value_spec.rb +286 -0
- data/spec/unit/type/file/content_spec.rb +12 -193
- data/spec/unit/type/file/source_spec.rb +211 -119
- data/spec/unit/type/file_spec.rb +133 -34
- data/spec/unit/type/interface_spec.rb +32 -0
- data/spec/unit/type/macauthorization_spec.rb +4 -1
- data/spec/unit/type/yumrepo_spec.rb +2 -2
- data/spec/unit/util/filetype_spec.rb +1 -1
- data/spec/unit/util/http_proxy_spec.rb +2 -2
- data/spec/unit/util/log/destinations_spec.rb +0 -2
- data/spec/unit/util/logging_spec.rb +69 -0
- data/spec/unit/util/multi_match_spec.rb +39 -0
- data/spec/unit/util/network_device/cisco/device_spec.rb +253 -216
- data/spec/unit/util/network_device/transport/telnet_spec.rb +60 -58
- data/spec/unit/util/plist_spec.rb +110 -0
- data/spec/unit/util/resource_template_spec.rb +2 -2
- data/spec/unit/util/run_mode_spec.rb +27 -3
- data/spec/unit/util/windows/adsi_spec.rb +4 -4
- data/spec/unit/util/windows/api_types_spec.rb +42 -0
- data/spec/unit/util/windows/security_descriptor_spec.rb +3 -3
- data/spec/unit/util/windows/sid_spec.rb +1 -1
- data/spec/unit/util_spec.rb +123 -13
- data/tasks/cfpropertylist.rake +15 -0
- metadata +114 -26
- data/lib/puppet/vendor/load_plist.rb +0 -1
- data/lib/puppet/vendor/plist/CHANGELOG +0 -82
- data/lib/puppet/vendor/plist/MIT-LICENSE +0 -21
- data/lib/puppet/vendor/plist/PUPPET_README.md +0 -6
- data/lib/puppet/vendor/plist/README +0 -36
- data/lib/puppet/vendor/plist/Rakefile +0 -144
- data/lib/puppet/vendor/plist/docs/USAGE +0 -104
- data/lib/puppet/vendor/plist/docs/jamis-template.rb +0 -591
- data/lib/puppet/vendor/plist/lib/plist.rb +0 -22
- data/lib/puppet/vendor/plist/lib/plist/generator.rb +0 -224
- data/lib/puppet/vendor/plist/lib/plist/parser.rb +0 -225
- data/lib/puppet/vendor/plist/test/assets/AlbumData.xml +0 -203
- data/lib/puppet/vendor/plist/test/assets/Cookies.plist +0 -104
- data/lib/puppet/vendor/plist/test/assets/commented.plist +0 -9
- data/lib/puppet/vendor/plist/test/assets/example_data.bin +0 -0
- data/lib/puppet/vendor/plist/test/assets/example_data.jpg +0 -0
- data/lib/puppet/vendor/plist/test/assets/example_data.plist +0 -259
- data/lib/puppet/vendor/plist/test/assets/test_data_elements.plist +0 -24
- data/lib/puppet/vendor/plist/test/assets/test_empty_key.plist +0 -13
- data/lib/puppet/vendor/plist/test/test_data_elements.rb +0 -115
- data/lib/puppet/vendor/plist/test/test_generator.rb +0 -59
- data/lib/puppet/vendor/plist/test/test_generator_basic_types.rb +0 -58
- data/lib/puppet/vendor/plist/test/test_generator_collections.rb +0 -82
- data/lib/puppet/vendor/plist/test/test_parser.rb +0 -90
@@ -1,11 +1,26 @@
|
|
1
|
+
require_relative 'iterable'
|
2
|
+
require_relative 'enumeration'
|
3
|
+
require_relative 'recursion_guard'
|
4
|
+
require_relative 'type_acceptor'
|
5
|
+
require_relative 'type_asserter'
|
6
|
+
require_relative 'type_assertion_error'
|
7
|
+
require_relative 'type_formatter'
|
8
|
+
require_relative 'type_calculator'
|
9
|
+
require_relative 'type_factory'
|
10
|
+
require_relative 'type_parser'
|
11
|
+
require_relative 'class_loader'
|
12
|
+
require_relative 'type_mismatch_describer'
|
13
|
+
|
1
14
|
require 'rgen/metamodel_builder'
|
2
15
|
|
16
|
+
module Puppet::Pops
|
17
|
+
module Types
|
3
18
|
# The Types model is a model of Puppet Language types.
|
4
19
|
#
|
5
20
|
# The exact relationship between types is not visible in this model wrt. the PDataType which is an abstraction
|
6
21
|
# 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 {
|
8
|
-
# be used to answer questions about types. The {
|
22
|
+
# infer the type by simply looking at the inheritance hierarchy. The {TypeCalculator} should
|
23
|
+
# be used to answer questions about types. The {TypeFactory} should be used to create an instance
|
9
24
|
# of a type whenever one is needed.
|
10
25
|
#
|
11
26
|
# The implementation of the Types model contains methods that are required for the type objects to behave as
|
@@ -14,1535 +29,2330 @@ require 'rgen/metamodel_builder'
|
|
14
29
|
#
|
15
30
|
# @api public
|
16
31
|
#
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
# TODO: See PUP-2978 for possible performance optimization
|
33
|
+
class TypedModelObject < Object
|
34
|
+
include Visitable
|
35
|
+
include Adaptable
|
36
|
+
end
|
37
|
+
|
38
|
+
# Base type for all types
|
39
|
+
# @api public
|
40
|
+
#
|
41
|
+
class PAnyType < TypedModelObject
|
42
|
+
# Accept a visitor that will be sent the message `visit`, once with `self` as the
|
43
|
+
# argument. The visitor will then visit all types that this type contains.
|
44
|
+
#
|
45
|
+
def accept(visitor, guard)
|
46
|
+
visitor.visit(self, guard)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Checks if _o_ is a type that is assignable to this type.
|
50
|
+
# If _o_ is a `Class` then it is first converted to a type.
|
51
|
+
# If _o_ is a Variant, then it is considered assignable when all its types are assignable
|
52
|
+
#
|
53
|
+
# The check for assignable must be guarded against self recursion since `self`, the given type _o_,
|
54
|
+
# or both, might be a `TypeAlias`. The initial caller of this method will typically never care
|
55
|
+
# about this and hence pass only the first argument, but as soon as a check of a contained type
|
56
|
+
# encounters a `TypeAlias`, then a `RecursionGuard` instance is created and passed on in all
|
57
|
+
# subsequent calls. The recursion is allowed to continue until self recursion has been detected in
|
58
|
+
# both `self` and in the given type. At that point the given type is considered to be assignable
|
59
|
+
# to `self` since all checks up to that point were positive.
|
60
|
+
#
|
61
|
+
# @param o [Class,PAnyType] the class or type to test
|
62
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
63
|
+
# @return [Boolean] `true` when _o_ is assignable to this type
|
64
|
+
# @api public
|
65
|
+
def assignable?(o, guard = nil)
|
66
|
+
case o
|
67
|
+
when Class
|
68
|
+
# Safe to call _assignable directly since a Class never is a Unit or Variant
|
69
|
+
_assignable?(TypeCalculator.singleton.type(o), guard)
|
70
|
+
when PUnitType
|
71
|
+
true
|
72
|
+
when PTypeAliasType
|
73
|
+
# An alias may contain self recursive constructs.
|
74
|
+
if o.self_recursion?
|
75
|
+
guard ||= RecursionGuard.new
|
76
|
+
if guard.add_that(o) == RecursionGuard::SELF_RECURSION_IN_BOTH
|
77
|
+
# Recursion detected both in self and other. This means that other is assignable
|
78
|
+
# to self. This point would not have been reached otherwise
|
40
79
|
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
80
|
else
|
51
|
-
|
81
|
+
assignable?(o.resolved_type, guard)
|
52
82
|
end
|
53
|
-
|
83
|
+
else
|
84
|
+
assignable?(o.resolved_type, guard)
|
85
|
+
end
|
86
|
+
when PVariantType
|
87
|
+
# Assignable if all contained types are assignable
|
88
|
+
o.types.all? { |vt| assignable?(vt, guard) }
|
89
|
+
when PNotUndefType
|
90
|
+
if !(o.type.nil? || o.type.assignable?(PUndefType::DEFAULT))
|
91
|
+
assignable?(o.type, guard)
|
92
|
+
else
|
93
|
+
_assignable?(o, guard)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
_assignable?(o, guard)
|
97
|
+
end
|
98
|
+
end
|
54
99
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
100
|
+
# Returns `true` if this instance is a callable that accepts the given _args_
|
101
|
+
#
|
102
|
+
# @param args [PAnyType] the arguments to test
|
103
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
104
|
+
# @return [Boolean] `true` if this instance is a callable that accepts the given _args_
|
105
|
+
def callable?(args, guard = nil)
|
106
|
+
args.is_a?(PAnyType) && kind_of_callable? && args.callable_args?(self, guard)
|
107
|
+
end
|
61
108
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
109
|
+
# Returns `true` if this instance is considered valid as arguments to the given `callable`
|
110
|
+
# @param callable [PAnyType] the callable
|
111
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
112
|
+
# @return [Boolean] `true` if this instance is considered valid as arguments to the given `callable`
|
113
|
+
# @api private
|
114
|
+
def callable_args?(callable, guard)
|
115
|
+
false
|
116
|
+
end
|
68
117
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
118
|
+
# Generalizes value specific types. Types that are not value specific will return `self` otherwise
|
119
|
+
# the generalized type is returned.
|
120
|
+
#
|
121
|
+
# @return [PAnyType] The generalized type
|
122
|
+
# @api public
|
123
|
+
def generalize
|
124
|
+
# Applicable to all types that have no variables
|
125
|
+
self
|
126
|
+
end
|
74
127
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
128
|
+
# Normalizes the type. This does not change the characteristics of the type but it will remove duplicates
|
129
|
+
# and constructs like NotUndef[T] where T is not assignable from Undef and change Variant[*T] where all
|
130
|
+
# T are enums into an Enum.
|
131
|
+
#
|
132
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
133
|
+
# @return [PAnyType] The iterable type that this type is assignable to or `nil`
|
134
|
+
# @api public
|
135
|
+
def normalize(guard = nil)
|
136
|
+
self
|
137
|
+
end
|
84
138
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
139
|
+
# Responds `true` for all callables, variants of callables and unless _optional_ is
|
140
|
+
# false, all optional callables.
|
141
|
+
# @param optional [Boolean]
|
142
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
143
|
+
# @return [Boolean] `true`if this type is considered callable
|
144
|
+
# @api private
|
145
|
+
def kind_of_callable?(optional = true, guard = nil)
|
146
|
+
false
|
147
|
+
end
|
92
148
|
|
93
|
-
|
94
|
-
|
95
|
-
|
149
|
+
# Returns `true` if an instance of this type is iterable, `false` otherwise
|
150
|
+
# The method #iterable_type must produce a `PIterableType` instance when this
|
151
|
+
# method returns `true`
|
152
|
+
#
|
153
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
154
|
+
# @return [Boolean] flag to indicate if instances of this type is iterable.
|
155
|
+
def iterable?(guard = nil)
|
156
|
+
false
|
157
|
+
end
|
96
158
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
159
|
+
# Returns the `PIterableType` that this type should be assignable to, or `nil` if no such type exists.
|
160
|
+
# A type that returns a `PIterableType` must respond `true` to `#iterable?`.
|
161
|
+
#
|
162
|
+
# @example
|
163
|
+
# Any Collection[T] is assignable to an Iterable[T]
|
164
|
+
# A String is assignable to an Iterable[String] iterating over the strings characters
|
165
|
+
# An Integer is assignable to an Iterable[Integer] iterating over the 'times' enumerator
|
166
|
+
# A Type[T] is assignable to an Iterable[Type[T]] if T is an Integer or Enum
|
167
|
+
#
|
168
|
+
# @param guard [RecursionGuard] guard against recursion. Only used by internal calls
|
169
|
+
# @return [PIterableType,nil] The iterable type that this type is assignable to or `nil`
|
170
|
+
# @api private
|
171
|
+
def iterable_type(guard = nil)
|
172
|
+
nil
|
173
|
+
end
|
102
174
|
|
103
|
-
|
104
|
-
|
105
|
-
|
175
|
+
def hash
|
176
|
+
self.class.hash
|
177
|
+
end
|
106
178
|
|
107
|
-
|
179
|
+
# Returns true if the given argument _o_ is an instance of this type
|
180
|
+
# @return [Boolean]
|
181
|
+
def instance?(o)
|
182
|
+
true
|
183
|
+
end
|
108
184
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
def simple_name
|
113
|
-
n = self.class.name
|
114
|
-
n[n.rindex('::')+3..n.size-5]
|
115
|
-
end
|
185
|
+
def eql?(o)
|
186
|
+
self.class == o.class
|
187
|
+
end
|
116
188
|
|
117
|
-
|
118
|
-
|
119
|
-
|
189
|
+
def ==(o)
|
190
|
+
eql?(o)
|
191
|
+
end
|
120
192
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
193
|
+
# Strips the class name from all module prefixes, the leading 'P' and the ending 'Type'. I.e.
|
194
|
+
# an instance of PVariantType will return 'Variant'
|
195
|
+
# @return [String] the simple name of this type
|
196
|
+
def simple_name
|
197
|
+
n = self.class.name
|
198
|
+
n[n.rindex('::')+3..n.size-5]
|
199
|
+
end
|
125
200
|
|
126
|
-
|
201
|
+
def to_alias_expanded_s
|
202
|
+
TypeFormatter.new.alias_expanded_string(self)
|
203
|
+
end
|
127
204
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
205
|
+
def to_s
|
206
|
+
TypeFormatter.string(self)
|
207
|
+
end
|
132
208
|
|
133
|
-
|
209
|
+
# The default instance of this type. Each type in the type system has this constant
|
210
|
+
# declared.
|
211
|
+
#
|
212
|
+
DEFAULT = PAnyType.new
|
134
213
|
|
135
|
-
|
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
|
143
|
-
end
|
144
|
-
end
|
214
|
+
protected
|
145
215
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
162
|
-
end
|
163
|
-
end
|
216
|
+
# @api private
|
217
|
+
def _assignable?(o, guard)
|
218
|
+
o.is_a?(PAnyType)
|
219
|
+
end
|
164
220
|
|
221
|
+
NAME_SEGMENT_SEPARATOR = '::'.freeze
|
165
222
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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]
|
223
|
+
# @api private
|
224
|
+
def class_from_string(str)
|
225
|
+
begin
|
226
|
+
str.split(NAME_SEGMENT_SEPARATOR).reduce(Object) do |memo, name_segment|
|
227
|
+
memo.const_get(name_segment)
|
177
228
|
end
|
229
|
+
rescue NameError
|
230
|
+
return nil
|
178
231
|
end
|
232
|
+
end
|
179
233
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
234
|
+
# Produces the tuple entry at the given index given a tuple type, its from/to constraints on the last
|
235
|
+
# type, and an index.
|
236
|
+
# Produces nil if the index is out of bounds
|
237
|
+
# from must be less than to, and from may not be less than 0
|
238
|
+
#
|
239
|
+
# @api private
|
240
|
+
#
|
241
|
+
def tuple_entry_at(tuple_t, from, to, index)
|
242
|
+
regular = (tuple_t.types.size - 1)
|
243
|
+
if index < regular
|
244
|
+
tuple_t.types[index]
|
245
|
+
elsif index < regular + to
|
246
|
+
# in the varargs part
|
247
|
+
tuple_t.types[-1]
|
248
|
+
else
|
249
|
+
nil
|
250
|
+
end
|
251
|
+
end
|
189
252
|
|
190
|
-
def instance?(o)
|
191
|
-
if o.is_a?(PAnyType)
|
192
|
-
type.nil? || type.assignable?(o)
|
193
|
-
else
|
194
|
-
assignable?(TypeCalculator.infer(o))
|
195
|
-
end
|
196
|
-
end
|
197
253
|
|
198
|
-
|
199
|
-
|
200
|
-
|
254
|
+
# Transform size_type to min, max
|
255
|
+
# if size_type == nil the constraint is 1,1
|
256
|
+
# if size_type.from == nil min size = 1
|
257
|
+
# if size_type.to == nil max size == Infinity
|
258
|
+
#
|
259
|
+
# @api private
|
260
|
+
def type_to_range(size_type)
|
261
|
+
return [1,1] if size_type.nil?
|
262
|
+
from = size_type.from
|
263
|
+
to = size_type.to
|
264
|
+
[from.nil? ? 1 : from, to.nil? ? Float::INFINITY : to]
|
265
|
+
end
|
201
266
|
|
202
|
-
|
203
|
-
|
204
|
-
|
267
|
+
# Applies a transformation by sending the given _method_ and _method_args_ to each of the types of the given array
|
268
|
+
# and collecting the results in a new array. If all transformation calls returned the type instance itself (i.e. no
|
269
|
+
# transformation took place), then this method will return `self`. If a transformation did occur, then this method
|
270
|
+
# will either return the transformed array or in case a block was given, the result of calling a given block with
|
271
|
+
# the transformed array.
|
272
|
+
#
|
273
|
+
# @param types [Array<PAnyType>] the array of types to transform
|
274
|
+
# @param method [Symbol] The method to call on each type
|
275
|
+
# @param method_args [Object] The arguments to pass to the method, if any
|
276
|
+
# @return [Object] self, the transformed array, or the result of calling a given block with the transformed array
|
277
|
+
# @yieldparam altered_types [Array<PAnyType>] the altered type array
|
278
|
+
# @api private
|
279
|
+
def alter_type_array(types, method, *method_args)
|
280
|
+
modified = false
|
281
|
+
modified_types = types.map do |t|
|
282
|
+
t_mod = t.send(method, *method_args)
|
283
|
+
modified = !t.equal?(t_mod) unless modified
|
284
|
+
t_mod
|
285
|
+
end
|
286
|
+
if modified
|
287
|
+
block_given? ? yield(modified_types) : modified_types
|
288
|
+
else
|
289
|
+
self
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
205
293
|
|
206
|
-
|
207
|
-
|
208
|
-
|
294
|
+
# @abstract Encapsulates common behavior for a type that contains one type
|
295
|
+
# @api public
|
296
|
+
class PTypeWithContainedType < PAnyType
|
297
|
+
attr_reader :type
|
209
298
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
end
|
299
|
+
def initialize(type)
|
300
|
+
@type = type
|
301
|
+
end
|
214
302
|
|
215
|
-
|
303
|
+
def accept(visitor, guard)
|
304
|
+
super
|
305
|
+
@type.accept(visitor, guard) unless @type.nil?
|
306
|
+
end
|
216
307
|
|
217
|
-
|
308
|
+
def generalize
|
309
|
+
if @type.nil?
|
310
|
+
self.class::DEFAULT
|
311
|
+
else
|
312
|
+
ge_type = @type.generalize
|
313
|
+
@type.equal?(ge_type) ? self : self.class.new(ge_type)
|
314
|
+
end
|
315
|
+
end
|
218
316
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
317
|
+
def normalize(guard = nil)
|
318
|
+
if @type.nil?
|
319
|
+
self.class::DEFAULT
|
320
|
+
else
|
321
|
+
ne_type = @type.normalize(guard)
|
322
|
+
@type.equal?(ne_type) ? self : self.class.new(ne_type)
|
226
323
|
end
|
324
|
+
end
|
227
325
|
|
228
|
-
|
229
|
-
|
326
|
+
def hash
|
327
|
+
self.class.hash * 31 * @type.hash
|
328
|
+
end
|
230
329
|
|
231
|
-
|
232
|
-
|
233
|
-
|
330
|
+
def eql?(o)
|
331
|
+
self.class == o.class && @type == o.type
|
332
|
+
end
|
333
|
+
end
|
234
334
|
|
235
|
-
|
236
|
-
|
237
|
-
|
335
|
+
# The type of types.
|
336
|
+
# @api public
|
337
|
+
#
|
338
|
+
class PType < PTypeWithContainedType
|
339
|
+
def instance?(o)
|
340
|
+
if o.is_a?(PAnyType)
|
341
|
+
type.nil? || type.assignable?(o)
|
342
|
+
else
|
343
|
+
assignable?(TypeCalculator.infer(o))
|
344
|
+
end
|
345
|
+
end
|
238
346
|
|
239
|
-
|
240
|
-
|
241
|
-
|
347
|
+
def iterable?(guard = nil)
|
348
|
+
case @type
|
349
|
+
when PEnumType
|
350
|
+
true
|
351
|
+
when PIntegerType
|
352
|
+
@type.finite_range?
|
353
|
+
else
|
354
|
+
false
|
355
|
+
end
|
356
|
+
end
|
242
357
|
|
243
|
-
|
244
|
-
|
245
|
-
|
358
|
+
def iterable_type(guard = nil)
|
359
|
+
# The types PIntegerType and PEnumType are Iterable
|
360
|
+
case @type
|
361
|
+
when PEnumType
|
362
|
+
# @type describes the element type perfectly since the iteration is made over the
|
363
|
+
# contained choices.
|
364
|
+
PIterableType.new(@type)
|
365
|
+
when PIntegerType
|
366
|
+
# @type describes the element type perfectly since the iteration is made over the
|
367
|
+
# specified range.
|
368
|
+
@type.finite_range? ? PIterableType.new(@type) : nil
|
369
|
+
else
|
370
|
+
nil
|
371
|
+
end
|
372
|
+
end
|
246
373
|
|
247
|
-
|
248
|
-
|
249
|
-
|
374
|
+
def eql?(o)
|
375
|
+
self.class == o.class && @type == o.type
|
376
|
+
end
|
250
377
|
|
251
|
-
|
378
|
+
def simple_name
|
379
|
+
# since this the class is inconsistently named PType and not PTypeType
|
380
|
+
'Type'
|
381
|
+
end
|
252
382
|
|
253
|
-
|
383
|
+
DEFAULT = PType.new(nil)
|
254
384
|
|
255
|
-
|
256
|
-
def _assignable?(o)
|
257
|
-
o.is_a?(PAnyType) && !o.assignable?(PUndefType::DEFAULT) && (@type.nil? || @type.assignable?(o))
|
258
|
-
end
|
259
|
-
end
|
385
|
+
protected
|
260
386
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
387
|
+
# @api private
|
388
|
+
def _assignable?(o, guard)
|
389
|
+
return false unless o.is_a?(PType)
|
390
|
+
return true if @type.nil? # wide enough to handle all types
|
391
|
+
return false if o.type.nil? # wider than t
|
392
|
+
@type.assignable?(o.type, guard)
|
393
|
+
end
|
394
|
+
end
|
267
395
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
end
|
396
|
+
class PNotUndefType < PTypeWithContainedType
|
397
|
+
def initialize(type = nil)
|
398
|
+
super(type.class == PAnyType ? nil : type)
|
399
|
+
end
|
273
400
|
|
274
|
-
|
401
|
+
def instance?(o)
|
402
|
+
!(o.nil? || o == :undef) && (@type.nil? || @type.instance?(o))
|
403
|
+
end
|
275
404
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
405
|
+
def normalize(guard = nil)
|
406
|
+
n = super
|
407
|
+
if n.type.nil?
|
408
|
+
n
|
409
|
+
else
|
410
|
+
if n.type.is_a?(POptionalType)
|
411
|
+
# No point in having an optional in a NotUndef
|
412
|
+
PNotUndef.new(n.type.type).normalize
|
413
|
+
elsif !n.type.assignable?(PUndefType::DEFAULT)
|
414
|
+
# THe type is NotUndef anyway, so it can be stripped of
|
415
|
+
n.type
|
416
|
+
else
|
417
|
+
n
|
418
|
+
end
|
281
419
|
end
|
420
|
+
end
|
282
421
|
|
283
|
-
|
284
|
-
# @api private
|
285
|
-
#
|
286
|
-
class PUnitType < PAnyType
|
287
|
-
def instance?(o)
|
288
|
-
true
|
289
|
-
end
|
422
|
+
DEFAULT = PNotUndefType.new
|
290
423
|
|
291
|
-
|
424
|
+
protected
|
292
425
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
end
|
426
|
+
# @api private
|
427
|
+
def _assignable?(o, guard)
|
428
|
+
o.is_a?(PAnyType) && !o.assignable?(PUndefType::DEFAULT, guard) && (@type.nil? || @type.assignable?(o, guard))
|
429
|
+
end
|
430
|
+
end
|
299
431
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
432
|
+
# @api public
|
433
|
+
#
|
434
|
+
class PUndefType < PAnyType
|
435
|
+
def instance?(o)
|
436
|
+
o.nil? || o == :undef
|
437
|
+
end
|
306
438
|
|
307
|
-
|
439
|
+
# @api private
|
440
|
+
def callable_args?(callable_t, guard)
|
441
|
+
# if callable_t is Optional (or indeed PUndefType), this means that 'missing callable' is accepted
|
442
|
+
callable_t.assignable?(DEFAULT, guard)
|
443
|
+
end
|
308
444
|
|
309
|
-
|
310
|
-
# @api private
|
311
|
-
def _assignable?(o)
|
312
|
-
o.is_a?(PDefaultType)
|
313
|
-
end
|
314
|
-
end
|
445
|
+
DEFAULT = PUndefType.new
|
315
446
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
self.class == o.class || o.class == PVariantType && o == PVariantType::DATA
|
323
|
-
end
|
447
|
+
protected
|
448
|
+
# @api private
|
449
|
+
def _assignable?(o, guard)
|
450
|
+
o.is_a?(PUndefType)
|
451
|
+
end
|
452
|
+
end
|
324
453
|
|
325
|
-
|
326
|
-
|
327
|
-
|
454
|
+
# A type private to the type system that describes "ignored type" - i.e. "I am what you are"
|
455
|
+
# @api private
|
456
|
+
#
|
457
|
+
class PUnitType < PAnyType
|
458
|
+
def instance?(o)
|
459
|
+
true
|
460
|
+
end
|
328
461
|
|
329
|
-
|
462
|
+
DEFAULT = PUnitType.new
|
330
463
|
|
331
|
-
|
464
|
+
protected
|
465
|
+
# @api private
|
466
|
+
def _assignable?(o, guard)
|
467
|
+
true
|
468
|
+
end
|
469
|
+
end
|
332
470
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
true
|
340
|
-
when Types::PNotUndefType
|
341
|
-
assignable?(o.type || PUndefType::DEFAULT)
|
342
|
-
else
|
343
|
-
PVariantType::DATA.assignable?(o)
|
344
|
-
end
|
345
|
-
end
|
346
|
-
end
|
471
|
+
# @api public
|
472
|
+
#
|
473
|
+
class PDefaultType < PAnyType
|
474
|
+
def instance?(o)
|
475
|
+
o == :default
|
476
|
+
end
|
347
477
|
|
348
|
-
|
349
|
-
# @api public
|
350
|
-
#
|
351
|
-
class PScalarType < PAnyType
|
478
|
+
DEFAULT = PDefaultType.new
|
352
479
|
|
353
|
-
|
354
|
-
|
355
|
-
|
480
|
+
protected
|
481
|
+
# @api private
|
482
|
+
def _assignable?(o, guard)
|
483
|
+
o.is_a?(PDefaultType)
|
484
|
+
end
|
485
|
+
end
|
356
486
|
|
357
|
-
|
487
|
+
# A flexible data type, being assignable to its subtypes as well as PArrayType and PHashType with element type assignable to PDataType.
|
488
|
+
#
|
489
|
+
# @api public
|
490
|
+
#
|
491
|
+
class PDataType < PAnyType
|
492
|
+
def eql?(o)
|
493
|
+
self.class == o.class || o == PVariantType::DATA
|
494
|
+
end
|
358
495
|
|
359
|
-
|
496
|
+
def instance?(o)
|
497
|
+
PVariantType::DATA.instance?(o)
|
498
|
+
end
|
360
499
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
500
|
+
DEFAULT = PDataType.new
|
501
|
+
|
502
|
+
protected
|
503
|
+
|
504
|
+
# Data is assignable by other Data and by Array[Data] and Hash[Scalar, Data]
|
505
|
+
# @api private
|
506
|
+
def _assignable?(o, guard)
|
507
|
+
# We cannot put the NotUndefType[Data] in the @data_variant_t since that causes an endless recursion
|
508
|
+
case o
|
509
|
+
when Types::PDataType
|
510
|
+
true
|
511
|
+
when Types::PNotUndefType
|
512
|
+
assignable?(o.type || PUndefType::DEFAULT, guard)
|
513
|
+
else
|
514
|
+
PVariantType::DATA.assignable?(o, guard)
|
365
515
|
end
|
516
|
+
end
|
517
|
+
end
|
366
518
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
include Enumerable
|
519
|
+
# Type that is PDataType compatible, but is not a PCollectionType.
|
520
|
+
# @api public
|
521
|
+
#
|
522
|
+
class PScalarType < PAnyType
|
372
523
|
|
373
|
-
|
524
|
+
def instance?(o)
|
525
|
+
assignable?(TypeCalculator.infer(o))
|
526
|
+
end
|
374
527
|
|
375
|
-
|
376
|
-
@values = values.sort.freeze
|
377
|
-
end
|
528
|
+
DEFAULT = PScalarType.new
|
378
529
|
|
379
|
-
|
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
|
386
|
-
end
|
387
|
-
end
|
530
|
+
protected
|
388
531
|
|
389
|
-
|
390
|
-
|
391
|
-
|
532
|
+
# @api private
|
533
|
+
def _assignable?(o, guard)
|
534
|
+
o.is_a?(PScalarType)
|
535
|
+
end
|
536
|
+
end
|
392
537
|
|
393
|
-
|
394
|
-
|
395
|
-
|
538
|
+
# A string type describing the set of strings having one of the given values
|
539
|
+
# @api public
|
540
|
+
#
|
541
|
+
class PEnumType < PScalarType
|
542
|
+
attr_reader :values
|
396
543
|
|
397
|
-
|
544
|
+
def initialize(values)
|
545
|
+
@values = values.sort.freeze
|
546
|
+
end
|
398
547
|
|
399
|
-
|
548
|
+
# Returns Enumerator if no block is given, otherwise, calls the given
|
549
|
+
# block with each of the strings for this enum
|
550
|
+
def each(&block)
|
551
|
+
r = Iterable.on(self)
|
552
|
+
block_given? ? r.each(&block) : r
|
553
|
+
end
|
400
554
|
|
401
|
-
|
402
|
-
|
403
|
-
|
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 }}
|
414
|
-
else
|
415
|
-
false
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
555
|
+
def iterable?(guard = nil)
|
556
|
+
true
|
557
|
+
end
|
419
558
|
|
420
|
-
|
421
|
-
#
|
422
|
-
|
423
|
-
|
424
|
-
from = -Float::INFINITY if from.nil? || from == :default
|
425
|
-
to = Float::INFINITY if to.nil? || to == :default
|
426
|
-
raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
|
427
|
-
@from = from
|
428
|
-
@to = to
|
429
|
-
end
|
559
|
+
def iterable_type(guard = nil)
|
560
|
+
# An instance of an Enum is a String
|
561
|
+
PStringType::ITERABLE_TYPE
|
562
|
+
end
|
430
563
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
@from == -Float::INFINITY ? nil : @from
|
435
|
-
end
|
564
|
+
def hash
|
565
|
+
@values.hash
|
566
|
+
end
|
436
567
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
@to == Float::INFINITY ? nil : @to
|
441
|
-
end
|
568
|
+
def eql?(o)
|
569
|
+
self.class == o.class && @values == o.values
|
570
|
+
end
|
442
571
|
|
443
|
-
|
444
|
-
# @return [Float,Integer]
|
445
|
-
def numeric_from
|
446
|
-
@from
|
447
|
-
end
|
572
|
+
DEFAULT = PEnumType.new(EMPTY_ARRAY)
|
448
573
|
|
449
|
-
|
450
|
-
# @return [Float,Integer]
|
451
|
-
def numeric_to
|
452
|
-
@to
|
453
|
-
end
|
574
|
+
protected
|
454
575
|
|
455
|
-
|
456
|
-
|
457
|
-
|
576
|
+
# @api private
|
577
|
+
def _assignable?(o, guard)
|
578
|
+
return true if self == o
|
579
|
+
svalues = values
|
580
|
+
if svalues.empty?
|
581
|
+
return true if o.is_a?(PStringType) || o.is_a?(PEnumType) || o.is_a?(PPatternType)
|
582
|
+
end
|
583
|
+
case o
|
584
|
+
when PStringType
|
585
|
+
# if the set of strings are all found in the set of enums
|
586
|
+
!o.values.empty? && o.values.all? { |s| svalues.any? { |e| e == s }}
|
587
|
+
when PEnumType
|
588
|
+
!o.values.empty? && o.values.all? { |s| svalues.any? {|e| e == s }}
|
589
|
+
else
|
590
|
+
false
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
458
594
|
|
459
|
-
|
460
|
-
|
461
|
-
|
595
|
+
# @api public
|
596
|
+
#
|
597
|
+
class PNumericType < PScalarType
|
598
|
+
def initialize(from, to = Float::INFINITY)
|
599
|
+
from = -Float::INFINITY if from.nil? || from == :default
|
600
|
+
to = Float::INFINITY if to.nil? || to == :default
|
601
|
+
raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
|
602
|
+
@from = from
|
603
|
+
@to = to
|
604
|
+
end
|
462
605
|
|
463
|
-
|
464
|
-
|
465
|
-
|
606
|
+
# Checks if this numeric range intersects with another
|
607
|
+
#
|
608
|
+
# @param o [PNumericType] the range to compare with
|
609
|
+
# @return [Boolean] `true` if this range intersects with the other range
|
610
|
+
# @api public
|
611
|
+
def intersect?(o)
|
612
|
+
self.class == o.class && !(@to < o.from || o.to < @from)
|
613
|
+
end
|
466
614
|
|
467
|
-
|
468
|
-
|
469
|
-
|
615
|
+
# Returns the lower bound of the numeric range or `nil` if no lower bound is set.
|
616
|
+
# @return [Float,Integer]
|
617
|
+
def from
|
618
|
+
@from == -Float::INFINITY ? nil : @from
|
619
|
+
end
|
470
620
|
|
471
|
-
|
621
|
+
# Returns the upper bound of the numeric range or `nil` if no upper bound is set.
|
622
|
+
# @return [Float,Integer]
|
623
|
+
def to
|
624
|
+
@to == Float::INFINITY ? nil : @to
|
625
|
+
end
|
472
626
|
|
473
|
-
|
627
|
+
# Same as #from but will return `-Float::Infinity` instead of `nil` if no lower bound is set.
|
628
|
+
# @return [Float,Integer]
|
629
|
+
def numeric_from
|
630
|
+
@from
|
631
|
+
end
|
474
632
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
end
|
481
|
-
end
|
633
|
+
# Same as #to but will return `Float::Infinity` instead of `nil` if no lower bound is set.
|
634
|
+
# @return [Float,Integer]
|
635
|
+
def numeric_to
|
636
|
+
@to
|
637
|
+
end
|
482
638
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
# The integer type is enumerable when it defines a range
|
487
|
-
include Enumerable
|
639
|
+
def hash
|
640
|
+
@from.hash * 31 + @to.hash
|
641
|
+
end
|
488
642
|
|
489
|
-
|
490
|
-
|
491
|
-
|
643
|
+
def eql?(o)
|
644
|
+
self.class == o.class && @from == o.numeric_from && @to == o.numeric_to
|
645
|
+
end
|
492
646
|
|
493
|
-
|
494
|
-
|
495
|
-
|
647
|
+
def instance?(o)
|
648
|
+
o.is_a?(Numeric) && o >= @from && o <= @to
|
649
|
+
end
|
496
650
|
|
497
|
-
|
498
|
-
|
499
|
-
|
651
|
+
def unbounded?
|
652
|
+
@from == -Float::INFINITY && @to == Float::INFINITY
|
653
|
+
end
|
500
654
|
|
501
|
-
|
502
|
-
def size
|
503
|
-
return Float::INFINITY if @from == -Float::INFINITY || @to == Float::INFINITY
|
504
|
-
1+(to-from).abs
|
505
|
-
end
|
655
|
+
DEFAULT = PNumericType.new(-Float::INFINITY)
|
506
656
|
|
507
|
-
|
508
|
-
# The number may be Infinity or -Infinity.
|
509
|
-
def range
|
510
|
-
[@from, @to]
|
511
|
-
end
|
657
|
+
protected
|
512
658
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
end
|
521
|
-
end
|
659
|
+
# @api_private
|
660
|
+
def _assignable?(o, guard)
|
661
|
+
return false unless o.is_a?(self.class)
|
662
|
+
# If o min and max are within the range of t
|
663
|
+
@from <= o.numeric_from && @to >= o.numeric_to
|
664
|
+
end
|
665
|
+
end
|
522
666
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
667
|
+
# @api public
|
668
|
+
#
|
669
|
+
class PIntegerType < PNumericType
|
670
|
+
# Will respond `true` for any range that is bounded at both ends.
|
671
|
+
#
|
672
|
+
# @return [Boolean] `true` if the type describes a finite range.
|
673
|
+
def finite_range?
|
674
|
+
@from != -Float::INFINITY && @to != Float::INFINITY
|
675
|
+
end
|
529
676
|
|
530
|
-
|
531
|
-
|
677
|
+
def generalize
|
678
|
+
DEFAULT
|
679
|
+
end
|
532
680
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
def generalize
|
537
|
-
DEFAULT
|
538
|
-
end
|
681
|
+
def instance?(o)
|
682
|
+
o.is_a?(Integer) && o >= numeric_from && o <= numeric_to
|
683
|
+
end
|
539
684
|
|
540
|
-
|
541
|
-
|
542
|
-
|
685
|
+
# Checks if this range is adjacent to the given range
|
686
|
+
#
|
687
|
+
# @param o [PIntegerType] the range to compare with
|
688
|
+
# @return [Boolean] `true` if this range is adjacent to the other range
|
689
|
+
# @api public
|
690
|
+
def adjacent?(o)
|
691
|
+
o.is_a?(PIntegerType) && (@to + 1 == o.from || o.to + 1 == @from)
|
692
|
+
end
|
543
693
|
|
544
|
-
|
694
|
+
# Concatenates this range with another range provided that the ranges intersect or
|
695
|
+
# are adjacent. When that's not the case, this method will return `nil`
|
696
|
+
#
|
697
|
+
# @param o [PIntegerType] the range to concatenate with this range
|
698
|
+
# @return [PIntegerType,nil] the concatenated range or `nil` when the ranges were apart
|
699
|
+
# @api public
|
700
|
+
def merge(o)
|
701
|
+
if intersect?(o) || adjacent?(o)
|
702
|
+
min = @from <= o.from ? @from : o.from
|
703
|
+
max = @to >= o.to ? @to : o.to
|
704
|
+
PIntegerType.new(min, max)
|
705
|
+
else
|
706
|
+
nil
|
545
707
|
end
|
708
|
+
end
|
546
709
|
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
attr_reader :element_type, :size_type
|
551
|
-
|
552
|
-
def initialize(element_type, size_type = nil)
|
553
|
-
@element_type = element_type
|
554
|
-
@size_type = size_type
|
555
|
-
end
|
710
|
+
def iterable?(guard = nil)
|
711
|
+
true
|
712
|
+
end
|
556
713
|
|
557
|
-
|
558
|
-
|
559
|
-
|
714
|
+
def iterable_type(guard = nil)
|
715
|
+
# It's unknown if the iterable will be a range (min, max) or a "times" (0, max)
|
716
|
+
PIterableType.new(PIntegerType::DEFAULT)
|
717
|
+
end
|
560
718
|
|
561
|
-
|
562
|
-
|
563
|
-
|
719
|
+
# Returns Float.Infinity if one end of the range is unbound
|
720
|
+
def size
|
721
|
+
return Float::INFINITY if @from == -Float::INFINITY || @to == Float::INFINITY
|
722
|
+
1+(to-from).abs
|
723
|
+
end
|
564
724
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
725
|
+
# Returns the range as an array ordered so the smaller number is always first.
|
726
|
+
# The number may be Infinity or -Infinity.
|
727
|
+
def range
|
728
|
+
[@from, @to]
|
729
|
+
end
|
569
730
|
|
570
|
-
|
571
|
-
|
572
|
-
|
731
|
+
# Returns Enumerator if no block is given
|
732
|
+
# Returns nil if size is infinity (does not yield)
|
733
|
+
def each(&block)
|
734
|
+
r = Iterable.on(self)
|
735
|
+
block_given? ? r.each(&block) : r
|
736
|
+
end
|
573
737
|
|
574
|
-
|
575
|
-
|
576
|
-
|
738
|
+
# Returns a range where both to and from are positive numbers. Negative
|
739
|
+
# numbers are converted to zero
|
740
|
+
# @return [PIntegerType] a positive range
|
741
|
+
def to_size
|
742
|
+
@from >= 0 ? self : PIntegerType.new(0, @to < 0 ? 0 : @to)
|
743
|
+
end
|
577
744
|
|
745
|
+
DEFAULT = PIntegerType.new(-Float::INFINITY)
|
746
|
+
end
|
578
747
|
|
579
|
-
|
580
|
-
|
581
|
-
|
748
|
+
# @api public
|
749
|
+
#
|
750
|
+
class PFloatType < PNumericType
|
751
|
+
def generalize
|
752
|
+
DEFAULT
|
753
|
+
end
|
582
754
|
|
583
|
-
|
755
|
+
def instance?(o)
|
756
|
+
o.is_a?(Float) && o >= numeric_from && o <= numeric_to
|
757
|
+
end
|
584
758
|
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
from = to = o.elements.size
|
599
|
-
(@size_type || DEFAULT_SIZE).assignable?(PIntegerType.new(from, to))
|
600
|
-
else
|
601
|
-
false
|
602
|
-
end
|
603
|
-
end
|
759
|
+
# Concatenates this range with another range provided that the ranges intersect. When that's not the case, this
|
760
|
+
# method will return `nil`
|
761
|
+
#
|
762
|
+
# @param o [PFloatType] the range to concatenate with this range
|
763
|
+
# @return [PFloatType,nil] the concatenated range or `nil` when the ranges were apart
|
764
|
+
# @api public
|
765
|
+
def merge(o)
|
766
|
+
if intersect?(o)
|
767
|
+
min = @from <= o.from ? @from : o.from
|
768
|
+
max = @to >= o.to ? @to : o.to
|
769
|
+
PFloatType.new(min, max)
|
770
|
+
else
|
771
|
+
nil
|
604
772
|
end
|
773
|
+
end
|
605
774
|
|
606
|
-
|
607
|
-
|
608
|
-
class PStringType < PScalarType
|
609
|
-
attr_reader :size_type, :values
|
775
|
+
DEFAULT = PFloatType.new(-Float::INFINITY)
|
776
|
+
end
|
610
777
|
|
611
|
-
|
612
|
-
|
613
|
-
|
778
|
+
# @api public
|
779
|
+
#
|
780
|
+
class PCollectionType < PAnyType
|
781
|
+
attr_reader :element_type, :size_type
|
614
782
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
783
|
+
def initialize(element_type, size_type = nil)
|
784
|
+
@element_type = element_type
|
785
|
+
@size_type = size_type
|
786
|
+
end
|
619
787
|
|
620
|
-
|
621
|
-
|
622
|
-
|
788
|
+
def accept(visitor, guard)
|
789
|
+
super
|
790
|
+
@size_type.accept(visitor, guard) unless @size_type.nil?
|
791
|
+
@element_type.accept(visitor, guard) unless @element_type.nil?
|
792
|
+
end
|
623
793
|
|
624
|
-
|
625
|
-
|
626
|
-
|
794
|
+
def generalize
|
795
|
+
if @element_type.nil?
|
796
|
+
DEFAULT
|
797
|
+
else
|
798
|
+
ge_type = @element_type.generalize
|
799
|
+
@size_type.nil? && @element_type.equal?(ge_type) ? self : self.class.new(ge_type, nil)
|
800
|
+
end
|
801
|
+
end
|
627
802
|
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
end
|
635
|
-
end
|
636
|
-
|
637
|
-
DEFAULT = PStringType.new(nil)
|
638
|
-
NON_EMPTY = PStringType.new(PIntegerType.new(1))
|
639
|
-
|
640
|
-
protected
|
641
|
-
|
642
|
-
# @api private
|
643
|
-
def _assignable?(o)
|
644
|
-
if values.empty?
|
645
|
-
# A general string is assignable by any other string or pattern restricted string
|
646
|
-
# if the string has a size constraint it does not match since there is no reasonable way
|
647
|
-
# to compute the min/max length a pattern will match. For enum, it is possible to test that
|
648
|
-
# each enumerator value is within range
|
649
|
-
case o
|
650
|
-
when PStringType
|
651
|
-
# true if size compliant
|
652
|
-
(@size_type || PCollectionType::DEFAULT_SIZE).assignable?(o.size_type || PCollectionType::DEFAULT_SIZE)
|
653
|
-
|
654
|
-
when PPatternType
|
655
|
-
# true if size constraint is at least 0 to +Infinity (which is the same as the default)
|
656
|
-
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE)
|
657
|
-
|
658
|
-
when PEnumType
|
659
|
-
if o.values.empty?
|
660
|
-
# enum represents all enums, and thus all strings, a sized constrained string can thus not
|
661
|
-
# be assigned any enum (unless it is max size).
|
662
|
-
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE)
|
663
|
-
else
|
664
|
-
# true if all enum values are within range
|
665
|
-
orange = o.values.map(&:size).minmax
|
666
|
-
srange = (@size_type || PCollectionType::DEFAULT_SIZE).range
|
667
|
-
# If o min and max are within the range of t
|
668
|
-
srange[0] <= orange[0] && srange[1] >= orange[1]
|
669
|
-
end
|
670
|
-
else
|
671
|
-
# no other type matches string
|
672
|
-
false
|
673
|
-
end
|
674
|
-
elsif o.is_a?(PStringType)
|
675
|
-
# A specific string acts as a set of strings - must have exactly the same strings
|
676
|
-
# In this case, size does not matter since the definition is very precise anyway
|
677
|
-
values == o.values
|
678
|
-
else
|
679
|
-
# All others are false, since no other type describes the same set of specific strings
|
680
|
-
false
|
681
|
-
end
|
682
|
-
end
|
803
|
+
def normalize(guard = nil)
|
804
|
+
if @element_type.nil?
|
805
|
+
DEFAULT
|
806
|
+
else
|
807
|
+
ne_type = @element_type.normalize(guard)
|
808
|
+
@element_type.equal?(ne_type) ? self : self.class.new(ne_type, @size_type)
|
683
809
|
end
|
810
|
+
end
|
684
811
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
attr_reader :pattern
|
812
|
+
def instance?(o)
|
813
|
+
assignable?(TypeCalculator.infer(o))
|
814
|
+
end
|
689
815
|
|
690
|
-
|
691
|
-
|
692
|
-
|
816
|
+
# Returns an array with from (min) size to (max) size
|
817
|
+
def size_range
|
818
|
+
(@size_type || DEFAULT_SIZE).range
|
819
|
+
end
|
693
820
|
|
694
|
-
|
695
|
-
|
696
|
-
|
821
|
+
def hash
|
822
|
+
@element_type.hash * 31 + @size_type.hash
|
823
|
+
end
|
697
824
|
|
698
|
-
|
699
|
-
|
700
|
-
|
825
|
+
def iterable?(guard = nil)
|
826
|
+
true
|
827
|
+
end
|
701
828
|
|
702
|
-
|
703
|
-
|
704
|
-
|
829
|
+
def iterable_type(guard = nil)
|
830
|
+
@element_type.nil? ? PIterableType::DEFAULT : PIterableType.new(@element_type)
|
831
|
+
end
|
832
|
+
|
833
|
+
def eql?(o)
|
834
|
+
self.class == o.class && @element_type == o.element_type && @size_type == o.size_type
|
835
|
+
end
|
705
836
|
|
706
|
-
DEFAULT = PRegexpType.new(nil)
|
707
837
|
|
708
|
-
|
838
|
+
DEFAULT_SIZE = PIntegerType.new(0)
|
839
|
+
ZERO_SIZE = PIntegerType.new(0, 0)
|
840
|
+
DEFAULT = PCollectionType.new(nil)
|
709
841
|
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
842
|
+
protected
|
843
|
+
|
844
|
+
# @api private
|
845
|
+
#
|
846
|
+
def _assignable?(o, guard)
|
847
|
+
case o
|
848
|
+
when PCollectionType
|
849
|
+
(@size_type || DEFAULT_SIZE).assignable?(o.size_type || DEFAULT_SIZE, guard)
|
850
|
+
when PTupleType
|
851
|
+
# compute the tuple's min/max size, and check if that size matches
|
852
|
+
from, to = type_to_range(o.size_type)
|
853
|
+
from = o.types.size - 1 + from
|
854
|
+
to = o.types.size - 1 + to
|
855
|
+
(@size_type || DEFAULT_SIZE).assignable?(PIntegerType.new(from, to), guard)
|
856
|
+
when PStructType
|
857
|
+
from = to = o.elements.size
|
858
|
+
(@size_type || DEFAULT_SIZE).assignable?(PIntegerType.new(from, to), guard)
|
859
|
+
else
|
860
|
+
false
|
715
861
|
end
|
862
|
+
end
|
863
|
+
end
|
716
864
|
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
#
|
722
|
-
class PPatternType < PScalarType
|
723
|
-
attr_reader :patterns
|
865
|
+
class PIterableType < PTypeWithContainedType
|
866
|
+
def element_type
|
867
|
+
@type
|
868
|
+
end
|
724
869
|
|
725
|
-
|
726
|
-
|
870
|
+
def instance?(o)
|
871
|
+
if @type.nil? || @type.assignable?(PAnyType::DEFAULT)
|
872
|
+
# Any element_type will do
|
873
|
+
case o
|
874
|
+
when Iterable, String, Hash, Array, Range, PEnumType
|
875
|
+
true
|
876
|
+
when Integer
|
877
|
+
o >= 0
|
878
|
+
when PIntegerType
|
879
|
+
o.finite_range?
|
880
|
+
else
|
881
|
+
false
|
727
882
|
end
|
883
|
+
else
|
884
|
+
assignable?(TypeCalculator.infer(o))
|
885
|
+
end
|
886
|
+
end
|
728
887
|
|
729
|
-
|
730
|
-
|
731
|
-
|
888
|
+
def iterable?(guard = nil)
|
889
|
+
true
|
890
|
+
end
|
732
891
|
|
733
|
-
|
734
|
-
|
735
|
-
|
892
|
+
def iterable_type(guard = nil)
|
893
|
+
self
|
894
|
+
end
|
736
895
|
|
737
|
-
|
896
|
+
DEFAULT = PIterableType.new(nil)
|
738
897
|
|
739
|
-
|
898
|
+
protected
|
740
899
|
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
900
|
+
# @api private
|
901
|
+
def _assignable?(o, guard)
|
902
|
+
if @type.nil? || @type.assignable?(PAnyType::DEFAULT, guard)
|
903
|
+
# Don't request the iterable_type. Since this Iterable accepts Any element, it is enough that o is iterable.
|
904
|
+
o.iterable?
|
905
|
+
else
|
906
|
+
o = o.iterable_type
|
907
|
+
o.nil? || o.element_type.nil? ? false : @type.assignable?(o.element_type, guard)
|
908
|
+
end
|
909
|
+
end
|
910
|
+
end
|
911
|
+
|
912
|
+
# @api public
|
913
|
+
#
|
914
|
+
class PIteratorType < PTypeWithContainedType
|
915
|
+
def element_type
|
916
|
+
@type
|
917
|
+
end
|
918
|
+
|
919
|
+
def instance?(o)
|
920
|
+
o.is_a?(Iterable) && (@element_type.nil? || @element_type.assignable?(o.element_type))
|
921
|
+
end
|
922
|
+
|
923
|
+
def iterable?(guard = nil)
|
924
|
+
true
|
925
|
+
end
|
926
|
+
|
927
|
+
def iterable_type(guard = nil)
|
928
|
+
@type.nil? ? PIteratbleType::DEFAULT : PIterableType.new(@element_type)
|
929
|
+
end
|
930
|
+
|
931
|
+
DEFAULT = PIteratorType.new(nil)
|
932
|
+
|
933
|
+
protected
|
934
|
+
|
935
|
+
# @api private
|
936
|
+
def _assignable?(o, guard)
|
937
|
+
o.is_a?(PIteratorType) && (@element_type.nil? || @element_type.assignable?(o.element_type, guard))
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
# @api public
|
942
|
+
#
|
943
|
+
class PStringType < PScalarType
|
944
|
+
attr_reader :size_type, :values
|
945
|
+
|
946
|
+
def initialize(size_type, values = EMPTY_ARRAY)
|
947
|
+
@size_type = size_type
|
948
|
+
@values = values.sort.freeze
|
949
|
+
end
|
950
|
+
|
951
|
+
def accept(visitor, guard)
|
952
|
+
super
|
953
|
+
@size_type.accept(visitor, guard) unless @size_type.nil?
|
954
|
+
end
|
955
|
+
|
956
|
+
def generalize
|
957
|
+
DEFAULT
|
958
|
+
end
|
959
|
+
|
960
|
+
def hash
|
961
|
+
@size_type.hash * 31 + @values.hash
|
962
|
+
end
|
963
|
+
|
964
|
+
def iterable?(guard = nil)
|
965
|
+
true
|
966
|
+
end
|
967
|
+
|
968
|
+
def iterable_type(guard = nil)
|
969
|
+
ITERABLE_TYPE
|
970
|
+
end
|
971
|
+
|
972
|
+
def eql?(o)
|
973
|
+
self.class == o.class && @size_type == o.size_type && @values == o.values
|
974
|
+
end
|
975
|
+
|
976
|
+
def instance?(o)
|
977
|
+
# true if size compliant
|
978
|
+
if o.is_a?(String) && (@size_type.nil? || @size_type.instance?(o.size))
|
979
|
+
@values.empty? || @values.include?(o)
|
980
|
+
else
|
981
|
+
false
|
982
|
+
end
|
983
|
+
end
|
984
|
+
|
985
|
+
DEFAULT = PStringType.new(nil)
|
986
|
+
NON_EMPTY = PStringType.new(PIntegerType.new(1))
|
987
|
+
|
988
|
+
# Iterates over each character of the string
|
989
|
+
ITERABLE_TYPE = PIterableType.new(PStringType.new(PIntegerType.new(1,1)))
|
990
|
+
|
991
|
+
protected
|
992
|
+
|
993
|
+
# @api private
|
994
|
+
def _assignable?(o, guard)
|
995
|
+
if values.empty?
|
996
|
+
# A general string is assignable by any other string or pattern restricted string
|
997
|
+
# if the string has a size constraint it does not match since there is no reasonable way
|
998
|
+
# to compute the min/max length a pattern will match. For enum, it is possible to test that
|
999
|
+
# each enumerator value is within range
|
1000
|
+
case o
|
1001
|
+
when PStringType
|
1002
|
+
# true if size compliant
|
1003
|
+
(@size_type || PCollectionType::DEFAULT_SIZE).assignable?(
|
1004
|
+
o.size_type || PCollectionType::DEFAULT_SIZE, guard)
|
1005
|
+
|
1006
|
+
when PPatternType
|
1007
|
+
# true if size constraint is at least 0 to +Infinity (which is the same as the default)
|
1008
|
+
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE, guard)
|
1009
|
+
|
1010
|
+
when PEnumType
|
747
1011
|
if o.values.empty?
|
748
|
-
#
|
749
|
-
#
|
750
|
-
@
|
1012
|
+
# enum represents all enums, and thus all strings, a sized constrained string can thus not
|
1013
|
+
# be assigned any enum (unless it is max size).
|
1014
|
+
@size_type.nil? || @size_type.assignable?(PCollectionType::DEFAULT_SIZE, guard)
|
751
1015
|
else
|
752
|
-
#
|
753
|
-
|
754
|
-
|
755
|
-
|
1016
|
+
# true if all enum values are within range
|
1017
|
+
orange = o.values.map(&:size).minmax
|
1018
|
+
srange = (@size_type || PCollectionType::DEFAULT_SIZE).range
|
1019
|
+
# If o min and max are within the range of t
|
1020
|
+
srange[0] <= orange[0] && srange[1] >= orange[1]
|
756
1021
|
end
|
757
|
-
when PPatternType
|
758
|
-
@patterns.empty?
|
759
1022
|
else
|
1023
|
+
# no other type matches string
|
760
1024
|
false
|
761
|
-
end
|
762
1025
|
end
|
1026
|
+
elsif o.is_a?(PStringType)
|
1027
|
+
# A specific string acts as a set of strings - must have exactly the same strings
|
1028
|
+
# In this case, size does not matter since the definition is very precise anyway
|
1029
|
+
values == o.values
|
1030
|
+
else
|
1031
|
+
# All others are false, since no other type describes the same set of specific strings
|
1032
|
+
false
|
763
1033
|
end
|
1034
|
+
end
|
1035
|
+
end
|
764
1036
|
|
765
|
-
|
766
|
-
|
767
|
-
|
1037
|
+
# @api public
|
1038
|
+
#
|
1039
|
+
class PRegexpType < PScalarType
|
1040
|
+
attr_reader :pattern
|
768
1041
|
|
769
|
-
|
770
|
-
|
771
|
-
|
1042
|
+
def initialize(pattern)
|
1043
|
+
@pattern = pattern
|
1044
|
+
end
|
772
1045
|
|
773
|
-
|
1046
|
+
def regexp
|
1047
|
+
@regexp ||= Regexp.new(@pattern || '')
|
1048
|
+
end
|
774
1049
|
|
775
|
-
|
1050
|
+
def hash
|
1051
|
+
@pattern.hash
|
1052
|
+
end
|
776
1053
|
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
1054
|
+
def eql?(o)
|
1055
|
+
self.class == o.class && @pattern == o.pattern
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
DEFAULT = PRegexpType.new(nil)
|
1059
|
+
|
1060
|
+
protected
|
1061
|
+
|
1062
|
+
# @api private
|
1063
|
+
#
|
1064
|
+
def _assignable?(o, guard)
|
1065
|
+
o.is_a?(PRegexpType) && (@pattern.nil? || @pattern == o.pattern)
|
1066
|
+
end
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
# Represents a subtype of String that narrows the string to those matching the patterns
|
1070
|
+
# If specified without a pattern it is basically the same as the String type.
|
1071
|
+
#
|
1072
|
+
# @api public
|
1073
|
+
#
|
1074
|
+
class PPatternType < PScalarType
|
1075
|
+
attr_reader :patterns
|
1076
|
+
|
1077
|
+
def initialize(patterns)
|
1078
|
+
@patterns = patterns.freeze
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
def accept(visitor, guard)
|
1082
|
+
super
|
1083
|
+
@patterns.each { |p| p.accept(visitor, guard) }
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def hash
|
1087
|
+
@patterns.hash
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
def eql?(o)
|
1091
|
+
self.class == o.class && @patterns.size == o.patterns.size && (@patterns - o.patterns).empty?
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
DEFAULT = PPatternType.new(EMPTY_ARRAY)
|
1095
|
+
|
1096
|
+
protected
|
1097
|
+
|
1098
|
+
# @api private
|
1099
|
+
#
|
1100
|
+
def _assignable?(o, guard)
|
1101
|
+
return true if self == o
|
1102
|
+
case o
|
1103
|
+
when PStringType, PEnumType
|
1104
|
+
if o.values.empty?
|
1105
|
+
# Strings / Enums (unknown which ones) cannot all match a pattern, but if there is no pattern it is ok
|
1106
|
+
# (There should really always be a pattern, but better safe than sorry).
|
1107
|
+
@patterns.empty?
|
1108
|
+
else
|
1109
|
+
# all strings in String/Enum type must match one of the patterns in Pattern type,
|
1110
|
+
# or Pattern represents all Patterns == all Strings
|
1111
|
+
regexps = @patterns.map { |p| p.regexp }
|
1112
|
+
regexps.empty? || o.values.all? { |v| regexps.any? {|re| re.match(v) } }
|
1113
|
+
end
|
1114
|
+
when PPatternType
|
1115
|
+
@patterns.empty?
|
1116
|
+
else
|
1117
|
+
false
|
782
1118
|
end
|
1119
|
+
end
|
1120
|
+
end
|
783
1121
|
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
#
|
788
|
-
class PStructElement < TypedModelObject
|
789
|
-
attr_accessor :key_type, :value_type
|
1122
|
+
# @api public
|
1123
|
+
#
|
1124
|
+
class PBooleanType < PScalarType
|
790
1125
|
|
791
|
-
|
792
|
-
|
793
|
-
|
1126
|
+
def instance?(o)
|
1127
|
+
o == true || o == false
|
1128
|
+
end
|
794
1129
|
|
795
|
-
|
796
|
-
k = key_type
|
797
|
-
k = k.optional_type if k.is_a?(POptionalType)
|
798
|
-
k.values[0]
|
799
|
-
end
|
1130
|
+
DEFAULT = PBooleanType.new
|
800
1131
|
|
801
|
-
|
802
|
-
@key_type = key_type
|
803
|
-
@value_type = value_type
|
804
|
-
end
|
1132
|
+
protected
|
805
1133
|
|
806
|
-
|
807
|
-
|
808
|
-
|
1134
|
+
# @api private
|
1135
|
+
#
|
1136
|
+
def _assignable?(o, guard)
|
1137
|
+
o.is_a?(PBooleanType)
|
1138
|
+
end
|
1139
|
+
end
|
809
1140
|
|
810
|
-
|
811
|
-
|
812
|
-
|
1141
|
+
# @api public
|
1142
|
+
#
|
1143
|
+
# @api public
|
1144
|
+
#
|
1145
|
+
class PStructElement < TypedModelObject
|
1146
|
+
attr_accessor :key_type, :value_type
|
813
1147
|
|
814
|
-
|
815
|
-
|
816
|
-
|
1148
|
+
def accept(visitor, guard)
|
1149
|
+
@key_type.accept(visitor, guard)
|
1150
|
+
@value_type.accept(visitor, guard)
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
def hash
|
1154
|
+
value_type.hash * 31 + key_type.hash
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
def name
|
1158
|
+
k = key_type
|
1159
|
+
k = k.optional_type if k.is_a?(POptionalType)
|
1160
|
+
k.values[0]
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
def initialize(key_type, value_type)
|
1164
|
+
@key_type = key_type
|
1165
|
+
@value_type = value_type
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
def generalize
|
1169
|
+
gv_type = @value_type.generalize
|
1170
|
+
@value_type.equal?(gv_type) ? self : PStructElement.new(@key_type, gv_type)
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
def normalize(guard = nil)
|
1174
|
+
nv_type = @value_type.normalize(guard)
|
1175
|
+
@value_type.equal?(nv_type) ? self : PStructElement.new(@key_type, nv_type)
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
def <=>(o)
|
1179
|
+
self.name <=> o.name
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
def eql?(o)
|
1183
|
+
self.class == o.class && value_type == o.value_type && key_type == o.key_type
|
1184
|
+
end
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
# @api public
|
1188
|
+
#
|
1189
|
+
class PStructType < PAnyType
|
1190
|
+
include Enumerable
|
1191
|
+
|
1192
|
+
def initialize(elements)
|
1193
|
+
@elements = elements.sort.freeze
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
def accept(visitor, guard)
|
1197
|
+
super
|
1198
|
+
@elements.each { |elem| elem.accept(visitor, guard) }
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
def each
|
1202
|
+
if block_given?
|
1203
|
+
elements.each { |elem| yield elem }
|
1204
|
+
else
|
1205
|
+
elements.to_enum
|
817
1206
|
end
|
1207
|
+
end
|
818
1208
|
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
1209
|
+
def generalize
|
1210
|
+
if @elements.empty?
|
1211
|
+
DEFAULT
|
1212
|
+
else
|
1213
|
+
alter_type_array(@elements, :generalize) { |altered| PStructType.new(altered) }
|
1214
|
+
end
|
1215
|
+
end
|
823
1216
|
|
824
|
-
|
825
|
-
|
826
|
-
|
1217
|
+
def normalize(guard = nil)
|
1218
|
+
if @elements.empty?
|
1219
|
+
DEFAULT
|
1220
|
+
else
|
1221
|
+
alter_type_array(@elements, :normalize, guard) { |altered| PStructType.new(altered) }
|
1222
|
+
end
|
1223
|
+
end
|
827
1224
|
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
else
|
832
|
-
elements.to_enum
|
833
|
-
end
|
834
|
-
end
|
1225
|
+
def hashed_elements
|
1226
|
+
@hashed ||= @elements.reduce({}) {|memo, e| memo[e.name] = e; memo }
|
1227
|
+
end
|
835
1228
|
|
836
|
-
|
837
|
-
|
838
|
-
|
1229
|
+
def hash
|
1230
|
+
@elements.hash
|
1231
|
+
end
|
839
1232
|
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
def hash
|
845
|
-
@elements.hash
|
846
|
-
end
|
1233
|
+
def iterable?(guard = nil)
|
1234
|
+
true
|
1235
|
+
end
|
847
1236
|
|
848
|
-
|
849
|
-
|
850
|
-
|
1237
|
+
def iterable_type(guard = nil)
|
1238
|
+
if self == DEFAULT
|
1239
|
+
PIterableType.new(PHashType::DEFAULT_KEY_PAIR_TUPLE)
|
1240
|
+
else
|
1241
|
+
tc = TypeCalculator.singleton
|
1242
|
+
PIterableType.new(
|
1243
|
+
PTupleType.new([
|
1244
|
+
tc.unwrap_single_variant(PVariantType.new(@elements.map {|se| se.key_type })),
|
1245
|
+
tc.unwrap_single_variant(PVariantType.new(@elements.map {|se| se.value_type }))],
|
1246
|
+
PHashType::KEY_PAIR_TUPLE_SIZE))
|
1247
|
+
end
|
1248
|
+
end
|
851
1249
|
|
852
|
-
|
853
|
-
|
854
|
-
|
1250
|
+
def eql?(o)
|
1251
|
+
self.class == o.class && @elements == o.elements
|
1252
|
+
end
|
855
1253
|
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
@elements.all? do |e|
|
860
|
-
key = e.name
|
861
|
-
v = o[key]
|
862
|
-
if v.nil? && !o.include?(key)
|
863
|
-
# Entry is missing. Only OK when key is optional
|
864
|
-
e.key_type.assignable?(PUndefType::DEFAULT)
|
865
|
-
else
|
866
|
-
matched += 1
|
867
|
-
e.value_type.instance?(v)
|
868
|
-
end
|
869
|
-
end && matched == o.size
|
870
|
-
end
|
1254
|
+
def elements
|
1255
|
+
@elements
|
1256
|
+
end
|
871
1257
|
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
size_o = o.size_type || collection_default_size_t
|
902
|
-
PIntegerType.new(required, elements.size).assignable?(size_o)
|
903
|
-
end
|
1258
|
+
def instance?(o)
|
1259
|
+
return false unless o.is_a?(Hash)
|
1260
|
+
matched = 0
|
1261
|
+
@elements.all? do |e|
|
1262
|
+
key = e.name
|
1263
|
+
v = o[key]
|
1264
|
+
if v.nil? && !o.include?(key)
|
1265
|
+
# Entry is missing. Only OK when key is optional
|
1266
|
+
e.key_type.assignable?(PUndefType::DEFAULT)
|
1267
|
+
else
|
1268
|
+
matched += 1
|
1269
|
+
e.value_type.instance?(v)
|
1270
|
+
end
|
1271
|
+
end && matched == o.size
|
1272
|
+
end
|
1273
|
+
|
1274
|
+
DEFAULT = PStructType.new(EMPTY_ARRAY)
|
1275
|
+
|
1276
|
+
protected
|
1277
|
+
|
1278
|
+
# @api private
|
1279
|
+
def _assignable?(o, guard)
|
1280
|
+
if o.is_a?(Types::PStructType)
|
1281
|
+
h2 = o.hashed_elements
|
1282
|
+
matched = 0
|
1283
|
+
elements.all? do |e1|
|
1284
|
+
e2 = h2[e1.name]
|
1285
|
+
if e2.nil?
|
1286
|
+
e1.key_type.assignable?(PUndefType::DEFAULT, guard)
|
904
1287
|
else
|
905
|
-
|
1288
|
+
matched += 1
|
1289
|
+
e1.key_type.assignable?(e2.key_type, guard) && e1.value_type.assignable?(e2.value_type, guard)
|
1290
|
+
end
|
1291
|
+
end && matched == h2.size
|
1292
|
+
elsif o.is_a?(Types::PHashType)
|
1293
|
+
required = 0
|
1294
|
+
required_elements_assignable = elements.all? do |e|
|
1295
|
+
if e.key_type.assignable?(PUndefType::DEFAULT)
|
1296
|
+
true
|
1297
|
+
else
|
1298
|
+
required += 1
|
1299
|
+
e.value_type.assignable?(o.element_type, guard)
|
906
1300
|
end
|
907
1301
|
end
|
1302
|
+
if required_elements_assignable
|
1303
|
+
size_o = o.size_type || collection_default_size_t
|
1304
|
+
PIntegerType.new(required, elements.size).assignable?(size_o, guard)
|
1305
|
+
end
|
1306
|
+
else
|
1307
|
+
false
|
908
1308
|
end
|
1309
|
+
end
|
1310
|
+
end
|
909
1311
|
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
1312
|
+
# @api public
|
1313
|
+
#
|
1314
|
+
class PTupleType < PAnyType
|
1315
|
+
include Enumerable
|
914
1316
|
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
1317
|
+
# If set, describes min and max required of the given types - if max > size of
|
1318
|
+
# types, the last type entry repeats
|
1319
|
+
#
|
1320
|
+
attr_reader :size_type
|
919
1321
|
|
920
|
-
|
1322
|
+
attr_reader :types
|
921
1323
|
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
1324
|
+
def accept(visitor, guard)
|
1325
|
+
super
|
1326
|
+
@size_type.accept(visitor, guard) unless @size_type.nil?
|
1327
|
+
@types.each { |elem| elem.accept(visitor, guard) }
|
1328
|
+
end
|
927
1329
|
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
# Can't pass a block to a callable that doesn't accept one
|
934
|
-
return false if param_block_t.nil?
|
935
|
-
|
936
|
-
# Check that the block is of the right tyṕe
|
937
|
-
return false unless param_block_t.assignable?(arg_block_t)
|
938
|
-
|
939
|
-
# Check other arguments
|
940
|
-
arg_count = arg_types.size - 1
|
941
|
-
params_size_t = params_tuple.size_type || PIntegerType.new(*params_tuple.size_range)
|
942
|
-
return false unless params_size_t.assignable?(PIntegerType.new(arg_count, arg_count))
|
943
|
-
|
944
|
-
ctypes = params_tuple.types
|
945
|
-
arg_count.times do |index|
|
946
|
-
return false unless (ctypes[index] || ctypes[-1]).assignable?(arg_types[index])
|
947
|
-
end
|
948
|
-
return true
|
949
|
-
end
|
1330
|
+
# @api private
|
1331
|
+
def callable_args?(callable_t, guard)
|
1332
|
+
unless size_type.nil?
|
1333
|
+
raise ArgumentError, 'Callable tuple may not have a size constraint when used as args'
|
1334
|
+
end
|
950
1335
|
|
951
|
-
|
952
|
-
|
953
|
-
|
1336
|
+
params_tuple = callable_t.param_types
|
1337
|
+
param_block_t = callable_t.block_type
|
1338
|
+
arg_types = @types
|
1339
|
+
arg_block_t = arg_types.last
|
1340
|
+
if arg_block_t.kind_of_callable?(true, guard)
|
1341
|
+
# Can't pass a block to a callable that doesn't accept one
|
1342
|
+
return false if param_block_t.nil?
|
954
1343
|
|
955
|
-
|
956
|
-
|
957
|
-
@size_type = size_type.nil? ? nil : size_type.to_size
|
958
|
-
end
|
1344
|
+
# Check that the block is of the right tyṕe
|
1345
|
+
return false unless param_block_t.assignable?(arg_block_t, guard)
|
959
1346
|
|
960
|
-
#
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
types.each { |x| yield x }
|
965
|
-
else
|
966
|
-
types.to_enum
|
967
|
-
end
|
968
|
-
end
|
1347
|
+
# Check other arguments
|
1348
|
+
arg_count = arg_types.size - 1
|
1349
|
+
params_size_t = params_tuple.size_type || PIntegerType.new(*params_tuple.size_range)
|
1350
|
+
return false unless params_size_t.assignable?(PIntegerType.new(arg_count, arg_count), guard)
|
969
1351
|
|
970
|
-
|
971
|
-
|
1352
|
+
ctypes = params_tuple.types
|
1353
|
+
arg_count.times do |index|
|
1354
|
+
return false unless (ctypes[index] || ctypes[-1]).assignable?(arg_types[index], guard)
|
972
1355
|
end
|
1356
|
+
return true
|
1357
|
+
end
|
973
1358
|
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
size_t = size_type || PIntegerType.new(*size_range)
|
1359
|
+
# Check that tuple is assignable and that the block (if declared) is optional
|
1360
|
+
params_tuple.assignable?(self, guard) && (param_block_t.nil? || param_block_t.assignable?(PUndefType::DEFAULT, guard))
|
1361
|
+
end
|
978
1362
|
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
true
|
984
|
-
end
|
1363
|
+
def initialize(types, size_type = nil)
|
1364
|
+
@types = types
|
1365
|
+
@size_type = size_type.nil? ? nil : size_type.to_size
|
1366
|
+
end
|
985
1367
|
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
1368
|
+
# Returns Enumerator for the types if no block is given, otherwise, calls the given
|
1369
|
+
# block with each of the types in this tuple
|
1370
|
+
def each
|
1371
|
+
if block_given?
|
1372
|
+
types.each { |x| yield x }
|
1373
|
+
else
|
1374
|
+
types.to_enum
|
1375
|
+
end
|
1376
|
+
end
|
995
1377
|
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
types_size = @types.size
|
1004
|
-
from, to = @size_type.range
|
1005
|
-
min = from - (types_size-1)
|
1006
|
-
min = min <= 0 ? 0 : min
|
1007
|
-
max = to - (types_size-1)
|
1008
|
-
[min, max]
|
1009
|
-
end
|
1378
|
+
def generalize
|
1379
|
+
if self == DEFAULT
|
1380
|
+
DEFAULT
|
1381
|
+
else
|
1382
|
+
alter_type_array(@types, :generalize) { |altered_types| PTupleType.new(altered_types, @size_type) }
|
1383
|
+
end
|
1384
|
+
end
|
1010
1385
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1386
|
+
def normalize(guard = nil)
|
1387
|
+
if self == DEFAULT
|
1388
|
+
DEFAULT
|
1389
|
+
else
|
1390
|
+
alter_type_array(@types, :normalize, guard) { |altered_types| PTupleType.new(altered_types, @size_type) }
|
1391
|
+
end
|
1392
|
+
end
|
1014
1393
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1394
|
+
def instance?(o)
|
1395
|
+
return false unless o.is_a?(Array)
|
1396
|
+
# compute the tuple's min/max size, and check if that size matches
|
1397
|
+
size_t = size_type || PIntegerType.new(*size_range)
|
1018
1398
|
|
1019
|
-
|
1020
|
-
|
1399
|
+
return false unless size_t.instance?(o.size)
|
1400
|
+
o.each_with_index do |element, index|
|
1401
|
+
return false unless (types[index] || types[-1]).instance?(element)
|
1402
|
+
end
|
1403
|
+
true
|
1404
|
+
end
|
1021
1405
|
|
1022
|
-
|
1406
|
+
def iterable?(guard = nil)
|
1407
|
+
true
|
1408
|
+
end
|
1023
1409
|
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
s_types = types
|
1028
|
-
return true if s_types.empty? && (o.is_a?(PArrayType))
|
1029
|
-
size_s = size_type || PIntegerType.new(*size_range)
|
1410
|
+
def iterable_type(guard = nil)
|
1411
|
+
PIterableType.new(TypeCalculator.singleton.unwrap_single_variant(PVariantType.new(types)))
|
1412
|
+
end
|
1030
1413
|
|
1031
|
-
|
1032
|
-
|
1414
|
+
# Returns the number of elements accepted [min, max] in the tuple
|
1415
|
+
def size_range
|
1416
|
+
if @size_type.nil?
|
1417
|
+
types_size = @types.size
|
1418
|
+
[types_size, types_size]
|
1419
|
+
else
|
1420
|
+
@size_type.range
|
1421
|
+
end
|
1422
|
+
end
|
1033
1423
|
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
return true
|
1041
|
-
else
|
1042
|
-
return false
|
1043
|
-
end
|
1044
|
-
elsif o.is_a?(PArrayType)
|
1045
|
-
o_entry = o.element_type
|
1046
|
-
# Array of anything can not be assigned (unless tuple is tuple of anything) - this case
|
1047
|
-
# was handled at the top of this method.
|
1048
|
-
#
|
1049
|
-
return false if o_entry.nil?
|
1050
|
-
size_o = o.size_type || PCollectionType::DEFAULT_SIZE
|
1051
|
-
return false unless size_s.assignable?(size_o)
|
1052
|
-
[s_types.size, size_o.range[1]].min.times { |index| return false unless (s_types[index] || s_types[-1]).assignable?(o_entry) }
|
1053
|
-
true
|
1054
|
-
else
|
1055
|
-
false
|
1056
|
-
end
|
1057
|
-
end
|
1424
|
+
# Returns the number of accepted occurrences [min, max] of the last type in the tuple
|
1425
|
+
# The defaults is [1,1]
|
1426
|
+
#
|
1427
|
+
def repeat_last_range
|
1428
|
+
if @size_type.nil?
|
1429
|
+
return [1, 1]
|
1058
1430
|
end
|
1431
|
+
types_size = @types.size
|
1432
|
+
from, to = @size_type.range
|
1433
|
+
min = from - (types_size-1)
|
1434
|
+
min = min <= 0 ? 0 : min
|
1435
|
+
max = to - (types_size-1)
|
1436
|
+
[min, max]
|
1437
|
+
end
|
1059
1438
|
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
# Types of parameters as a Tuple with required/optional count, or an Integer with min (required), max count
|
1064
|
-
# @return [PTupleType] the tuple representing the parameter types
|
1065
|
-
attr_reader :param_types
|
1066
|
-
|
1067
|
-
# Although being an abstract type reference, only Callable, or all Callables wrapped in
|
1068
|
-
# Optional or Variant are supported
|
1069
|
-
# If not set, the meaning is that block is not supported.
|
1070
|
-
# @return [PAnyType|nil] the block type
|
1071
|
-
attr_reader :block_type
|
1072
|
-
|
1073
|
-
# @param param_types [PTupleType]
|
1074
|
-
# @param block_type [PAnyType|nil]
|
1075
|
-
def initialize(param_types, block_type = nil)
|
1076
|
-
@param_types = param_types
|
1077
|
-
@block_type = block_type
|
1078
|
-
end
|
1439
|
+
def hash
|
1440
|
+
@size_type.hash * 31 + @types.hash
|
1441
|
+
end
|
1079
1442
|
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
block_t = @block_type.nil? ? nil : @block_type.generalize
|
1084
|
-
PCallableType.new(params_t, block_t)
|
1085
|
-
end
|
1443
|
+
def eql?(o)
|
1444
|
+
self.class == o.class && @types == o.types && @size_type == o.size_type
|
1445
|
+
end
|
1086
1446
|
|
1087
|
-
|
1088
|
-
|
1089
|
-
end
|
1447
|
+
DATA = PTupleType.new([PDataType::DEFAULT], PCollectionType::DEFAULT_SIZE)
|
1448
|
+
DEFAULT = PTupleType.new(EMPTY_ARRAY)
|
1090
1449
|
|
1091
|
-
|
1092
|
-
def callable_args?(required_callable_t)
|
1093
|
-
# If the required callable is euqal or more specific than self, self is acceptable arguments
|
1094
|
-
required_callable_t.assignable?(self)
|
1095
|
-
end
|
1450
|
+
protected
|
1096
1451
|
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1452
|
+
# @api private
|
1453
|
+
def _assignable?(o, guard)
|
1454
|
+
return true if self == o
|
1455
|
+
s_types = types
|
1456
|
+
return true if s_types.empty? && (o.is_a?(PArrayType))
|
1457
|
+
size_s = size_type || PIntegerType.new(*size_range)
|
1100
1458
|
|
1101
|
-
|
1102
|
-
|
1103
|
-
@param_types.nil? ? nil : @param_types.size_range
|
1104
|
-
end
|
1459
|
+
if o.is_a?(PTupleType)
|
1460
|
+
size_o = o.size_type || PIntegerType.new(*o.size_range)
|
1105
1461
|
|
1106
|
-
#
|
1462
|
+
# not assignable if the number of types in o is outside number of types in t1
|
1463
|
+
if size_s.assignable?(size_o, guard)
|
1464
|
+
o_types = o.types
|
1465
|
+
o_types.size.times do |index|
|
1466
|
+
return false unless (s_types[index] || s_types[-1]).assignable?(o_types[index], guard)
|
1467
|
+
end
|
1468
|
+
return true
|
1469
|
+
else
|
1470
|
+
return false
|
1471
|
+
end
|
1472
|
+
elsif o.is_a?(PArrayType)
|
1473
|
+
o_entry = o.element_type
|
1474
|
+
# Array of anything can not be assigned (unless tuple is tuple of anything) - this case
|
1475
|
+
# was handled at the top of this method.
|
1107
1476
|
#
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1477
|
+
return false if o_entry.nil?
|
1478
|
+
size_o = o.size_type || PCollectionType::DEFAULT_SIZE
|
1479
|
+
return false unless size_s.assignable?(size_o, guard)
|
1480
|
+
[s_types.size, size_o.range[1]].min.times { |index| return false unless (s_types[index] || s_types[-1]).assignable?(o_entry, guard) }
|
1481
|
+
true
|
1482
|
+
else
|
1483
|
+
false
|
1484
|
+
end
|
1485
|
+
end
|
1486
|
+
end
|
1111
1487
|
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1488
|
+
# @api public
|
1489
|
+
#
|
1490
|
+
class PCallableType < PAnyType
|
1491
|
+
# Types of parameters as a Tuple with required/optional count, or an Integer with min (required), max count
|
1492
|
+
# @return [PTupleType] the tuple representing the parameter types
|
1493
|
+
attr_reader :param_types
|
1494
|
+
|
1495
|
+
# Although being an abstract type reference, only Callable, or all Callables wrapped in
|
1496
|
+
# Optional or Variant are supported
|
1497
|
+
# If not set, the meaning is that block is not supported.
|
1498
|
+
# @return [PAnyType|nil] the block type
|
1499
|
+
attr_reader :block_type
|
1500
|
+
|
1501
|
+
# @param param_types [PTupleType]
|
1502
|
+
# @param block_type [PAnyType|nil]
|
1503
|
+
def initialize(param_types, block_type = nil)
|
1504
|
+
@param_types = param_types
|
1505
|
+
@block_type = block_type
|
1506
|
+
end
|
1124
1507
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1508
|
+
def accept(visitor, guard)
|
1509
|
+
super
|
1510
|
+
@param_types.accept(visitor, guard) unless @param_types.nil?
|
1511
|
+
@block_type.accept(visitor, guard) unless @block_type.nil?
|
1512
|
+
end
|
1128
1513
|
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1514
|
+
def generalize
|
1515
|
+
if self == DEFAULT
|
1516
|
+
DEFAULT
|
1517
|
+
else
|
1518
|
+
params_t = @param_types.nil? ? nil : @param_types.generalize
|
1519
|
+
block_t = @block_type.nil? ? nil : @block_type.generalize
|
1520
|
+
@param_types.equal?(params_t) && @block_type.equal?(block_t) ? self : PCallableType.new(params_t, block_t)
|
1521
|
+
end
|
1522
|
+
end
|
1523
|
+
|
1524
|
+
def normalize(guard = nil)
|
1525
|
+
if self == DEFAULT
|
1526
|
+
DEFAULT
|
1527
|
+
else
|
1528
|
+
params_t = @param_types.nil? ? nil : @param_types.normalize(guard)
|
1529
|
+
block_t = @block_type.nil? ? nil : @block_type.normalize(guard)
|
1530
|
+
@param_types.equal?(params_t) && @block_type.equal?(block_t) ? self : PCallableType.new(params_t, block_t)
|
1531
|
+
end
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
def instance?(o)
|
1535
|
+
assignable?(TypeCalculator.infer(o))
|
1536
|
+
end
|
1132
1537
|
|
1133
|
-
|
1538
|
+
# @api private
|
1539
|
+
def callable_args?(required_callable_t, guard)
|
1540
|
+
# If the required callable is euqal or more specific than self, self is acceptable arguments
|
1541
|
+
required_callable_t.assignable?(self, guard)
|
1542
|
+
end
|
1134
1543
|
|
1135
|
-
|
1544
|
+
def kind_of_callable?(optional=true, guard = nil)
|
1545
|
+
true
|
1546
|
+
end
|
1136
1547
|
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
return true if @param_types.nil?
|
1548
|
+
# Returns the number of accepted arguments [min, max]
|
1549
|
+
def size_range
|
1550
|
+
@param_types.nil? ? nil : @param_types.size_range
|
1551
|
+
end
|
1142
1552
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1553
|
+
# Returns the number of accepted arguments for the last parameter type [min, max]
|
1554
|
+
#
|
1555
|
+
def last_range
|
1556
|
+
@param_types.nil? ? nil : @param_types.repeat_last_range
|
1557
|
+
end
|
1558
|
+
|
1559
|
+
# Range [0,0], [0,1], or [1,1] for the block
|
1560
|
+
#
|
1561
|
+
def block_range
|
1562
|
+
case block_type
|
1563
|
+
when POptionalType
|
1564
|
+
[0,1]
|
1565
|
+
when PVariantType, PCallableType
|
1566
|
+
[1,1]
|
1567
|
+
else
|
1568
|
+
[0,0]
|
1152
1569
|
end
|
1570
|
+
end
|
1153
1571
|
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1572
|
+
def hash
|
1573
|
+
@param_types.hash * 31 + @block_type.hash
|
1574
|
+
end
|
1157
1575
|
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
block_t = callable.block_type
|
1162
|
-
# does not support calling with a block, but have to check that callable is ok with missing block
|
1163
|
-
(param_t.nil? || param_t.assignable?(self)) && (block_t.nil? || block_t.assignable(PUndefType::DEFAULT))
|
1164
|
-
end
|
1576
|
+
def eql?(o)
|
1577
|
+
self.class == o.class && @param_types == o.param_types && @block_type == o.block_type
|
1578
|
+
end
|
1165
1579
|
|
1166
|
-
|
1167
|
-
if self == DEFAULT
|
1168
|
-
self
|
1169
|
-
else
|
1170
|
-
PArrayType.new(element_type.nil? ? nil : element_type.generalize)
|
1171
|
-
end
|
1172
|
-
end
|
1580
|
+
DEFAULT = PCallableType.new(nil)
|
1173
1581
|
|
1174
|
-
|
1175
|
-
return false unless o.is_a?(Array)
|
1176
|
-
element_t = element_type
|
1177
|
-
return false unless element_t.nil? || o.all? {|element| element_t.instance?(element) }
|
1178
|
-
size_t = size_type
|
1179
|
-
size_t.nil? || size_t.instance?(o.size)
|
1180
|
-
end
|
1582
|
+
protected
|
1181
1583
|
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
end
|
1217
|
-
# ... and so must the last, possibly optional (ranged) type
|
1218
|
-
s_entry.assignable?(o_ranged)
|
1219
|
-
elsif o.is_a?(PArrayType)
|
1220
|
-
super && (s_entry.nil? || s_entry.assignable?(o.element_type))
|
1221
|
-
else
|
1222
|
-
false
|
1223
|
-
end
|
1224
|
-
end
|
1584
|
+
# @api private
|
1585
|
+
def _assignable?(o, guard)
|
1586
|
+
return false unless o.is_a?(PCallableType)
|
1587
|
+
# nil param_types means, any other Callable is assignable
|
1588
|
+
return true if @param_types.nil?
|
1589
|
+
|
1590
|
+
# NOTE: these tests are made in reverse as it is calling the callable that is constrained
|
1591
|
+
# (it's lower bound), not its upper bound
|
1592
|
+
return false unless o.param_types.assignable?(@param_types, guard)
|
1593
|
+
# names are ignored, they are just information
|
1594
|
+
# Blocks must be compatible
|
1595
|
+
this_block_t = @block_type || PUndefType::DEFAULT
|
1596
|
+
that_block_t = o.block_type || PUndefType::DEFAULT
|
1597
|
+
that_block_t.assignable?(this_block_t, guard)
|
1598
|
+
end
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
# @api public
|
1602
|
+
#
|
1603
|
+
class PArrayType < PCollectionType
|
1604
|
+
|
1605
|
+
# @api private
|
1606
|
+
def callable_args?(callable, guard = nil)
|
1607
|
+
param_t = callable.param_types
|
1608
|
+
block_t = callable.block_type
|
1609
|
+
# does not support calling with a block, but have to check that callable is ok with missing block
|
1610
|
+
(param_t.nil? || param_t.assignable?(self, guard)) && (block_t.nil? || block_t.assignable(PUndefType::DEFAULT, guard))
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
def generalize
|
1614
|
+
if self == DATA
|
1615
|
+
self
|
1616
|
+
else
|
1617
|
+
super
|
1225
1618
|
end
|
1619
|
+
end
|
1226
1620
|
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1621
|
+
def normalize(guard = nil)
|
1622
|
+
if self == DATA
|
1623
|
+
self
|
1624
|
+
else
|
1625
|
+
super
|
1626
|
+
end
|
1627
|
+
end
|
1231
1628
|
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1629
|
+
def instance?(o)
|
1630
|
+
return false unless o.is_a?(Array)
|
1631
|
+
element_t = element_type
|
1632
|
+
return false unless element_t.nil? || o.all? {|element| element_t.instance?(element) }
|
1633
|
+
size_t = size_type
|
1634
|
+
size_t.nil? || size_t.instance?(o.size)
|
1635
|
+
end
|
1236
1636
|
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1637
|
+
DATA = PArrayType.new(PDataType::DEFAULT, DEFAULT_SIZE)
|
1638
|
+
DEFAULT = PArrayType.new(nil)
|
1639
|
+
EMPTY = PArrayType.new(PUnitType::DEFAULT, ZERO_SIZE)
|
1640
|
+
|
1641
|
+
protected
|
1642
|
+
|
1643
|
+
# Array is assignable if o is an Array and o's element type is assignable, or if o is a Tuple
|
1644
|
+
# @api private
|
1645
|
+
def _assignable?(o, guard)
|
1646
|
+
s_entry = element_type
|
1647
|
+
if o.is_a?(PTupleType)
|
1648
|
+
# If s_entry is nil, this Array type has no opinion on element types. Therefore any
|
1649
|
+
# tuple can be assigned.
|
1650
|
+
return true if s_entry.nil?
|
1651
|
+
|
1652
|
+
return false unless o.types.all? {|o_element_t| s_entry.assignable?(o_element_t, guard) }
|
1653
|
+
o_regular = o.types[0..-2]
|
1654
|
+
o_ranged = o.types[-1]
|
1655
|
+
o_from, o_to = type_to_range(o.size_type)
|
1656
|
+
o_required = o_regular.size + o_from
|
1657
|
+
|
1658
|
+
# array type may be size constrained
|
1659
|
+
size_s = size_type || DEFAULT_SIZE
|
1660
|
+
min, max = size_s.range
|
1661
|
+
# Tuple with fewer min entries can not be assigned
|
1662
|
+
return false if o_required < min
|
1663
|
+
# Tuple with more optionally available entries can not be assigned
|
1664
|
+
return false if o_regular.size + o_to > max
|
1665
|
+
# each tuple type must be assignable to the element type
|
1666
|
+
o_required.times do |index|
|
1667
|
+
o_entry = tuple_entry_at(o, o_from, o_to, index)
|
1668
|
+
return false unless s_entry.assignable?(o_entry, guard)
|
1669
|
+
end
|
1670
|
+
# ... and so must the last, possibly optional (ranged) type
|
1671
|
+
s_entry.assignable?(o_ranged)
|
1672
|
+
elsif o.is_a?(PArrayType)
|
1673
|
+
super && (s_entry.nil? || s_entry.assignable?(o.element_type, guard))
|
1674
|
+
else
|
1675
|
+
false
|
1676
|
+
end
|
1677
|
+
end
|
1678
|
+
end
|
1248
1679
|
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1680
|
+
# @api public
|
1681
|
+
#
|
1682
|
+
class PHashType < PCollectionType
|
1683
|
+
attr_accessor :key_type
|
1252
1684
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
if (key_t.nil? || o.keys.all? {|key| key_t.instance?(key) }) &&
|
1258
|
-
(element_t.nil? || o.values.all? {|value| element_t.instance?(value) })
|
1259
|
-
size_t = size_type
|
1260
|
-
size_t.nil? || size_t.instance?(o.size)
|
1261
|
-
else
|
1262
|
-
false
|
1263
|
-
end
|
1264
|
-
end
|
1685
|
+
def initialize(key_type, value_type, size_type = nil)
|
1686
|
+
super(value_type, size_type)
|
1687
|
+
@key_type = key_type
|
1688
|
+
end
|
1265
1689
|
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1690
|
+
def accept(visitor, guard)
|
1691
|
+
super
|
1692
|
+
@key_type.accept(visitor, guard) unless @key_type.nil?
|
1693
|
+
end
|
1269
1694
|
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1695
|
+
def generalize
|
1696
|
+
if self == DEFAULT || self == DATA || self == EMPTY
|
1697
|
+
self
|
1698
|
+
else
|
1699
|
+
key_t = @key_type
|
1700
|
+
key_t = key_t.generalize unless key_t.nil?
|
1701
|
+
value_t = @element_type
|
1702
|
+
value_t = value_t.generalize unless value_t.nil?
|
1703
|
+
@size_type.nil? && @key_type.equal?(key_t) && @element_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, nil)
|
1704
|
+
end
|
1705
|
+
end
|
1706
|
+
|
1707
|
+
def normalize(guard = nil)
|
1708
|
+
if self == DEFAULT || self == DATA || self == EMPTY
|
1709
|
+
self
|
1710
|
+
else
|
1711
|
+
key_t = @key_type
|
1712
|
+
key_t = key_t.normalize(guard) unless key_t.nil?
|
1713
|
+
value_t = @element_type
|
1714
|
+
value_t = value_t.normalize(guard) unless value_t.nil?
|
1715
|
+
@size_type.nil? && @key_type.equal?(key_t) && @element_type.equal?(value_t) ? self : PHashType.new(key_t, value_t, nil)
|
1716
|
+
end
|
1717
|
+
end
|
1718
|
+
|
1719
|
+
def hash
|
1720
|
+
@key_type.hash * 31 + super
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
def instance?(o)
|
1724
|
+
return false unless o.is_a?(Hash)
|
1725
|
+
key_t = key_type
|
1726
|
+
element_t = element_type
|
1727
|
+
if (key_t.nil? || o.keys.all? {|key| key_t.instance?(key) }) &&
|
1728
|
+
(element_t.nil? || o.values.all? {|value| element_t.instance?(value) })
|
1729
|
+
size_t = size_type
|
1730
|
+
size_t.nil? || size_t.instance?(o.size)
|
1731
|
+
else
|
1732
|
+
false
|
1733
|
+
end
|
1734
|
+
end
|
1735
|
+
|
1736
|
+
def iterable?(guard = nil)
|
1737
|
+
true
|
1738
|
+
end
|
1739
|
+
|
1740
|
+
def iterable_type(guard = nil)
|
1741
|
+
if self == DEFAULT || self == EMPTY
|
1742
|
+
PIterableType.new(DEFAULT_KEY_PAIR_TUPLE)
|
1743
|
+
else
|
1744
|
+
PIterableType.new(PTupleType.new([@key_type, @element_type], KEY_PAIR_TUPLE_SIZE))
|
1745
|
+
end
|
1746
|
+
end
|
1747
|
+
|
1748
|
+
def eql?(o)
|
1749
|
+
super && @key_type == o.key_type
|
1750
|
+
end
|
1751
|
+
|
1752
|
+
def is_the_empty_hash?
|
1753
|
+
self == EMPTY
|
1754
|
+
end
|
1755
|
+
|
1756
|
+
DEFAULT = PHashType.new(nil, nil)
|
1757
|
+
KEY_PAIR_TUPLE_SIZE = PIntegerType.new(2,2)
|
1758
|
+
DEFAULT_KEY_PAIR_TUPLE = PTupleType.new([PUnitType::DEFAULT, PUnitType::DEFAULT], KEY_PAIR_TUPLE_SIZE)
|
1759
|
+
DATA = PHashType.new(PScalarType::DEFAULT, PDataType::DEFAULT, DEFAULT_SIZE)
|
1760
|
+
EMPTY = PHashType.new(PUnitType::DEFAULT, PUnitType::DEFAULT, PIntegerType.new(0, 0))
|
1761
|
+
|
1762
|
+
protected
|
1763
|
+
|
1764
|
+
# Hash is assignable if o is a Hash and o's key and element types are assignable
|
1765
|
+
# @api private
|
1766
|
+
def _assignable?(o, guard)
|
1767
|
+
case o
|
1768
|
+
when PHashType
|
1769
|
+
size_s = size_type
|
1770
|
+
return true if (size_s.nil? || size_s.from == 0) && o.is_the_empty_hash?
|
1771
|
+
return false unless (key_type.nil? || key_type.assignable?(o.key_type, guard)) && (element_type.nil? || element_type.assignable?(o.element_type, guard))
|
1772
|
+
super
|
1773
|
+
when PStructType
|
1774
|
+
# hash must accept String as key type
|
1775
|
+
# hash must accept all value types
|
1776
|
+
# hash must accept the size of the struct
|
1777
|
+
o_elements = o.elements
|
1778
|
+
(size_type || DEFAULT_SIZE).instance?(o_elements.size) &&
|
1779
|
+
o_elements.all? {|e| (key_type.nil? || key_type.instance?(e.name)) && (element_type.nil? || element_type.assignable?(e.value_type, guard)) }
|
1780
|
+
else
|
1781
|
+
false
|
1782
|
+
end
|
1783
|
+
end
|
1784
|
+
end
|
1785
|
+
|
1786
|
+
# A flexible type describing an any? of other types
|
1787
|
+
# @api public
|
1788
|
+
#
|
1789
|
+
class PVariantType < PAnyType
|
1790
|
+
include Enumerable
|
1273
1791
|
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1792
|
+
attr_reader :types
|
1793
|
+
|
1794
|
+
# @param types [Array[PAnyType]] the variants
|
1795
|
+
def initialize(types)
|
1796
|
+
@types = types.uniq.freeze
|
1797
|
+
end
|
1798
|
+
|
1799
|
+
def accept(visitor, guard)
|
1800
|
+
super
|
1801
|
+
@types.each { |t| t.accept(visitor, guard) }
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
def each
|
1805
|
+
if block_given?
|
1806
|
+
types.each { |t| yield t }
|
1807
|
+
else
|
1808
|
+
types.to_enum
|
1809
|
+
end
|
1810
|
+
end
|
1811
|
+
|
1812
|
+
def generalize
|
1813
|
+
if self == DEFAULT || self == DATA
|
1814
|
+
self
|
1815
|
+
else
|
1816
|
+
alter_type_array(@types, :generalize) { |altered| PVariantType.new(mod_types) }
|
1817
|
+
end
|
1818
|
+
end
|
1819
|
+
|
1820
|
+
def normalize(guard = nil)
|
1821
|
+
if self == DEFAULT || self == DATA || @types.empty?
|
1822
|
+
self
|
1823
|
+
else
|
1824
|
+
# Normalize all contained types
|
1825
|
+
modified = false
|
1826
|
+
types = alter_type_array(@types, :normalize, guard)
|
1827
|
+
if types == self
|
1828
|
+
types = @types
|
1829
|
+
else
|
1830
|
+
modified = true
|
1831
|
+
end
|
1832
|
+
|
1833
|
+
if types.size == 1
|
1834
|
+
types[0]
|
1835
|
+
elsif types.any? { |t| t.is_a?(PUndefType) }
|
1836
|
+
# Undef entry present. Use an OptionalType with a normalized Variant of all types that are not Undef
|
1837
|
+
POptionalType.new(PVariantType.new(types.reject { |ot| ot.is_a?(PUndefType) }).normalize(guard)).normalize(guard)
|
1838
|
+
else
|
1839
|
+
# Merge all variants into this one
|
1840
|
+
types = types.map do |t|
|
1841
|
+
if t.is_a?(PVariantType)
|
1842
|
+
modified = true
|
1843
|
+
t.types
|
1296
1844
|
else
|
1297
|
-
|
1845
|
+
t
|
1846
|
+
end
|
1847
|
+
end
|
1848
|
+
types.flatten! if modified
|
1849
|
+
size_before_merge = types.size
|
1850
|
+
|
1851
|
+
types = swap_not_undefs(types)
|
1852
|
+
types = swap_optionals(types)
|
1853
|
+
types = merge_enums(types)
|
1854
|
+
types = merge_patterns(types)
|
1855
|
+
types = merge_int_ranges(types)
|
1856
|
+
types = merge_float_ranges(types)
|
1857
|
+
|
1858
|
+
if types.size == 1
|
1859
|
+
types[0]
|
1860
|
+
else
|
1861
|
+
modified || types.size != size_before_merge ? PVariantType.new(types) : self
|
1298
1862
|
end
|
1299
1863
|
end
|
1300
1864
|
end
|
1865
|
+
end
|
1301
1866
|
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
class PVariantType < PAnyType
|
1306
|
-
include Enumerable
|
1867
|
+
def hash
|
1868
|
+
@types.hash
|
1869
|
+
end
|
1307
1870
|
|
1308
|
-
|
1871
|
+
def instance?(o)
|
1872
|
+
# instance of variant if o is instance? of any of variant's types
|
1873
|
+
@types.any? { |type| type.instance?(o) }
|
1874
|
+
end
|
1309
1875
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1876
|
+
def kind_of_callable?(optional = true, guard = nil)
|
1877
|
+
@types.all? { |type| type.kind_of_callable?(optional, guard) }
|
1878
|
+
end
|
1879
|
+
|
1880
|
+
def resolved?
|
1881
|
+
@types.all? { |type| type.resolved? }
|
1882
|
+
end
|
1883
|
+
|
1884
|
+
def eql?(o)
|
1885
|
+
o = DATA if o.is_a?(PDataType)
|
1886
|
+
self.class == o.class && @types.size == o.types.size && (@types - o.types).empty?
|
1887
|
+
end
|
1313
1888
|
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1889
|
+
# Variant compatible with the Data type.
|
1890
|
+
DATA = PVariantType.new([PHashType::DATA, PArrayType::DATA, PScalarType::DEFAULT, PUndefType::DEFAULT, PTupleType::DATA])
|
1891
|
+
|
1892
|
+
DEFAULT = PVariantType.new(EMPTY_ARRAY)
|
1893
|
+
|
1894
|
+
protected
|
1895
|
+
|
1896
|
+
# @api private
|
1897
|
+
def _assignable?(o, guard)
|
1898
|
+
# Data is a specific variant
|
1899
|
+
o = DATA if o.is_a?(PDataType)
|
1900
|
+
if o.is_a?(PVariantType)
|
1901
|
+
# A variant is assignable if all of its options are assignable to one of this type's options
|
1902
|
+
return true if self == o
|
1903
|
+
o.types.all? do |other|
|
1904
|
+
# if the other is a Variant, all of its options, but be assignable to one of this type's options
|
1905
|
+
other = other.is_a?(PDataType) ? DATA : other
|
1906
|
+
if other.is_a?(PVariantType)
|
1907
|
+
assignable?(other, guard)
|
1317
1908
|
else
|
1318
|
-
types.
|
1909
|
+
types.any? {|option_t| option_t.assignable?(other, guard) }
|
1319
1910
|
end
|
1320
1911
|
end
|
1912
|
+
else
|
1913
|
+
# A variant is assignable if o is assignable to any of its types
|
1914
|
+
types.any? { |option_t| option_t.assignable?(o, guard) }
|
1915
|
+
end
|
1916
|
+
end
|
1321
1917
|
|
1322
|
-
|
1323
|
-
|
1918
|
+
# @api private
|
1919
|
+
def swap_optionals(array)
|
1920
|
+
if array.size > 1
|
1921
|
+
parts = array.partition {|t| t.is_a?(POptionalType) }
|
1922
|
+
optionals = parts[0]
|
1923
|
+
if optionals.size > 1
|
1924
|
+
others = parts[1]
|
1925
|
+
others << POptionalType.new(PVariantType.new(optionals.map { |optional| optional.type }).normalize)
|
1926
|
+
array = others
|
1324
1927
|
end
|
1928
|
+
end
|
1929
|
+
array
|
1930
|
+
end
|
1325
1931
|
|
1326
|
-
|
1327
|
-
|
1932
|
+
# @api private
|
1933
|
+
def swap_not_undefs(array)
|
1934
|
+
if array.size > 1
|
1935
|
+
parts = array.partition {|t| t.is_a?(PNotUndefType) }
|
1936
|
+
not_undefs = parts[0]
|
1937
|
+
if not_undefs.size > 1
|
1938
|
+
others = parts[1]
|
1939
|
+
others << PNotUndefType.new(PVariantType.new(not_undefs.map { |not_undef| not_undef.type }).normalize)
|
1940
|
+
array = others
|
1328
1941
|
end
|
1942
|
+
end
|
1943
|
+
array
|
1944
|
+
end
|
1329
1945
|
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1946
|
+
# @api private
|
1947
|
+
def merge_enums(array)
|
1948
|
+
if array.size > 1
|
1949
|
+
parts = array.partition {|t| t.is_a?(PEnumType) || t.is_a?(PStringType) && !t.values.empty? }
|
1950
|
+
enums = parts[0]
|
1951
|
+
if enums.size > 1
|
1952
|
+
others = parts[1]
|
1953
|
+
others << PEnumType.new(enums.map { |enum| enum.values }.flatten.uniq)
|
1954
|
+
array = others
|
1333
1955
|
end
|
1956
|
+
end
|
1957
|
+
array
|
1958
|
+
end
|
1334
1959
|
|
1335
|
-
|
1336
|
-
|
1960
|
+
# @api private
|
1961
|
+
def merge_patterns(array)
|
1962
|
+
if array.size > 1
|
1963
|
+
parts = array.partition {|t| t.is_a?(PPatternType) }
|
1964
|
+
patterns = parts[0]
|
1965
|
+
if patterns.size > 1
|
1966
|
+
others = parts[1]
|
1967
|
+
others << PPatternType.new(patterns.map { |pattern| pattern.patterns }.flatten.uniq)
|
1968
|
+
array = others
|
1337
1969
|
end
|
1970
|
+
end
|
1971
|
+
array
|
1972
|
+
end
|
1338
1973
|
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1974
|
+
# @api private
|
1975
|
+
def merge_int_ranges(array)
|
1976
|
+
if array.size > 1
|
1977
|
+
parts = array.partition {|t| t.is_a?(PIntegerType) }
|
1978
|
+
ranges = parts[0]
|
1979
|
+
array = merge_ranges(ranges) + parts[1] if ranges.size > 1
|
1980
|
+
end
|
1981
|
+
array
|
1982
|
+
end
|
1344
1983
|
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
else
|
1365
|
-
types.any? {|option_t| option_t.assignable?(other) }
|
1366
|
-
end
|
1367
|
-
end
|
1984
|
+
def merge_float_ranges(array)
|
1985
|
+
if array.size > 1
|
1986
|
+
parts = array.partition {|t| t.is_a?(PFloatType) }
|
1987
|
+
ranges = parts[0]
|
1988
|
+
array = merge_ranges(ranges) + parts[1] if ranges.size > 1
|
1989
|
+
end
|
1990
|
+
array
|
1991
|
+
end
|
1992
|
+
|
1993
|
+
# @api private
|
1994
|
+
def merge_ranges(ranges)
|
1995
|
+
result = []
|
1996
|
+
while !ranges.empty?
|
1997
|
+
unmerged = []
|
1998
|
+
x = ranges.pop
|
1999
|
+
result << ranges.inject(x) do |memo, y|
|
2000
|
+
merged = memo.merge(y)
|
2001
|
+
if merged.nil?
|
2002
|
+
unmerged << y
|
1368
2003
|
else
|
1369
|
-
|
1370
|
-
types.any? { |option_t| option_t.assignable?(o) }
|
2004
|
+
memo = merged
|
1371
2005
|
end
|
2006
|
+
memo
|
1372
2007
|
end
|
2008
|
+
ranges = unmerged
|
1373
2009
|
end
|
2010
|
+
result
|
2011
|
+
end
|
2012
|
+
end
|
1374
2013
|
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
2014
|
+
# @api public
|
2015
|
+
#
|
2016
|
+
class PRuntimeType < PAnyType
|
2017
|
+
attr_reader :runtime, :runtime_type_name
|
1379
2018
|
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
2019
|
+
def initialize(runtime, runtime_type_name = nil)
|
2020
|
+
@runtime = runtime
|
2021
|
+
@runtime_type_name = runtime_type_name
|
2022
|
+
end
|
1384
2023
|
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
2024
|
+
def hash
|
2025
|
+
@runtime.hash * 31 + @runtime_type_name.hash
|
2026
|
+
end
|
1388
2027
|
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
2028
|
+
def eql?(o)
|
2029
|
+
self.class == o.class && @runtime == o.runtime && @runtime_type_name == o.runtime_type_name
|
2030
|
+
end
|
1392
2031
|
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
2032
|
+
def instance?(o)
|
2033
|
+
assignable?(TypeCalculator.infer(o))
|
2034
|
+
end
|
1396
2035
|
|
1397
|
-
|
2036
|
+
def iterable?(guard = nil)
|
2037
|
+
c = class_from_string(@runtime_type_name)
|
2038
|
+
c.nil? ? false : c < Iterable
|
2039
|
+
end
|
1398
2040
|
|
1399
|
-
|
2041
|
+
def iterable_type(guard = nil)
|
2042
|
+
iterable?(guard) ? PIterableType.new(self) : nil
|
2043
|
+
end
|
1400
2044
|
|
1401
|
-
|
1402
|
-
# a class that is the same or subclass of t1's resolved runtime type name
|
1403
|
-
# @api private
|
1404
|
-
def _assignable?(o)
|
1405
|
-
return false unless o.is_a?(PRuntimeType)
|
1406
|
-
return false unless @runtime == o.runtime
|
1407
|
-
return true if @runtime_type_name.nil? # t1 is wider
|
1408
|
-
return false if o.runtime_type_name.nil? # t1 not nil, so o can not be wider
|
2045
|
+
DEFAULT = PRuntimeType.new(nil)
|
1409
2046
|
|
1410
|
-
|
1411
|
-
c1 = class_from_string(@runtime_type_name)
|
1412
|
-
c2 = class_from_string(o.runtime_type_name)
|
1413
|
-
return false unless c1.is_a?(Module) && c2.is_a?(Module)
|
1414
|
-
!!(c2 <= c1)
|
1415
|
-
end
|
1416
|
-
end
|
2047
|
+
protected
|
1417
2048
|
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
2049
|
+
# Assignable if o's has the same runtime and the runtime name resolves to
|
2050
|
+
# a class that is the same or subclass of t1's resolved runtime type name
|
2051
|
+
# @api private
|
2052
|
+
def _assignable?(o, guard)
|
2053
|
+
return false unless o.is_a?(PRuntimeType)
|
2054
|
+
return false unless @runtime == o.runtime
|
2055
|
+
return true if @runtime_type_name.nil? # t1 is wider
|
2056
|
+
return false if o.runtime_type_name.nil? # t1 not nil, so o can not be wider
|
1422
2057
|
|
1423
|
-
|
2058
|
+
# NOTE: This only supports Ruby, must change when/if the set of runtimes is expanded
|
2059
|
+
c1 = class_from_string(@runtime_type_name)
|
2060
|
+
c2 = class_from_string(o.runtime_type_name)
|
2061
|
+
return false unless c1.is_a?(Module) && c2.is_a?(Module)
|
2062
|
+
!!(c2 <= c1)
|
2063
|
+
end
|
2064
|
+
end
|
1424
2065
|
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
2066
|
+
# Abstract representation of a type that can be placed in a Catalog.
|
2067
|
+
# @api public
|
2068
|
+
#
|
2069
|
+
class PCatalogEntryType < PAnyType
|
1428
2070
|
|
1429
|
-
|
1430
|
-
# @api private
|
1431
|
-
def _assignable?(o)
|
1432
|
-
o.is_a?(PCatalogEntryType)
|
1433
|
-
end
|
1434
|
-
end
|
2071
|
+
DEFAULT = PCatalogEntryType.new
|
1435
2072
|
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
class PHostClassType < PCatalogEntryType
|
1440
|
-
attr_reader :class_name
|
2073
|
+
def instance?(o)
|
2074
|
+
assignable?(TypeCalculator.infer(o))
|
2075
|
+
end
|
1441
2076
|
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
2077
|
+
protected
|
2078
|
+
# @api private
|
2079
|
+
def _assignable?(o, guard)
|
2080
|
+
o.is_a?(PCatalogEntryType)
|
2081
|
+
end
|
2082
|
+
end
|
1445
2083
|
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
end
|
2084
|
+
# Represents a (host-) class in the Puppet Language.
|
2085
|
+
# @api public
|
2086
|
+
#
|
2087
|
+
class PHostClassType < PCatalogEntryType
|
2088
|
+
attr_reader :class_name
|
1452
2089
|
|
1453
|
-
|
2090
|
+
def initialize(class_name)
|
2091
|
+
@class_name = class_name
|
2092
|
+
end
|
1454
2093
|
|
1455
|
-
|
2094
|
+
def hash
|
2095
|
+
11 * @class_name.hash
|
2096
|
+
end
|
2097
|
+
def eql?(o)
|
2098
|
+
self.class == o.class && @class_name == o.class_name
|
2099
|
+
end
|
1456
2100
|
|
1457
|
-
|
1458
|
-
def _assignable?(o)
|
1459
|
-
return false unless o.is_a?(PHostClassType)
|
1460
|
-
# Class = Class[name}, Class[name] != Class
|
1461
|
-
return true if @class_name.nil?
|
1462
|
-
# Class[name] = Class[name]
|
1463
|
-
@class_name == o.class_name
|
1464
|
-
end
|
1465
|
-
end
|
2101
|
+
DEFAULT = PHostClassType.new(nil)
|
1466
2102
|
|
1467
|
-
|
1468
|
-
# @api public
|
1469
|
-
#
|
1470
|
-
class PResourceType < PCatalogEntryType
|
1471
|
-
attr_reader :type_name, :title
|
2103
|
+
protected
|
1472
2104
|
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
2105
|
+
# @api private
|
2106
|
+
def _assignable?(o, guard)
|
2107
|
+
return false unless o.is_a?(PHostClassType)
|
2108
|
+
# Class = Class[name}, Class[name] != Class
|
2109
|
+
return true if @class_name.nil?
|
2110
|
+
# Class[name] = Class[name]
|
2111
|
+
@class_name == o.class_name
|
2112
|
+
end
|
2113
|
+
end
|
1477
2114
|
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
2115
|
+
# Represents a Resource Type in the Puppet Language
|
2116
|
+
# @api public
|
2117
|
+
#
|
2118
|
+
class PResourceType < PCatalogEntryType
|
2119
|
+
attr_reader :type_name, :title
|
1481
2120
|
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
2121
|
+
def initialize(type_name, title = nil)
|
2122
|
+
@type_name = type_name
|
2123
|
+
@title = title
|
2124
|
+
end
|
2125
|
+
|
2126
|
+
def hash
|
2127
|
+
@type_name.hash * 31 + @title.hash
|
2128
|
+
end
|
2129
|
+
|
2130
|
+
def eql?(o)
|
2131
|
+
self.class == o.class && @type_name == o.type_name && @title == o.title
|
2132
|
+
end
|
2133
|
+
|
2134
|
+
DEFAULT = PResourceType.new(nil)
|
2135
|
+
|
2136
|
+
protected
|
2137
|
+
|
2138
|
+
# @api private
|
2139
|
+
def _assignable?(o, guard)
|
2140
|
+
return false unless o.is_a?(PResourceType)
|
2141
|
+
return true if @type_name.nil?
|
2142
|
+
return false if @type_name != o.type_name
|
2143
|
+
return true if @title.nil?
|
2144
|
+
@title == o.title
|
2145
|
+
end
|
2146
|
+
end
|
2147
|
+
|
2148
|
+
# Represents a type that accept PUndefType instead of the type parameter
|
2149
|
+
# required_type - is a short hand for Variant[T, Undef]
|
2150
|
+
# @api public
|
2151
|
+
#
|
2152
|
+
class POptionalType < PTypeWithContainedType
|
2153
|
+
def optional_type
|
2154
|
+
@type
|
2155
|
+
end
|
1485
2156
|
|
1486
|
-
|
2157
|
+
def kind_of_callable?(optional=true, guard = nil)
|
2158
|
+
optional && !@type.nil? && @type.kind_of_callable?(optional, guard)
|
2159
|
+
end
|
1487
2160
|
|
1488
|
-
|
2161
|
+
def instance?(o)
|
2162
|
+
PUndefType::DEFAULT.instance?(o) || (!@type.nil? && @type.instance?(o))
|
2163
|
+
end
|
1489
2164
|
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
2165
|
+
def normalize(guard = nil)
|
2166
|
+
n = super
|
2167
|
+
if n.type.nil?
|
2168
|
+
n
|
2169
|
+
else
|
2170
|
+
if n.type.is_a?(PNotUndefType)
|
2171
|
+
# No point in having an NotUndef in an Optional
|
2172
|
+
POptionalType.new(n.type.type).normalize
|
2173
|
+
elsif n.type.assignable?(PUndefType::DEFAULT)
|
2174
|
+
# THe type is Optional anyway, so it can be stripped of
|
2175
|
+
n.type
|
2176
|
+
else
|
2177
|
+
n
|
1497
2178
|
end
|
1498
2179
|
end
|
2180
|
+
end
|
1499
2181
|
|
1500
|
-
|
1501
|
-
# required_type - is a short hand for Variant[T, Undef]
|
1502
|
-
# @api public
|
1503
|
-
#
|
1504
|
-
class POptionalType < PAnyType
|
1505
|
-
attr_reader :optional_type
|
2182
|
+
DEFAULT = POptionalType.new(nil)
|
1506
2183
|
|
1507
|
-
|
1508
|
-
@optional_type = optional_type
|
1509
|
-
end
|
2184
|
+
protected
|
1510
2185
|
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
2186
|
+
# @api private
|
2187
|
+
def _assignable?(o, guard)
|
2188
|
+
return true if o.is_a?(PUndefType)
|
2189
|
+
return true if @type.nil?
|
2190
|
+
if o.is_a?(POptionalType)
|
2191
|
+
@type.assignable?(o.optional_type, guard)
|
2192
|
+
else
|
2193
|
+
@type.assignable?(o, guard)
|
2194
|
+
end
|
2195
|
+
end
|
2196
|
+
end
|
1514
2197
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
end
|
2198
|
+
class PTypeReferenceType < PAnyType
|
2199
|
+
attr_reader :name, :parameters
|
1518
2200
|
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
2201
|
+
def initialize(name, parameters = nil)
|
2202
|
+
@name = name
|
2203
|
+
@parameters = parameters.nil? ? EMPTY_ARRAY : parameters
|
2204
|
+
end
|
1522
2205
|
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
2206
|
+
def callable?(args)
|
2207
|
+
false
|
2208
|
+
end
|
1526
2209
|
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
2210
|
+
def instance?(o)
|
2211
|
+
false
|
2212
|
+
end
|
2213
|
+
|
2214
|
+
def hash
|
2215
|
+
@name.hash * 31 + @parameters.hash
|
2216
|
+
end
|
1530
2217
|
|
1531
|
-
|
2218
|
+
def eql?(o)
|
2219
|
+
super && o.name == @name && o.parameters == @parameters
|
2220
|
+
end
|
1532
2221
|
|
1533
|
-
|
2222
|
+
protected
|
1534
2223
|
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
2224
|
+
def _assignable?(o, guard)
|
2225
|
+
# A type must be assignable to itself or a lot of unit tests will break
|
2226
|
+
o == self
|
2227
|
+
end
|
2228
|
+
|
2229
|
+
DEFAULT = PTypeReferenceType.new('UnresolvedReference')
|
2230
|
+
end
|
2231
|
+
|
2232
|
+
# Describes a named alias for another Type.
|
2233
|
+
# The alias is created with a name and an unresolved type expression. The type expression may
|
2234
|
+
# in turn contain other aliases (including the alias that contains it) which means that an alias
|
2235
|
+
# might contain self recursion. Whether or not that is the case is computed and remembered when the alias
|
2236
|
+
# is resolved since guarding against self recursive constructs is relatively expensive.
|
2237
|
+
#
|
2238
|
+
class PTypeAliasType < PAnyType
|
2239
|
+
attr_reader :name
|
2240
|
+
|
2241
|
+
# @param name [String] The name of the type
|
2242
|
+
# @param type_expr [Model::PopsObject] The expression that describes the aliased type
|
2243
|
+
# @param resolved_type [PAnyType] the resolve type (only used for the DEFAULT initialization)
|
2244
|
+
def initialize(name, type_expr, resolved_type = nil)
|
2245
|
+
@name = name
|
2246
|
+
@type_expr = type_expr
|
2247
|
+
@resolved_type = resolved_type
|
2248
|
+
@self_recursion = false
|
2249
|
+
end
|
2250
|
+
|
2251
|
+
# Returns the resolved type. The type must have been resolved by a call prior to calls to this
|
2252
|
+
# method or an error will be raised.
|
2253
|
+
#
|
2254
|
+
# @return [PAnyType] The resolved type of this alias.
|
2255
|
+
# @raise [Puppet::Error] unless the type has been resolved prior to calling this method
|
2256
|
+
def resolved_type
|
2257
|
+
raise Puppet::Error, "Reference to unresolved type #{@name}" unless @resolved_type
|
2258
|
+
@resolved_type
|
2259
|
+
end
|
2260
|
+
|
2261
|
+
def callable_args?(callable, guard)
|
2262
|
+
guarded_recursion(guard, false) { |g| resolved_type.callable_args?(callable, g) }
|
2263
|
+
end
|
2264
|
+
|
2265
|
+
def kind_of_callable?(optional=true, guard = nil)
|
2266
|
+
guarded_recursion(guard, false) { |g| resolved_type.kind_of_callable?(optional, g) }
|
2267
|
+
end
|
2268
|
+
|
2269
|
+
def instance?(o)
|
2270
|
+
# No value can ever be recursive so no guard is needed here
|
2271
|
+
resolved_type.instance?(o)
|
2272
|
+
end
|
2273
|
+
|
2274
|
+
def iterable?(guard = nil)
|
2275
|
+
guarded_recursion(guard, false) { |g| resolved_type.iterable?(g) }
|
2276
|
+
end
|
2277
|
+
|
2278
|
+
def iterable_type(guard = nil)
|
2279
|
+
guarded_recursion(guard, nil) { |g| resolved_type.iterable_type(g) }
|
2280
|
+
end
|
2281
|
+
|
2282
|
+
def hash
|
2283
|
+
@name.hash
|
2284
|
+
end
|
2285
|
+
|
2286
|
+
# Called from the TypeParser once it has found a type using the Loader. The TypeParser will
|
2287
|
+
# interpret the contained expression and the resolved type is remembered. This method also
|
2288
|
+
# checks and remembers if the resolve type contains self recursion.
|
2289
|
+
#
|
2290
|
+
# @param type_parser [TypeParser] type parser that will interpret the type expression
|
2291
|
+
# @param loader [Loader::Loader] loader to use when loading type aliases
|
2292
|
+
# @return [PTypeAliasType] the receiver of the call, i.e. `self`
|
2293
|
+
# @api private
|
2294
|
+
def resolve(type_parser, loader)
|
2295
|
+
if @resolved_type.nil?
|
2296
|
+
# resolved to PTypeReferenceType::DEFAULT during resolve to avoid endless recursion
|
2297
|
+
@resolved_type = PTypeReferenceType::DEFAULT
|
2298
|
+
@self_recursion = true # assumed while it being found out below
|
2299
|
+
begin
|
2300
|
+
@resolved_type = type_parser.interpret(@type_expr, loader).normalize
|
2301
|
+
|
2302
|
+
# Find out if this type is recursive. A recursive type has performance implications
|
2303
|
+
# on several methods and this knowledge is used to avoid that for non-recursive
|
2304
|
+
# types.
|
2305
|
+
guard = RecursionGuard.new
|
2306
|
+
accept(NoopTypeAcceptor::INSTANCE, guard)
|
2307
|
+
@self_recursion = guard.recursive_this?(self)
|
2308
|
+
rescue
|
2309
|
+
@resolved_type = nil
|
2310
|
+
raise
|
1544
2311
|
end
|
1545
2312
|
end
|
2313
|
+
self
|
2314
|
+
end
|
2315
|
+
|
2316
|
+
def eql?(o)
|
2317
|
+
super && o.name == @name
|
1546
2318
|
end
|
1547
|
-
end
|
1548
2319
|
|
2320
|
+
def accept(visitor, guard)
|
2321
|
+
guarded_recursion(guard, nil) do |g|
|
2322
|
+
super
|
2323
|
+
resolved_type.accept(visitor, g)
|
2324
|
+
end
|
2325
|
+
end
|
2326
|
+
|
2327
|
+
def self_recursion?
|
2328
|
+
@self_recursion
|
2329
|
+
end
|
2330
|
+
|
2331
|
+
protected
|
2332
|
+
|
2333
|
+
def _assignable?(o, guard)
|
2334
|
+
guard ||= RecursionGuard.new
|
2335
|
+
if guard.add_this(self) == RecursionGuard::SELF_RECURSION_IN_BOTH
|
2336
|
+
# Recursion detected both in self and other. This means that other is assignable
|
2337
|
+
# to self. This point would not have been reached otherwise
|
2338
|
+
true
|
2339
|
+
else
|
2340
|
+
resolved_type.assignable?(o, guard)
|
2341
|
+
end
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
private
|
2345
|
+
|
2346
|
+
def guarded_recursion(guard, dflt)
|
2347
|
+
if @self_recursion
|
2348
|
+
guard ||= RecursionGuard.new
|
2349
|
+
(guard.add_this(self) & RecursionGuard::SELF_RECURSION_IN_THIS) == 0 ? yield(guard) : dflt
|
2350
|
+
else
|
2351
|
+
yield(guard)
|
2352
|
+
end
|
2353
|
+
end
|
2354
|
+
|
2355
|
+
DEFAULT = PTypeAliasType.new('UnresolvedAlias', nil, PTypeReferenceType::DEFAULT)
|
2356
|
+
end
|
2357
|
+
end
|
2358
|
+
end
|