class Puppet::Pops::Types::PInitType

@api public

Constants

DEFAULT
EXACTLY_ONE

Attributes

init_args[R]

Public Class Methods

create(scope, value, func) click to toggle source
   # File lib/puppet/pops/types/p_init_type.rb
93 def self.create(scope, value, func)
94   func.call(scope, @target_type, value)
95 end
from_array(scope, value, func) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
 97 def self.from_array(scope, value, func)
 98   # If there is a single argument that matches the array, then that gets priority over
 99   # expanding the array into all arguments
100   if @single_type.instance?(value) || (@other_type && !@other_type.instance?(value) && @has_optional_single && @other_type.instance?([value]))
101     func.call(scope, @target_type, value)
102   else
103     func.call(scope, @target_type, *value)
104   end
105 end
new(type, init_args) click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
22 def initialize(type, init_args)
23   super(type)
24   @init_args = init_args.nil? ? EMPTY_ARRAY : init_args
25 
26   if type.nil?
27     raise ArgumentError, _('Init cannot be parameterized with an undefined type and additional arguments') unless @init_args.empty?
28     @initialized = true
29   else
30     @initialized = false
31   end
32 end
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/p_init_type.rb
 7 def self.register_ptype(loader, ir)
 8   create_ptype(loader, ir, 'AnyType',
 9     'type' => {
10       KEY_TYPE => POptionalType.new(PTypeType::DEFAULT),
11       KEY_VALUE => nil
12     },
13     'init_args' => {
14       KEY_TYPE => PArrayType::DEFAULT,
15       KEY_VALUE => EMPTY_ARRAY
16     }
17   )
18 end

Public Instance Methods

accept(visitor, guard) click to toggle source
Calls superclass method
    # File lib/puppet/pops/types/p_init_type.rb
202 def accept(visitor, guard)
203   guarded_recursion(guard, nil) do |g|
204     super(visitor, g)
205     @single_type.accept(visitor, guard) if @single_type
206     @other_type.accept(visitor, guard) if @other_type
207   end
208 end
assert_initialized() click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
141 def assert_initialized
142   return self if @initialized
143 
144   @initialized = true
145   @self_recursion = true
146 
147   begin
148     # Filter out types that will provide a new_function but are unsuitable to be contained in Init
149     #
150     # Calling Init#new would cause endless recursion
151     # The Optional is the same as Variant[T,Undef].
152     # The NotUndef is not meaningful to create instances of
153     if @type.instance_of?(PInitType) || @type.instance_of?(POptionalType) || @type.instance_of?(PNotUndefType)
154       raise ArgumentError.new
155     end
156     new_func = @type.new_function
157   rescue ArgumentError
158     raise ArgumentError, _("Creation of new instance of type '%{type_name}' is not supported") % { type_name: @type.to_s }
159   end
160   param_tuples = new_func.dispatcher.signatures.map { |closure| closure.type.param_types }
161 
162   # An instance of the contained type is always a match to this type.
163   single_types = [@type]
164 
165   if @init_args.empty?
166     # A value that is assignable to the type of a single parameter is also a match
167     single_tuples, other_tuples = param_tuples.partition { |tuple| EXACTLY_ONE == tuple.size_range }
168     single_types.concat(single_tuples.map { |tuple| tuple.types[0] })
169   else
170     tc = TypeCalculator.singleton
171     init_arg_types = @init_args.map { |arg| tc.infer_set(arg) }
172     arg_count = 1 + init_arg_types.size
173 
174     # disqualify all parameter tuples that doesn't allow one value (type unknown at ths stage) + init args.
175     param_tuples = param_tuples.select do |tuple|
176       min, max = tuple.size_range
177       if arg_count >= min && arg_count <= max
178         # Aside from the first parameter, does the other parameters match?
179         tuple.assignable?(PTupleType.new(tuple.types[0..0].concat(init_arg_types)))
180       else
181         false
182       end
183     end
184     if param_tuples.empty?
185       raise ArgumentError, _("The type '%{type}' does not represent a valid set of parameters for %{subject}.new()") %
186         { type: to_s, subject: @type.generalize.name }
187     end
188     single_types.concat(param_tuples.map { |tuple| tuple.types[0] })
189     other_tuples = EMPTY_ARRAY
190   end
191   @single_type = PVariantType.maybe_create(single_types)
192   unless other_tuples.empty?
193     @other_type = PVariantType.maybe_create(other_tuples)
194     @has_optional_single = other_tuples.any? { |tuple| tuple.size_range.min == 1 }
195   end
196 
197   guard = RecursionGuard.new
198   accept(NoopTypeAcceptor::INSTANCE, guard)
199   @self_recursion = guard.recursive_this?(self)
200 end
create(scope, value) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
111 def create(scope, value)
112   self.class.create(scope, value, loader.load(:function, 'new'))
113 end
eql?(o) click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
64 def eql?(o)
65   super && @init_args == o.init_args
66 end
from_array(scope, value) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
107 def from_array(scope, value)
108   self.class.from_array(scope, value, loader.load(:function, 'new'))
109 end
hash() click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
68 def hash
69   super ^ @init_args.hash
70 end
instance?(o, guard = nil) click to toggle source
   # File lib/puppet/pops/types/p_init_type.rb
