Class: CrystalRuby::Types::Type

Inherits:
Object
  • Object
show all
Extended by:
CrystalRuby::Typemaps
Includes:
Allocator
Defined in:
lib/crystalruby/types/type.rb

Direct Known Subclasses

FixedWidth, Primitive

Constant Summary collapse

ARC_MUTEX =

TODO: Replace with pthread primitives and share with Crystal

CrystalRuby::ArcMutex.new

Constants included from CrystalRuby::Typemaps

CrystalRuby::Typemaps::CRYSTAL_TYPE_MAP, CrystalRuby::Typemaps::C_TYPE_CONVERSIONS, CrystalRuby::Typemaps::C_TYPE_MAP, CrystalRuby::Typemaps::ERROR_VALUE, CrystalRuby::Typemaps::FFI_TYPE_MAP

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CrystalRuby::Typemaps

build_type_map, convert_crystal_to_lib_type, convert_lib_to_crystal_type, crystal_type, error_value, ffi_type, lib_type

Methods included from Allocator

included

Constructor Details

#initialize(_rbval) ⇒ Type

Returns a new instance of Type.



52
53
54
55
# File 'lib/crystalruby/types/type.rb', line 52

def initialize(_rbval)
  @class = self.class
  raise error if error
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/crystalruby/types/type.rb', line 199

def method_missing(method, *args, &block)
  v = begin
    native
  rescue StandardError
    super
  end
  if v.respond_to?(method)
    hash_before = v.hash
    result = v.send(method, *args, &block)
    if v.hash != hash_before
      self.value = v
      v.equal?(result) ? self : result
    else
      result
    end
  else
    super
  end
end

Class Attribute Details

.convert_ifObject

Returns the value of attribute convert_if.



42
43
44
# File 'lib/crystalruby/types/type.rb', line 42

def convert_if
  @convert_if
end

.ffi_typeObject

Returns the value of attribute ffi_type.



42
43
44
# File 'lib/crystalruby/types/type.rb', line 42

def ffi_type
  @ffi_type
end

.inner_typesObject

Returns the value of attribute inner_types.



42
43
44
# File 'lib/crystalruby/types/type.rb', line 42

def inner_types
  @inner_types
end

.memsizeObject

Returns the value of attribute memsize.



42
43
44
# File 'lib/crystalruby/types/type.rb', line 42

def memsize
  @memsize
end

.typenameObject

Returns the value of attribute typename.



42
43
44
# File 'lib/crystalruby/types/type.rb', line 42

def typename
  @typename
end

Instance Attribute Details

#memoryObject

Returns the value of attribute memory.



50
51
52
# File 'lib/crystalruby/types/type.rb', line 50

def memory
  @memory
end

#value(native: false) ⇒ Object

Returns the value of attribute value.



50
51
52
# File 'lib/crystalruby/types/type.rb', line 50

def value
  @value
end

Class Method Details

.[](*value) ⇒ Object



87
88
89
90
# File 'lib/crystalruby/types/type.rb', line 87

def self.[](*value)
  is_list_type = ancestors.any? { |a| a < CrystalRuby::Types::Array || a < CrystalRuby::Types::Tuple }
  new(is_list_type ? value : value.first)
end

.anonymous?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/crystalruby/types/type.rb', line 92

def self.anonymous?
  name.nil? || name.start_with?("CrystalRuby::Types::")
end

.base_crystal_class_nameObject



105
106
107
# File 'lib/crystalruby/types/type.rb', line 105

def self.base_crystal_class_name
  crystal_class_name.split("::").last
end

.bind_local_vars!(variable_names, binding) ⇒ Object



219
220
221
222
223
224
225
226
227
228
# File 'lib/crystalruby/types/type.rb', line 219

def self.bind_local_vars!(variable_names, binding)
  variable_names.each do |name|
    define_singleton_method(name) do
      binding.local_variable_get("#{name}")
    end
    define_method(name) do
      binding.local_variable_get("#{name}")
    end
  end
end

.cast!(value) ⇒ Object



161
162
163
# File 'lib/crystalruby/types/type.rb', line 161

def self.cast!(value)
  value.is_a?(Type) ? value.value : value
end

.crystal_class_nameObject



96
97
98
99
100
101
102
103
# File 'lib/crystalruby/types/type.rb', line 96

def self.crystal_class_name
  name || native_type_expr.split(",").join("_and_")
                          .split("|").join("_or_")
                          .split("(").join("_of_")
                          .gsub(/[^a-zA-Z0-9_]/, "")
                          .split("_")
                          .map(&:capitalize).join << "_#{type_digest[0..6]}"
end

.crystal_typeObject



236
237
238
# File 'lib/crystalruby/types/type.rb', line 236

def self.crystal_type
  lib_type(ffi_type)
end

.crystal_type_to_pointer_type_conversion(expr) ⇒ Object



129
130
131
# File 'lib/crystalruby/types/type.rb', line 129

def self.crystal_type_to_pointer_type_conversion(expr)
  anonymous? ? "#{crystal_class_name}.new(#{expr}).return_value" : "#{expr}.return_value"
end

.each_child_address(pointer) ⇒ Object



230
# File 'lib/crystalruby/types/type.rb', line 230

def self.each_child_address(pointer); end

.finalize(_memory) ⇒ Object



57
58
59
# File 'lib/crystalruby/types/type.rb', line 57

def self.finalize(_memory)
  ->(_) {}
end

.fixed_width?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/crystalruby/types/type.rb', line 157

def self.fixed_width?
  false
end

.from_ffi_array_repr(value) ⇒ Object



181
182
183
# File 'lib/crystalruby/types/type.rb', line 181

def self.from_ffi_array_repr(value)
  anonymous? ? new(value).value : new(value)
