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
92 def self.create(scope, value, func)
93   func.call(scope, @target_type, value)
94 end
from_array(scope, value, func) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
 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
new(type, init_args) click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
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
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/p_init_type.rb
 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

Public Instance Methods

accept(visitor, guard) click to toggle source
Calls superclass method
    # File lib/puppet/pops/types/p_init_type.rb
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
assert_initialized() click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
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.signatures.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
create(scope, value) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
110 def create(scope, value)
111   self.class.create(scope, value, loader.load(:function, 'new'))
112 end
eql?(o) click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
63 def eql?(o)
64   super && @init_args == o.init_args
65 end
from_array(scope, value) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
106 def from_array(scope, value)
107   self.class.from_array(scope, value, loader.load(:function, 'new'))
108 end
hash() click to toggle source
Calls superclass method
   # File lib/puppet/pops/types/p_init_type.rb
67 def hash
68   super ^ @init_args.hash
69 end
instance?(o, guard = nil) click to toggle source
   # File lib/puppet/pops/types/p_init_type.rb
33 def instance?(o, guard = nil)
34   really_instance?(o, guard) == 1
35 end
new_function() click to toggle source
Calls superclass method
    # File lib/puppet/pops/types/p_init_type.rb
 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
really_instance?(o, guard = nil) click to toggle source

@api private

   # File lib/puppet/pops/types/p_init_type.rb
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

Protected Instance Methods

_assignable?(o, guard) click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
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

Private Instance Methods

guarded_recursion(guard, dflt) { |guard| ... } click to toggle source
    # File lib/puppet/pops/types/p_init_type.rb
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