puppet 5.0.1 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/puppet/agent.rb +1 -0
- data/lib/puppet/defaults.rb +1 -1
- data/lib/puppet/functions.rb +6 -7
- data/lib/puppet/functions/all.rb +100 -0
- data/lib/puppet/functions/any.rb +105 -0
- data/lib/puppet/functions/defined.rb +3 -3
- data/lib/puppet/functions/new.rb +2 -1
- data/lib/puppet/functions/reduce.rb +31 -0
- data/lib/puppet/functions/tree_each.rb +200 -0
- data/lib/puppet/module.rb +30 -0
- data/lib/puppet/parser/functions/new.rb +67 -0
- data/lib/puppet/parser/functions/reduce.rb +31 -0
- data/lib/puppet/parser/relationship.rb +2 -2
- data/lib/puppet/parser/resource.rb +39 -10
- data/lib/puppet/parser/scope.rb +1 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +11 -4
- data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -4
- data/lib/puppet/pops/evaluator/relationship_operator.rb +1 -1
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +3 -3
- data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -1
- data/lib/puppet/pops/loader/module_loaders.rb +1 -1
- data/lib/puppet/pops/loader/static_loader.rb +1 -2
- data/lib/puppet/pops/loaders.rb +1 -2
- data/lib/puppet/pops/lookup/context.rb +1 -1
- data/lib/puppet/pops/lookup/lookup_adapter.rb +2 -1
- data/lib/puppet/pops/model/ast.rb +440 -436
- data/lib/puppet/pops/model/factory.rb +140 -140
- data/lib/puppet/pops/pcore.rb +1 -2
- data/lib/puppet/pops/resource/param.rb +1 -1
- data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
- data/lib/puppet/pops/serialization/from_data_converter.rb +0 -12
- data/lib/puppet/pops/time/timestamp.rb +29 -17
- data/lib/puppet/pops/types/annotatable.rb +2 -2
- data/lib/puppet/pops/types/annotation.rb +8 -8
- data/lib/puppet/pops/types/class_loader.rb +3 -3
- data/lib/puppet/pops/types/implementation_registry.rb +1 -1
- data/lib/puppet/pops/types/iterable.rb +2 -2
- data/lib/puppet/pops/types/p_binary_type.rb +2 -2
- data/lib/puppet/pops/types/p_init_type.rb +238 -0
- data/lib/puppet/pops/types/p_meta_type.rb +14 -11
- data/lib/puppet/pops/types/p_object_type.rb +15 -15
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +2 -2
- data/lib/puppet/pops/types/p_sem_ver_type.rb +2 -2
- data/lib/puppet/pops/types/p_sensitive_type.rb +2 -2
- data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
- data/lib/puppet/pops/types/p_timestamp_type.rb +6 -2
- data/lib/puppet/pops/types/p_type_set_type.rb +10 -9
- data/lib/puppet/pops/types/ruby_generator.rb +6 -5
- data/lib/puppet/pops/types/ruby_method.rb +2 -2
- data/lib/puppet/pops/types/string_converter.rb +1 -1
- data/lib/puppet/pops/types/tree_iterators.rb +250 -0
- data/lib/puppet/pops/types/type_calculator.rb +13 -13
- data/lib/puppet/pops/types/type_factory.rb +26 -7
- data/lib/puppet/pops/types/type_formatter.rb +9 -4
- data/lib/puppet/pops/types/type_parser.rb +8 -3
- data/lib/puppet/pops/types/type_set_reference.rb +2 -2
- data/lib/puppet/pops/types/types.rb +168 -109
- data/lib/puppet/provider/package/gem.rb +10 -9
- data/lib/puppet/provider/package/pip.rb +12 -3
- data/lib/puppet/provider/package/yum.rb +9 -1
- data/lib/puppet/resource/capability_finder.rb +30 -11
- data/lib/puppet/type/file.rb +21 -13
- data/lib/puppet/util/execution.rb +67 -14
- data/lib/puppet/util/suidmanager.rb +1 -0
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +130 -66
- data/man/man5/puppet.conf.5 +1 -1
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-simple.txt +1 -0
- data/spec/integration/parser/collection_spec.rb +40 -1
- data/spec/shared_contexts/types_setup.rb +41 -2
- data/spec/unit/agent_spec.rb +11 -0
- data/spec/unit/file_bucket/dipper_spec.rb +13 -4
- data/spec/unit/functions/all_spec.rb +97 -0
- data/spec/unit/functions/any_spec.rb +109 -0
- data/spec/unit/functions/hiera_spec.rb +5 -0
- data/spec/unit/functions/new_spec.rb +66 -0
- data/spec/unit/functions/tree_each_spec.rb +444 -0
- data/spec/unit/module_spec.rb +29 -0
- data/spec/unit/pops/serialization/serialization_spec.rb +2 -2
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +2 -2
- data/spec/unit/pops/types/iterable_spec.rb +9 -9
- data/spec/unit/pops/types/p_init_type_spec.rb +285 -0
- data/spec/unit/pops/types/p_object_type_spec.rb +8 -8
- data/spec/unit/pops/types/p_sensitive_type_spec.rb +4 -0
- data/spec/unit/pops/types/p_timespan_type_spec.rb +14 -0
- data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -1
- data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
- data/spec/unit/pops/types/ruby_generator_spec.rb +9 -22
- data/spec/unit/pops/types/string_converter_spec.rb +2 -2
- data/spec/unit/pops/types/type_acceptor_spec.rb +2 -2
- data/spec/unit/pops/types/type_calculator_spec.rb +43 -38
- data/spec/unit/pops/types/type_factory_spec.rb +6 -6
- data/spec/unit/pops/types/type_formatter_spec.rb +6 -6
- data/spec/unit/pops/types/types_spec.rb +16 -4
- data/spec/unit/provider/package/gem_spec.rb +6 -6
- data/spec/unit/provider/package/pip_spec.rb +44 -23
- data/spec/unit/provider/package/puppet_gem_spec.rb +1 -1
- data/spec/unit/provider/package/yum_spec.rb +8 -0
- data/spec/unit/resource/capability_finder_spec.rb +4 -5
- data/spec/unit/type/file_spec.rb +19 -14
- data/spec/unit/util/execution_spec.rb +216 -82
- data/tasks/generate_ast_model.rake +10 -2
- metadata +15 -2
data/lib/puppet/pops/pcore.rb
CHANGED
@@ -96,8 +96,7 @@ module Pcore
|
|
96
96
|
aliases.each do |name, type_string|
|
97
97
|
add_type(Types::PTypeAliasType.new(name, Types::TypeFactory.type_reference(type_string), nil), loader, name_authority)
|
98
98
|
end
|
99
|
-
|
100
|
-
aliases.each_key.map { |name| loader.load(:type, name).resolve(parser, loader) }
|
99
|
+
aliases.each_key.map { |name| loader.load(:type, name).resolve(loader) }
|
101
100
|
end
|
102
101
|
end
|
103
102
|
end
|
@@ -21,7 +21,7 @@ class Param
|
|
21
21
|
def self.register_ptype(loader, ir)
|
22
22
|
@ptype = Pcore::create_object_type(loader, ir, self, 'Puppet::Resource::Param', nil,
|
23
23
|
{
|
24
|
-
Types::KEY_TYPE => Types::
|
24
|
+
Types::KEY_TYPE => Types::PTypeType::DEFAULT,
|
25
25
|
Types::KEY_NAME => Types::PStringType::NON_EMPTY,
|
26
26
|
'name_var' => {
|
27
27
|
Types::KEY_TYPE => Types::PBooleanType::DEFAULT,
|
@@ -164,18 +164,6 @@ module Serialization
|
|
164
164
|
{ :type_name => pcore_type.name, :arg_class => value.class.name }
|
165
165
|
end
|
166
166
|
end
|
167
|
-
|
168
|
-
def data_to_pcore_type(pcore_type)
|
169
|
-
if pcore_type.is_a?(Hash)
|
170
|
-
without_value { convert(pcore_type) }
|
171
|
-
else
|
172
|
-
type = Types::TypeParser.singleton.parse(pcore_type, @loader)
|
173
|
-
if type.is_a?(Types::PTypeReferenceType)
|
174
|
-
raise SerializationError, _('No implementation mapping found for Puppet Type %{type_name}') % { type_name: pcore_type }
|
175
|
-
end
|
176
|
-
type
|
177
|
-
end
|
178
|
-
end
|
179
167
|
end
|
180
168
|
end
|
181
169
|
end
|
@@ -71,31 +71,43 @@ class Timestamp < TimeData
|
|
71
71
|
parsed = nil
|
72
72
|
if format.is_a?(Array)
|
73
73
|
format.each do |fmt|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
parsed = DateTime._strptime(str, fmt)
|
75
|
+
next if parsed.nil?
|
76
|
+
if parsed.include?(:leftover) || (has_timezone && parsed.include?(:zone))
|
77
|
+
parsed = nil
|
78
|
+
next
|
79
79
|
end
|
80
|
+
break
|
81
|
+
end
|
82
|
+
if parsed.nil?
|
83
|
+
raise ArgumentError, _(
|
84
|
+
"Unable to parse '%{str}' using any of the formats %{formats}") % { str: str, formats: format.join(', ') }
|
80
85
|
end
|
81
|
-
raise ArgumentError, _("Unable to parse '%{str}' using any of the formats %{formats}") % { str: str, formats: format.join(', ') } if parsed.nil?
|
82
86
|
else
|
83
|
-
|
84
|
-
|
85
|
-
parsed = DateTime.strptime(str, format)
|
86
|
-
rescue ArgumentError
|
87
|
+
parsed = DateTime._strptime(str, format)
|
88
|
+
if parsed.nil? || parsed.include?(:leftover)
|
87
89
|
raise ArgumentError, _("Unable to parse '%{str}' using format '%{format}'") % { str: str, format: format }
|
88
90
|
end
|
91
|
+
if has_timezone && parsed.include?(:zone)
|
92
|
+
raise ArgumentError, _(
|
93
|
+
'Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
unless has_timezone
|
97
|
+
timezone = parsed[:zone]
|
98
|
+
has_timezone = !timezone.nil?
|
89
99
|
end
|
90
|
-
|
100
|
+
fraction = parsed[:sec_fraction]
|
101
|
+
|
102
|
+
# Convert msec rational found in _strptime hash to usec
|
103
|
+
fraction = fraction * 1000000 unless fraction.nil?
|
104
|
+
|
105
|
+
# Create the Time instance and adjust for timezone
|
106
|
+
parsed_time = ::Time.utc(parsed[:year], parsed[:mon], parsed[:mday], parsed[:hour], parsed[:min], parsed[:sec], fraction)
|
91
107
|
parsed_time -= utc_offset(timezone) if has_timezone
|
92
|
-
from_time(parsed_time)
|
93
|
-
end
|
94
108
|
|
95
|
-
|
96
|
-
|
97
|
-
raise ArgumentError, _('Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument')
|
98
|
-
end
|
109
|
+
# Convert to Timestamp
|
110
|
+
from_time(parsed_time)
|
99
111
|
end
|
100
112
|
|
101
113
|
undef_method :-@, :+@, :div, :fdiv, :abs, :abs2, :magnitude # does not make sense on a Timestamp
|
@@ -7,9 +7,9 @@ KEY_ANNOTATIONS = 'annotations'.freeze
|
|
7
7
|
#
|
8
8
|
# @api public
|
9
9
|
module Annotatable
|
10
|
-
TYPE_ANNOTATIONS = PHashType.new(
|
10
|
+
TYPE_ANNOTATIONS = PHashType.new(PTypeType.new(PTypeReferenceType.new('Annotation')), PHashType::DEFAULT)
|
11
11
|
|
12
|
-
# @return [{
|
12
|
+
# @return [{PTypeType => PStructType}] the map of annotations
|
13
13
|
# @api public
|
14
14
|
def annotations
|
15
15
|
@annotations.nil? ? EMPTY_HASH : @annotations
|
@@ -21,29 +21,29 @@ module Types
|
|
21
21
|
# If no annotation was found and no block is given, this method returns `nil`
|
22
22
|
#
|
23
23
|
# @param o [Object] object to annotate
|
24
|
-
# @param block [Proc] optional, evaluated when a new annotation must be created. Should return the
|
24
|
+
# @param block [Proc] optional, evaluated when a new annotation must be created. Should return the init hash
|
25
25
|
# @return [Annotation<self>] an annotation of the same class as the receiver of the call
|
26
26
|
#
|
27
27
|
def self.annotate(o)
|
28
28
|
adapter = get(o)
|
29
29
|
if adapter.nil?
|
30
30
|
if o.is_a?(Annotatable)
|
31
|
-
|
32
|
-
|
31
|
+
init_hash = o.annotations[_pcore_type]
|
32
|
+
init_hash = yield if init_hash.nil? && block_given?
|
33
33
|
else
|
34
|
-
|
34
|
+
init_hash = yield if block_given?
|
35
35
|
end
|
36
|
-
adapter = associate_adapter(_pcore_type.from_hash(
|
36
|
+
adapter = associate_adapter(_pcore_type.from_hash(init_hash), o) unless init_hash.nil?
|
37
37
|
end
|
38
38
|
adapter
|
39
39
|
end
|
40
40
|
|
41
41
|
# Forces the creation or removal of an annotation of this type.
|
42
|
-
# If `
|
43
|
-
# If `
|
42
|
+
# If `init_hash` is a hash, a new annotation is created and returned
|
43
|
+
# If `init_hash` is `nil`, then the annotation is cleared and the previous annotation is returned.
|
44
44
|
#
|
45
45
|
# @param o [Object] object to annotate
|
46
|
-
# @param
|
46
|
+
# @param init_hash [Hash{String,Object},nil] the initializer for the annotation or `nil` to clear the annotation
|
47
47
|
# @return [Annotation<self>] an annotation of the same class as the receiver of the call
|
48
48
|
#
|
49
49
|
def self.annotate_new(o, init_hash)
|
@@ -24,7 +24,7 @@ class ClassLoader
|
|
24
24
|
when Array
|
25
25
|
provide_from_name_path(name.join('::'), name)
|
26
26
|
|
27
|
-
when PAnyType,
|
27
|
+
when PAnyType, PTypeType
|
28
28
|
provide_from_type(name)
|
29
29
|
|
30
30
|
else
|
@@ -44,8 +44,8 @@ class ClassLoader
|
|
44
44
|
# There is no other thing to load except this Enum meta type
|
45
45
|
RGen::MetamodelBuilder::MMBase::Boolean
|
46
46
|
|
47
|
-
when
|
48
|
-
# TODO:
|
47
|
+
when PTypeType
|
48
|
+
# TODO: PTypeType should have a type argument (a PAnyType) so the Class' class could be returned
|
49
49
|
# (but this only matters in special circumstances when meta programming has been used).
|
50
50
|
Class
|
51
51
|
|
@@ -41,7 +41,7 @@ module Types
|
|
41
41
|
TypeAsserter.assert_instance_of('Second argument of type mapping', TYPE_REGEXP_SUBST, puppet_type_or_pattern)
|
42
42
|
register_implementation_regexp(puppet_type_or_pattern, expr, loader)
|
43
43
|
else
|
44
|
-
TypeAsserter.assert_instance_of('Second argument of type mapping',
|
44
|
+
TypeAsserter.assert_instance_of('Second argument of type mapping', PTypeType::DEFAULT, puppet_type_or_pattern)
|
45
45
|
register_implementation(puppet_type_or_pattern, expr, loader)
|
46
46
|
end
|
47
47
|
end
|
@@ -132,13 +132,13 @@ module Puppet::Pops::Types
|
|
132
132
|
def reverse_each(&block)
|
133
133
|
# Default implementation cannot propagate reverse_each to a new enumerator so chained
|
134
134
|
# calls must put reverse_each last.
|
135
|
-
raise ArgumentError 'reverse_each() is not implemented'
|
135
|
+
raise ArgumentError, 'reverse_each() is not implemented'
|
136
136
|
end
|
137
137
|
|
138
138
|
def step(step, &block)
|
139
139
|
# Default implementation cannot propagate step to a new enumerator so chained
|
140
140
|
# calls must put stepping last.
|
141
|
-
raise ArgumentError 'step() is not implemented'
|
141
|
+
raise ArgumentError, 'step() is not implemented'
|
142
142
|
end
|
143
143
|
|
144
144
|
def to_a
|
@@ -144,8 +144,8 @@ class PBinaryType < PAnyType
|
|
144
144
|
end
|
145
145
|
|
146
146
|
# @api private
|
147
|
-
def self.new_function(
|
148
|
-
@new_function ||= Puppet::Functions.create_loaded_function(:new_Binary, loader) do
|
147
|
+
def self.new_function(type)
|
148
|
+
@new_function ||= Puppet::Functions.create_loaded_function(:new_Binary, type.loader) do
|
149
149
|
local_types do
|
150
150
|
type 'ByteInteger = Integer[0,255]'
|
151
151
|
type 'Base64Format = Enum["%b", "%u", "%B", "%s", "%r"]'
|
@@ -0,0 +1,238 @@
|
|
1
|
+
module Puppet::Pops
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# @api public
|
5
|
+
class PInitType < PTypeWithContainedType
|
6
|
+
def self.register_ptype(loader, ir)
|
7
|
+
create_ptype(loader, ir, 'AnyType',
|
8
|
+
'type' => {
|
9
|
+
KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
|
10
|
+
KEY_VALUE => nil
|
11
|
+
},
|
12
|
+
'init_args' => {
|
13
|
+
KEY_TYPE => PArrayType::DEFAULT,
|
14
|
+
KEY_VALUE => EMPTY_ARRAY
|
15
|
+
}
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :init_args
|
20
|
+
|
21
|
+
def initialize(type, init_args)
|
22
|
+
super(type)
|
23
|
+
@init_args = init_args.nil? ? EMPTY_ARRAY : init_args
|
24
|
+
|
25
|
+
if type.nil?
|
26
|
+
raise ArgumentError, _('Init cannot be parameterized with an undefined type and additional arguments') unless @init_args.empty?
|
27
|
+
@initialized = true
|
28
|
+
else
|
29
|
+
@initialized = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def instance?(o, guard = nil)
|
34
|
+
really_instance?(o, guard) == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def really_instance?(o, guard = nil)
|
39
|
+
if @type.nil?
|
40
|
+
TypeFactory.rich_data.really_instance?(o)
|
41
|
+
else
|
42
|
+
assert_initialized
|
43
|
+
guarded_recursion(guard, 0) do |g|
|
44
|
+
v = @type.really_instance?(o, g)
|
45
|
+
if v < 1
|
46
|
+
if @single_type
|
47
|
+
s = @single_type.really_instance?(o, g)
|
48
|
+
v = s if s > v
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if v < 1
|
52
|
+
if @other_type
|
53
|
+
s = @other_type.really_instance?(o, g)
|
54
|
+
s = @other_type.really_instance?([o], g) if s < 0 && @has_optional_single
|
55
|
+
v = s if s > v
|
56
|
+
end
|
57
|
+
end
|
58
|
+
v
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def eql?(o)
|
64
|
+
super && @init_args == o.init_args
|
65
|
+
end
|
66
|
+
|
67
|
+
def hash
|
68
|
+
super ^ @init_args.hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def new_function
|
72
|
+
return super if type.nil?
|
73
|
+
assert_initialized
|
74
|
+
|
75
|
+
target_type = type
|
76
|
+
single_type = @single_type
|
77
|
+
if @init_args.empty?
|
78
|
+
@new_function ||= Puppet::Functions.create_function(:new_Init, Puppet::Functions::InternalFunction) do
|
79
|
+
@target_type = target_type
|
80
|
+
@single_type = single_type
|
81
|
+
|
82
|
+
dispatch :from_array do
|
83
|
+
scope_param
|
84
|
+
param 'Array', :value
|
85
|
+
end
|
86
|
+
|
87
|
+
dispatch :create do
|
88
|
+
scope_param
|
89
|
+
param 'Any', :value
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.create(scope, value, func)
|
93
|
+
func.call(scope, @target_type, value)
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.from_array(scope, value, func)
|
97
|
+
# If there is a single argument that matches the array, then that gets priority over
|
98
|
+
# expanding the array into all arguments
|
99
|
+
if @single_type.instance?(value) || (@other_type && !@other_type.instance?(value) && @has_optional_single && @other_type.instance?([value]))
|
100
|
+
func.call(scope, @target_type, value)
|
101
|
+
else
|
102
|
+
func.call(scope, @target_type, *value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def from_array(scope, value)
|
107
|
+
self.class.from_array(scope, value, loader.load(:function, 'new'))
|
108
|
+
end
|
109
|
+
|
110
|
+
def create(scope, value)
|
111
|
+
self.class.create(scope, value, loader.load(:function, 'new'))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
else
|
115
|
+
init_args = @init_args
|
116
|
+
@new_function ||= Puppet::Functions.create_function(:new_Init, Puppet::Functions::InternalFunction) do
|
117
|
+
@target_type = target_type
|
118
|
+
@init_args = init_args
|
119
|
+
|
120
|
+
dispatch :create do
|
121
|
+
scope_param
|
122
|
+
param 'Any', :value
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.create(scope, value, func)
|
126
|
+
func.call(scope, @target_type, value, *@init_args)
|
127
|
+
end
|
128
|
+
|
129
|
+
def create(scope, value)
|
130
|
+
self.class.create(scope, value, loader.load(:function, 'new'))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
DEFAULT = PInitType.new(nil, EMPTY_ARRAY)
|
137
|
+
|
138
|
+
EXACTLY_ONE = [1, 1].freeze
|
139
|
+
|
140
|
+
def assert_initialized
|
141
|
+
return self if @initialized
|
142
|
+
|
143
|
+
@initialized = true
|
144
|
+
@self_recursion = true
|
145
|
+
|
146
|
+
begin
|
147
|
+
# Filter out types that will provide a new_function but are unsuitable to be contained in Init
|
148
|
+
#
|
149
|
+
# Calling Init#new would cause endless recursion
|
150
|
+
# The Optional is the same as Variant[T,Undef].
|
151
|
+
# The NotUndef is not meaningful to create instances of
|
152
|
+
if @type.instance_of?(PInitType) || @type.instance_of?(POptionalType) || @type.instance_of?(PNotUndefType)
|
153
|
+
raise ArgumentError.new
|
154
|
+
end
|
155
|
+
new_func = @type.new_function
|
156
|
+
rescue ArgumentError
|
157
|
+
raise ArgumentError, _("Creation of new instance of type '%{type_name}' is not supported") % { type_name: @type.to_s }
|
158
|
+
end
|
159
|
+
param_tuples = new_func.dispatcher.dispatchers.map { |closure| closure.type.param_types }
|
160
|
+
|
161
|
+
# An instance of the contained type is always a match to this type.
|
162
|
+
single_types = [@type]
|
163
|
+
|
164
|
+
if @init_args.empty?
|
165
|
+
# A value that is assignable to the type of a single parameter is also a match
|
166
|
+
single_tuples, other_tuples = param_tuples.partition { |tuple| EXACTLY_ONE == tuple.size_range }
|
167
|
+
single_types.concat(single_tuples.map { |tuple| tuple.types[0] })
|
168
|
+
else
|
169
|
+
tc = TypeCalculator.singleton
|
170
|
+
init_arg_types = @init_args.map { |arg| tc.infer_set(arg) }
|
171
|
+
arg_count = 1 + init_arg_types.size
|
172
|
+
|
173
|
+
# disqualify all parameter tuples that doesn't allow one value (type unknown at ths stage) + init args.
|
174
|
+
param_tuples = param_tuples.select do |tuple|
|
175
|
+
min, max = tuple.size_range
|
176
|
+
if arg_count >= min && arg_count <= max
|
177
|
+
# Aside from the first parameter, does the other parameters match?
|
178
|
+
tuple.assignable?(PTupleType.new(tuple.types[0..0].concat(init_arg_types)))
|
179
|
+
else
|
180
|
+
false
|
181
|
+
end
|
182
|
+
end
|
183
|
+
if param_tuples.empty?
|
184
|
+
raise ArgumentError, _("The type '%{type}' does not represent a valid set of parameters for %{subject}.new()") %
|
185
|
+
{ type: to_s, subject: @type.generalize.name }
|
186
|
+
end
|
187
|
+
single_types.concat(param_tuples.map { |tuple| tuple.types[0] })
|
188
|
+
other_tuples = EMPTY_ARRAY
|
189
|
+
end
|
190
|
+
@single_type = PVariantType.maybe_create(single_types)
|
191
|
+
unless other_tuples.empty?
|
192
|
+
@other_type = PVariantType.maybe_create(other_tuples)
|
193
|
+
@has_optional_single = other_tuples.any? { |tuple| tuple.size_range.min == 1 }
|
194
|
+
end
|
195
|
+
|
196
|
+
guard = RecursionGuard.new
|
197
|
+
accept(NoopTypeAcceptor::INSTANCE, guard)
|
198
|
+
@self_recursion = guard.recursive_this?(self)
|
199
|
+
end
|
200
|
+
|
201
|
+
def accept(visitor, guard)
|
202
|
+
guarded_recursion(guard, nil) do |g|
|
203
|
+
super(visitor, g)
|
204
|
+
@single_type.accept(visitor, guard) if @single_type
|
205
|
+
@other_type.accept(visitor, guard) if @other_type
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
protected
|
210
|
+
|
211
|
+
def _assignable?(o, guard)
|
212
|
+
guarded_recursion(guard, false) do |g|
|
213
|
+
assert_initialized
|
214
|
+
if o.is_a?(PInitType)
|
215
|
+
@type.nil? || @type.assignable?(o.type, g)
|
216
|
+
elsif @type.nil?
|
217
|
+
TypeFactory.rich_data.assignable?(o, g)
|
218
|
+
else
|
219
|
+
@type.assignable?(o, g) ||
|
220
|
+
@single_type && @single_type.assignable?(o, g) ||
|
221
|
+
@other_type && (@other_type.assignable?(o, g) || @has_optional_single && @other_type.assignable?(PTupleType.new([o])))
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def guarded_recursion(guard, dflt)
|
229
|
+
if @self_recursion
|
230
|
+
guard ||= RecursionGuard.new
|
231
|
+
guard.with_this(self) { |state| (state & RecursionGuard::SELF_RECURSION_IN_THIS) == 0 ? yield(guard) : dflt }
|
232
|
+
else
|
233
|
+
yield(guard)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|