end

.inner_typeObject



254
255
256
# File 'lib/crystalruby/types/type.rb', line 254

def self.inner_type
  inner_types.first
end

.inspectObject



270
271
272
# File 'lib/crystalruby/types/type.rb', line 270

def self.inspect
  type_expr
end

.inspect_nameObject



61
62
63
# File 'lib/crystalruby/types/type.rb', line 61

def self.inspect_name
  (name || "#{typename}").to_s.gsub(/^CrystalRuby::Types::[^::]+::/, "")
end

.native_type_exprObject



73
74
75
76
77
78
79
80
81
# File 'lib/crystalruby/types/type.rb', line 73

def self.native_type_expr
  if !inner_types
    "::#{typename}"
  elsif !inner_keys
    "::#{typename}(#{inner_types.map(&:native_type_expr).join(", ")})"
  else
    "::#{typename}(#{inner_keys.zip(inner_types).map { |k, v| "#{k}: #{v.native_type_expr}" }.join(", ")})"
  end
end

.nested_typesObject



121
122
123
# File 'lib/crystalruby/types/type.rb', line 121

def self.nested_types
  [self, *(inner_types || []).map(&:nested_types)].flatten.uniq
end

.numeric?Boolean

Returns:

  • (Boolean)


145
146
147
# File 'lib/crystalruby/types/type.rb', line 145

def self.numeric?
  false
end

.pointer_to_crystal_type_conversion(expr) ⇒ Object



125
126
127
# File 'lib/crystalruby/types/type.rb', line 125

def self.pointer_to_crystal_type_conversion(expr)
  anonymous? ? "#{crystal_class_name}.new(#{expr}).native" : "#{crystal_class_name}.new(#{expr})"
end

.primitive?Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/crystalruby/types/type.rb', line 149

def self.primitive?
  false
end

.template_nameObject



133
134
135
# File 'lib/crystalruby/types/type.rb', line 133

def self.template_name
  typename || superclass.template_name
end

.type_defnObject



137
138
139
140
141
142
143
# File 'lib/crystalruby/types/type.rb', line 137

def self.type_defn
  unless Template.const_defined?(template_name) && Template.const_get(template_name).is_a?(Template::Renderer)
    raise "Template not found for #{template_name}"
  end

  Template.const_get(template_name).render(binding)
end

.type_digestObject



117
118
119
# File 'lib/crystalruby/types/type.rb', line 117

def self.type_digest
  Digest::MD5.hexdigest(native_type_expr.to_s)
end

.type_exprObject



258
259
260
261
262
263
264
265
266
267
268
# File 'lib/crystalruby/types/type.rb', line 258

def self.type_expr
  if !inner_types
    inspect_name
  elsif !anonymous?
    name
  elsif inner_keys
    "#{inspect_name}(#{inner_keys.zip(inner_types).map { |k, v| "#{k}: #{v.inspect}" }.join(", ")})"
  else
    "#{inspect_name}(#{inner_types.map(&:inspect).join(", ")})"
  end
end

.union_typesObject



65
66
67
# File 'lib/crystalruby/types/type.rb', line 65

def self.union_types
  [self]
end

.valid?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/crystalruby/types/type.rb', line 69

def self.valid?
  true
end

.valid_cast?(raw) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/crystalruby/types/type.rb', line 83

def self.valid_cast?(raw)
  raw.is_a?(self) || convert_if.any? { |type| raw.is_a?(type) }
end

.validate!(type) ⇒ Object



246
247
248
249
250
251
252
# File 'lib/crystalruby/types/type.rb', line 246

def self.validate!(type)
  unless type.is_a?(Class) && type.ancestors.include?(Types::Type)
    raise "Result #{type} is not a valid CrystalRuby type"
  end

  raise "Invalid type: #{type.error}" unless type.valid?
end

.variable_width?Boolean

Returns:

  • (Boolean)


153
154
155
# File 'lib/crystalruby/types/type.rb', line 153

def self.variable_width?
  false
end

.|(other) ⇒ Object



240
241
242
243
244
# File 'lib/crystalruby/types/type.rb', line 240

def self.|(other)
  raise "Cannot union non-crystal type #{other}" unless other.is_a?(Class) && other.ancestors.include?(Type)

  CrystalRuby::Types::TaggedUnion(*union_types, *other.union_types)
end

Instance Method Details

#==(other) ⇒ Object



165
166
167
# File 'lib/crystalruby/types/type.rb', line 165

def ==(other)
  value(native: true) == (other.is_a?(Type) ? other.value(native: true) : other)
end

#coerce(other) ⇒ Object



173
174
175
# File 'lib/crystalruby/types/type.rb', line 173

def coerce(other)
  [other, value]
end

#deep_dupObject

Create a brand new copy of this object



190
191
192
# File 'lib/crystalruby/types/type.rb', line 190

def deep_dup
  self.class.new(native)
end

#dupObject

Create a new reference to this object.



195
196
197
# File 'lib/crystalruby/types/type.rb', line 195

def dup
  self.class.new(@memory)
end

#inner_valueObject



185
186
187
# File 'lib/crystalruby/types/type.rb', line 185

def inner_value
  @value
end

#inspectObject



177
178
179
# File 'lib/crystalruby/types/type.rb', line 177

def inspect
  value.inspect
end

#item_sizeObject



232
233
234
# File 'lib/crystalruby/types/type.rb', line 232

def item_size
  inner_types.map(&:memsize).sum
end

#nativeObject



113
114
115
# File 'lib/crystalruby/types/type.rb', line 113

def native
  value(native: true)
end

#nil?Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/crystalruby/types/type.rb', line 169

def nil?
  value.nil?
end