34 def instance?(o, guard = nil)
35   really_instance?(o, guard) == 1
36 end
new_function() click to toggle source
Calls superclass method
    # File lib/puppet/pops/types/p_init_type.rb
 72 def new_function
 73   return super if type.nil?
 74   assert_initialized
 75 
 76   target_type = type
 77   single_type = @single_type
 78   if @init_args.empty?
 79     @new_function ||= Puppet::Functions.create_function(:new_Init, Puppet::Functions::InternalFunction) do
 80       @target_type = target_type
 81       @single_type = single_type
 82 
 83       dispatch :from_array do
 84         scope_param
 85         param 'Array', :value
 86       end
 87 
 88       dispatch :create do
 89         scope_param
 90         param 'Any', :value
 91       end
 92 
 93       def self.create(scope, value, func)
 94         func.call(scope, @target_type, value)
 95       end
 96 
 97       def self.from_array(scope, value, func)
 98         # If there is a single argument that matches the array, then that gets priority over
 99         # expanding the array into all arguments
100         if @single_type.instance?(value) || (@other_type && !@other_type.instance?(value) && @has_optional_single && @other_type.instance?([value]))
101           func.call(scope, @target_type, value)
102         else
103           func.call(scope, @target_type, *value)
104         end
105       end
106 
107       def from_array(scope, value)
108         self.class.from_array(scope, value, loader.load(:function, 'new'))
109       end
110 
111       def create(scope, value)
112         self.class.create(scope, value, loader.load(:function, 'new'))
113       end
114     end
115   else
116     init_args = @init_args
117     @new_function ||= Puppet::Functions.create_function(:new_Init, Puppet::Functions::InternalFunction) do
118       @target_type = target_type
119       @init_args = init_args
120 
121       dispatch :create do
122         scope_param
123         param 'Any', :value
124       end
125 
126       def self.create(scope, value, func)
127         func.call(scope, @target_type, value, *@init_args)
128       end
129 
130       def create(scope, value)
131         self.class.create(scope, value, loader.load(:function, 'new'))
132       end
133     end
134   end
135 end
really_instance?(o, guard = nil) click to toggle source

@api private

   # File lib/puppet/pops/types/p_init_type.rb
39 def really_instance?(o, guard = nil)
40   if @type.nil?
41     TypeFactory.rich_data.really_instance?(o)
42   else
43     assert_initialized
44     guarded_recursion(guard, 0) do |g|
45       v = @type.really_instance?(o, g)
46       if v < 1
47         if @single_type
48           s = @single_type.really_instance?(o, g)
49           v = s if s > v
50         end
51       end
52       if v < 1
53         if @other_type
54           s = @other_type.really_instance?(o, g)
55           s = @other_type.really_instance?([o], g) if s < 0 && @has_optional_single
56           v = s if s > v
57         end
58       end
59       v
60     end
61   end
62 end

Protected Instance Methods

_assignable?(o, guard) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
212 def _assignable?(o, guard)
213   guarded_recursion(guard, false) do |g|
214     assert_initialized
215     if o.is_a?(PInitType)
216       @type.nil? || @type.assignable?(o.type, g)
217     elsif @type.nil?
218       TypeFactory.rich_data.assignable?(o, g)
219     else
220       @type.assignable?(o, g) ||
221         @single_type && @single_type.assignable?(o, g) ||
222         @other_type && (@other_type.assignable?(o, g) || @has_optional_single && @other_type.assignable?(PTupleType.new([o])))
223     end
224   end
225 end

Private Instance Methods

guarded_recursion(guard, dflt) { |guard| ... } click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
229 def guarded_recursion(guard, dflt)
230   if @self_recursion
231     guard ||= RecursionGuard.new
232     guard.with_this(self) { |state| (state & RecursionGuard::SELF_RECURSION_IN_THIS) == 0 ? yield(guard) : dflt }
233   else
234     yield(guard)
235   end
236 end