Class: Puppet::Pops::Types::TypeCalculator

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/types/type_calculator.rb

Overview

Note:

In general, new instances of the wanted type should be created as they are assigned to models using containment, and a contained object can only be in one container at a time. Also, the type system may include more details in each type instance, such as if it may be nil, be empty, contain a certain count etc. Or put differently, the puppet types are not singletons.

The TypeCalculator can answer questions about puppet types.

The Puppet type system is primarily based on sub-classing. When asking the type calculator to infer types from Ruby in general, it may not provide the wanted answer; it does not for instance take module inclusions and extensions into account. In general the type system should be unsurprising for anyone being exposed to the notion of type. The type Data may require a bit more explanation; this is an abstract type that includes all literal types, as well as Array with an element type compatible with Data, and Hash with key compatible with Literal and elements compatible with Data. Expressed differently; Data is what you typically express using JSON (with the exception that the Puppet type system also includes Pattern (regular expression) as a literal.

Inference


The ‘infer(o)` method infers a Puppet type for literal Ruby objects, and for Arrays and Hashes.

Assignability


The ‘assignable?(t1, t2)` method answers if t2 conforms to t1. The type t2 may be an instance, in which case its type is inferred, or a type.

Instance?


The ‘instance?(t, o)` method answers if the given object (instance) is an instance that is assignable to the given type.

String


Creates a string representation of a type.

Creation of Type instances


Instance of the classes in the type model are used to denote a specific type. It is most convenient to use the TypeFactory when creating instances.

Equality and Hash


Type instances are equal in terms of Ruby eql? and ‘==` if they describe the same type, but they are not equal? if they are not the same type instance. Two types that describe the same type have identical hash - this makes them usable as hash keys.

Types and Subclasses


In general, the type calculator should be used to answer questions if a type is a subtype of another (using #assignable?, or #instance? if the question is if a given object is an instance of a given type (or is a subtype thereof). Many of the types also have a Ruby subtype relationship; e.g. PHashType and PArrayType are both subtypes of PCollectionType, and PIntegerType, PFloatType, PStringType,… are subtypes of PLiteralType. Even if it is possible to answer certain questions about type by looking at the Ruby class of the types this is considered an implementation detail, and such checks should in general be performed by the type_calculator which implements the type system semantics.

The PRubyType


The PRubyType corresponds to a Ruby Class, except for the puppet types that are specialized (i.e. PRubyType should not be used for Integer, String, etc. since there are specialized types for those). When the type calculator deals with PRubyTypes and checks for assignability, it determines the “common ancestor class” of two classes. This check is made based on the superclasses of the two classes being compared. In order to perform this, the classes must be present (i.e. they are resolved from the string form in the PRubyType to a loaded, instantiated Ruby Class). In general this is not a problem, since the question to produce the common super type for two objects means that the classes must be present or there would have been no instances present in the first place. If however the classes are not present, the type calculator will fall back and state that the two types at least have Object in common.

Constant Summary collapse

Types =
Puppet::Pops::Types

Instance Method Summary collapse

Constructor Details

#initializeTypeCalculator

Returns a new instance of TypeCalculator.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/puppet/pops/types/type_calculator.rb', line 75

def initialize
  @@assignable_visitor ||= Puppet::Pops::Visitor.new(nil,"assignable",1,1)
  @@infer_visitor ||= Puppet::Pops::Visitor.new(nil,"infer",0,0)
  @@string_visitor ||= Puppet::Pops::Visitor.new(nil,"string",0,0)

  da = Types::PArrayType.new()
  da.element_type = Types::PDataType.new()
  @data_array = da

  h = Types::PHashType.new()
  h.element_type = Types::PDataType.new()
  h.key_type = Types::PLiteralType.new()
  @data_hash = h

  @data_t = Types::PDataType.new()
  @literal_t = Types::PLiteralType.new()
  @numeric_t = Types::PNumericType.new()
  @t = Types::PObjectType.new()
end

Instance Method Details

#assignable?(t, t2) ⇒ Boolean

Answers ‘can an instance of type t2 be assigned to a variable of type t’

Returns:

  • (Boolean)


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/puppet/pops/types/type_calculator.rb', line 128

def assignable?(t, t2)
   # nil is assignable to anything
   if is_pnil?(t2)
     return true
   end

   if t.is_a?(Class)
     t = type(t)
   end

   if t2.is_a?(Class)
     t2 = type(t2)
   end

   @@assignable_visitor.visit_this(self, t, t2)
end

#assignable_Object(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

False in general type calculator



412
413
414
# File 'lib/puppet/pops/types/type_calculator.rb', line 412

def assignable_Object(t, t2)
  false
end

#assignable_PArrayType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Array is assignable if t2 is an Array and t2’s element type is assignable



463
464
465
466
# File 'lib/puppet/pops/types/type_calculator.rb', line 463

def assignable_PArrayType(t, t2)
  return false unless t2.is_a?(Types::PArrayType)
  assignable?(t.element_type, t2.element_type)
end

#assignable_PBooleanType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



447
448
449
# File 'lib/puppet/pops/types/type_calculator.rb', line 447

def assignable_PBooleanType(t, t2)
  t2.is_a?(Types::PBooleanType)
end

#assignable_PCollectionType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



457
458
459
# File 'lib/puppet/pops/types/type_calculator.rb', line 457

def assignable_PCollectionType(t, t2)
  t2.is_a?(Types::PCollectionType)
end

#assignable_PDataType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Data is assignable by other Data and by Array and Hash[Literal, Data]



477
478
479
# File 'lib/puppet/pops/types/type_calculator.rb', line 477

def assignable_PDataType(t, t2)
  t2.is_a?(Types::PDataType) || assignable?(@data_array, t2) || assignable?(@data_hash, t2)
end

#assignable_PFloatType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



442
443
444
# File 'lib/puppet/pops/types/type_calculator.rb', line 442

def assignable_PFloatType(t, t2)
  t2.is_a?(Types::PFloatType)
end

#assignable_PHashType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Hash is assignable if t2 is a Hash and t2’s key and element types are assignable



470
471
472
473
# File 'lib/puppet/pops/types/type_calculator.rb', line 470

def assignable_PHashType(t, t2)
  return false unless t2.is_a?(Types::PHashType)
  assignable?(t.key_type, t2.key_type) && assignable?(t.element_type, t2.element_type)
end

#assignable_PIntegerType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



432
433
434
# File 'lib/puppet/pops/types/type_calculator.rb', line 432

def assignable_PIntegerType(t, t2)
  t2.is_a?(Types::PIntegerType)
end

#assignable_PLiteralType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



422
423
424
# File 'lib/puppet/pops/types/type_calculator.rb', line 422

def assignable_PLiteralType(t, t2)
  t2.is_a?(Types::PLiteralType)
end

#assignable_PNumericType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



427
428
429
# File 'lib/puppet/pops/types/type_calculator.rb', line 427

def assignable_PNumericType(t, t2)
  t2.is_a?(Types::PNumericType)
end

#assignable_PObjectType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



417
418
419
# File 'lib/puppet/pops/types/type_calculator.rb', line 417

def assignable_PObjectType(t, t2)
  t2.is_a?(Types::PObjectType)
end

#assignable_PPatternType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



452
453
454
# File 'lib/puppet/pops/types/type_calculator.rb', line 452

def assignable_PPatternType(t, t2)
  t2.is_a?(Types::PPatternType)
end

#assignable_PRubyType(t1, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Assignable if t2’s ruby class is same or subclass of t1’s ruby class



483
484
485
486
487
488
489
# File 'lib/puppet/pops/types/type_calculator.rb', line 483

def assignable_PRubyType(t1, t2)
  return false unless t2.is_a?(Types::PRubyType)
  c1 = class_from_string(t1.ruby_class)
  c2 = class_from_string(t2.ruby_class)
  return false unless c1.is_a?(Class) && c2.is_a?(Class)
  !!(c2 <= c1)
end

#assignable_PStringType(t, t2) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



437
438
439
# File 'lib/puppet/pops/types/type_calculator.rb', line 437

def assignable_PStringType(t, t2)
  t2.is_a?(Types::PStringType)
end

#common_type(t1, t2) ⇒ Object

Answers, ‘What is the common type of t1 and t2?’

Raises:

  • (ArgumentError)


217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/puppet/pops/types/type_calculator.rb', line 217

def common_type(t1, t2)
  raise ArgumentError, 'two types expected' unless (is_ptype?(t1) || is_pnil?(t1)) && (is_ptype?(t2) || is_pnil?(t2))

  # if either is nil, the common type is the other
  if is_pnil?(t1)
    return t2
  elsif is_pnil?(t2)
    return t1
  end

  # Simple case, one is assignable to the other
  if assignable?(t1, t2)
    return t1
  elsif assignable?(t2, t1)
    return t2
  end

  # when both are arrays, return an array with common element type
  if t1.is_a?(Types::PArrayType) && t2.is_a?(Types::PArrayType)
    type = Types::PArrayType.new()
    type.element_type = common_type(t1.element_type, t2.element_type)
    return type
  end

  # when both are hashes, return a hash with common key- and element type
  if t1.is_a?(Types::PHashType) && t2.is_a?(Types::PHashType)
    type = Types::PHashType.new()
    type.key_type = common_type(t1.key_type, t2.key_type)
    type.element_type = common_type(t1.element_type, t2.element_type)
    return type
  end

  # Common abstract types, from most specific to most general
  if common_numeric?(t1, t2)
    return Types::PNumericType.new()
  end

  if common_literal?(t1, t2)
    return Types::PLiteralType.new()
  end

  if common_data?(t1,t2)
    return Types::PDataType.new()
  end

  if t1.is_a?(Types::PRubyType) && t2.is_a?(Types::PRubyType)
    if t1.ruby_class == t2.ruby_class
      return t1
    end
    # finding the common super class requires that names are resolved to class
    c1 = Types::ClassLoader.provide_from_type(t1)
    c2 = Types::ClassLoader.provide_from_type(t2)
    if c1 && c2
      c2_superclasses = superclasses(c2)
      superclasses(c1).each do|c1_super|
        c2_superclasses.each do |c2_super|
          if c1_super == c2_super
            result = Types::PRubyType.new()
            result.ruby_class = c1_super.name
            return result
          end
        end
      end
    end
  end
  # If both are RubyObjects

  if common_pobject?(t1, t2)
    return Types::PObjectType.new()
  end
end

#dataObject

Convenience method to get a data type for comparisons



98
99
100
# File 'lib/puppet/pops/types/type_calculator.rb', line 98

def data
  @data_t
end

#infer(o) ⇒ Object

Answers ‘what is the Puppet Type of o’



189
190
191
# File 'lib/puppet/pops/types/type_calculator.rb', line 189

def infer(o)
  @@infer_visitor.visit_this(self, o)
end

#infer_and_reduce_type(enumerable) ⇒ Object

Reduce an enumerable of objects to a single common type



316
317
318
# File 'lib/puppet/pops/types/type_calculator.rb', line 316

def infer_and_reduce_type(enumerable)
  reduce_type(enumerable.collect() {|o| infer(o) })
end

#infer_Array(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



385
386
387
388
389
390
391
392
393
# File 'lib/puppet/pops/types/type_calculator.rb', line 385

def infer_Array(o)
  type = Types::PArrayType.new()
  type.element_type = if o.empty?
    Types::PNilType.new()
  else
    infer_and_reduce_type(o)
  end
  type
end

#infer_Class(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The type of all classes is PType



323
324
325
# File 'lib/puppet/pops/types/type_calculator.rb', line 323

def infer_Class(o)
  Types::PType.new()
end

#infer_FalseClass(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



380
381
382
# File 'lib/puppet/pops/types/type_calculator.rb', line 380

def infer_FalseClass(o)
  Types::PBooleanType.new()
end

#infer_Float(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



355
356
357
# File 'lib/puppet/pops/types/type_calculator.rb', line 355

def infer_Float(o)
  Types::PFloatType.new()
end

#infer_Hash(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/puppet/pops/types/type_calculator.rb', line 396

def infer_Hash(o)
  type = Types::PHashType.new()
  if o.empty?
    ktype = Types::PNilType.new()
    etype = Types::PNilType.new()
  else
    ktype = infer_and_reduce_type(o.keys())
    etype = infer_and_reduce_type(o.values())
  end
  type.key_type = ktype
  type.element_type = etype
  type
end

#infer_Integer(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



360
361
362
# File 'lib/puppet/pops/types/type_calculator.rb', line 360

def infer_Integer(o)
  Types::PIntegerType.new()
end

#infer_NilClass(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



370
371
372
# File 'lib/puppet/pops/types/type_calculator.rb', line 370

def infer_NilClass(o)
  Types::PNilType.new()
end

#infer_Object(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



328
329
330
331
332
# File 'lib/puppet/pops/types/type_calculator.rb', line 328

def infer_Object(o)
  type = Types::PRubyType.new()
  type.ruby_class = o.class.name
  type
end

#infer_PObjectType(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The type of all types is PType



337
338
339
# File 'lib/puppet/pops/types/type_calculator.rb', line 337

def infer_PObjectType(o)
  Types::PType.new()
end

#infer_PType(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The type of all types is PType This is the metatype short circuit.



345
346
347
# File 'lib/puppet/pops/types/type_calculator.rb', line 345

def infer_PType(o)
  Types::PType.new()
end

#infer_Regexp(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



365
366
367
# File 'lib/puppet/pops/types/type_calculator.rb', line 365

def infer_Regexp(o)
  Types::PPatternType.new()
end

#infer_String(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



350
351
352
# File 'lib/puppet/pops/types/type_calculator.rb', line 350

def infer_String(o)
  Types::PStringType.new()
end

#infer_TrueClass(o) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



375
376
377
# File 'lib/puppet/pops/types/type_calculator.rb', line 375

def infer_TrueClass(o)
  Types::PBooleanType.new()
end

#injectable_class(klazz) ⇒ Class?

Answers the question ‘is it possible to inject an instance of the given class’ A class is injectable if it has a special *assisted inject* class method called inject taking an injector and a scope as argument, or if it has a zero args initialize method.

Parameters:

  • klazz (Class, PRubyType)

    the class/type to check if it is injectable

Returns:

  • (Class, nil)

    the injectable Class, or nil if not injectable



110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/puppet/pops/types/type_calculator.rb', line 110

def injectable_class(klazz)
  # Handle case when we get a PType instead of a class
  if klazz.is_a?(Types::PRubyType)
    klazz = Puppet::Pops::Types::ClassLoader.provide(klazz)
  end

  # data types can not be injected (check again, it is not safe to assume that given RubyType klazz arg was ok)
  return false unless type(klazz).is_a?(Types::PRubyType)
  if (klazz.respond_to?(:inject) && klazz.method(:inject).arity() == -4) || klazz.instance_method(:initialize).arity() == 0
    klazz
  else
    nil
  end
end

#instance?(t, o) ⇒ Boolean

Answers ‘is o an instance of type t’

Returns:

  • (Boolean)


196
197
198
# File 'lib/puppet/pops/types/type_calculator.rb', line 196

def instance?(t, o)
  assignable?(t, infer(o))
end

#is_pnil?(t) ⇒ Boolean

Answers if t represents the puppet type PNilType

Returns:

  • (Boolean)


210
211
212
# File 'lib/puppet/pops/types/type_calculator.rb', line 210

def is_pnil?(t)
  return t.nil? || t.is_a?(Types::PNilType)
end

#is_ptype?(t) ⇒ Boolean

Answers if t is a puppet type

Returns:

  • (Boolean)


203
204
205
# File 'lib/puppet/pops/types/type_calculator.rb', line 203

def is_ptype?(t)
  return t.is_a?(Types::PObjectType)
end

#reduce_type(enumerable) ⇒ Object

Reduces an enumerable of types to a single common type.



309
310
311
# File 'lib/puppet/pops/types/type_calculator.rb', line 309

def reduce_type(enumerable)
  enumerable.reduce(nil) {|memo, t| common_type(memo, t) }
end

#string(t) ⇒ Object

Produces a string representing the type



301
302
303
# File 'lib/puppet/pops/types/type_calculator.rb', line 301

def string(t)
  @@string_visitor.visit_this(self, t)
end

#string_PArrayType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



525
526
527
# File 'lib/puppet/pops/types/type_calculator.rb', line 525

def string_PArrayType(t)
  "Array[#{string(t.element_type)}]"
end

#string_PBooleanType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



498
# File 'lib/puppet/pops/types/type_calculator.rb', line 498

def string_PBooleanType(t) ; "Boolean" ; end

#string_PDataType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



504
# File 'lib/puppet/pops/types/type_calculator.rb', line 504

def string_PDataType(t)    ; "Data"    ; end

#string_PFloatType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



513
# File 'lib/puppet/pops/types/type_calculator.rb', line 513

def string_PFloatType(t)   ; "Float"   ; end

#string_PHashType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



530
531
532
# File 'lib/puppet/pops/types/type_calculator.rb', line 530

def string_PHashType(t)
  "Hash[#{string(t.key_type)}, #{string(t.element_type)}]"
end

#string_PIntegerType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



510
# File 'lib/puppet/pops/types/type_calculator.rb', line 510

def string_PIntegerType(t) ; "Integer" ; end

#string_PLiteralType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



501
# File 'lib/puppet/pops/types/type_calculator.rb', line 501

def string_PLiteralType(t) ; "Literal" ; end

#string_PNumericType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



507
# File 'lib/puppet/pops/types/type_calculator.rb', line 507

def string_PNumericType(t) ; "Numeric" ; end

#string_PObjectType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



495
# File 'lib/puppet/pops/types/type_calculator.rb', line 495

def string_PObjectType(t)  ; "Object"  ; end

#string_PPatternType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



516
# File 'lib/puppet/pops/types/type_calculator.rb', line 516

def string_PPatternType(t) ; "Pattern" ; end

#string_PRubyType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



522
# File 'lib/puppet/pops/types/type_calculator.rb', line 522

def string_PRubyType(t)   ; "Ruby[#{t.ruby_class}]"  ; end

#string_PStringType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



519
# File 'lib/puppet/pops/types/type_calculator.rb', line 519

def string_PStringType(t)  ; "String"  ; end

#string_PType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



492
# File 'lib/puppet/pops/types/type_calculator.rb', line 492

def string_PType(t)        ; "Type"    ; end

#superclasses(c) ⇒ Object

Produces the superclasses of the given class, including the class



290
291
292
293
294
295
296
297
# File 'lib/puppet/pops/types/type_calculator.rb', line 290

def superclasses(c)
  result = [c]
  while s = c.superclass
    result << s
    c = s
  end
  result
end

#type(c) ⇒ Object

Raises:

  • (ArgumentError)


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/puppet/pops/types/type_calculator.rb', line 149

def type(c)
  raise ArgumentError, "Argument must be a Class" unless c.is_a? Class

  # Can't use a visitor here since we don't have an instance of the class
  case
  when c <= Integer
    type = Types::PIntegerType.new()
  when c == Float
    type = Types::PFloatType.new()
  when c == Numeric
    type = Types::PNumericType.new()
  when c == String
    type = Types::PStringType.new()
  when c == Regexp
    type = Types::PPatternType.new()
  when c == NilClass
    type = Types::PNilType.new()
  when c == FalseClass, c == TrueClass
    type = Types::PBooleanType.new()
  when c == Class
    type = Types::PType.new()
  when c == Array
    # Assume array of data values
    type = Types::PArrayType.new()
    type.element_type = Types::PDataType.new()
  when c == Hash
    # Assume hash with literal keys and data values
    type = Types::PHashType.new()
    type.key_type = Types::PLiteralType.new()
    type.element_type = Types::PDataType.new()
  else
    type = Types::PRubyType.new()
    type.ruby_class = c.name
  end
  type
end