Class: CrystalRuby::Types::Type
Constant Summary
collapse
- ARC_MUTEX =
TODO: Replace with pthread primitives and share with Crystal
CrystalRuby::ArcMutex.new
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
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
gc_bytes_seen, gc_hint!, gc_hint_reset!, 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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
# File 'lib/crystalruby/types/type.rb', line 209
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_if ⇒ Object
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_type ⇒ Object
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_types ⇒ Object
Returns the value of attribute inner_types.
42
43
44
|
# File 'lib/crystalruby/types/type.rb', line 42
def inner_types
@inner_types
end
|
.memsize ⇒ Object
Returns the value of attribute memsize.
42
43
44
|
# File 'lib/crystalruby/types/type.rb', line 42
def memsize
@memsize
end
|
.typename ⇒ Object
Returns the value of attribute typename.
42
43
44
|
# File 'lib/crystalruby/types/type.rb', line 42
def typename
@typename
end
|
Instance Attribute Details
#ffi_primitive ⇒ Object
Returns the value of attribute ffi_primitive.
50
51
52
|
# File 'lib/crystalruby/types/type.rb', line 50
def ffi_primitive
@ffi_primitive
end
|
#memory ⇒ Object
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
97
98
99
100
|
# File 'lib/crystalruby/types/type.rb', line 97
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
102
103
104
|
# File 'lib/crystalruby/types/type.rb', line 102
def self.anonymous?
name.nil? || name.start_with?("CrystalRuby::Types::")
end
|
.base_crystal_class_name ⇒ Object
115
116
117
|
# File 'lib/crystalruby/types/type.rb', line 115
def self.base_crystal_class_name
crystal_class_name.split("::").last
end
|
.bind_local_vars!(variable_names, binding) ⇒ Object
229
230
231
232
233
234
235
236
237
238
|
# File 'lib/crystalruby/types/type.rb', line 229
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
171
172
173
|
# File 'lib/crystalruby/types/type.rb', line 171
def self.cast!(value)
value.is_a?(Type) ? value.value : value
end
|
.crystal_class_name ⇒ Object
106
107
108
109
110
111
112
113
|
# File 'lib/crystalruby/types/type.rb', line 106
def self.crystal_class_name
name || named_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_type ⇒ Object
257
258
259
|
# File 'lib/crystalruby/types/type.rb', line 257
def self.crystal_type
lib_type(ffi_type)
end
|
.crystal_type_to_pointer_type_conversion(expr) ⇒ Object
139
140
141
|
# File 'lib/crystalruby/types/type.rb', line 139
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
240
|
# File 'lib/crystalruby/types/type.rb', line 240
def self.each_child_address(pointer); end
|
.ffi_primitive_type ⇒ Object
For non-container ffi_primitive non-named types, just use the raw FFI type, as it’s much more efficient due to skipping Arc overhead.
253
254
255
|
# File 'lib/crystalruby/types/type.rb', line 253
def self.ffi_primitive_type
respond_to?(:ffi_primitive) && anonymous? ? ffi_primitive : nil
end
|
.finalize(_memory) ⇒ Object
57
58
59
|
# File 'lib/crystalruby/types/type.rb', line 57
def self.finalize(_memory)
->(_) {}
end
|
.fixed_width? ⇒ Boolean
167
168
169
|
# File 'lib/crystalruby/types/type.rb', line 167
def self.fixed_width?
false
end
|
.from_ffi_array_repr(value) ⇒ Object
191
192
193
|
# File 'lib/crystalruby/types/type.rb', line 191
def self.from_ffi_array_repr(value)
anonymous? ? new(value).value : new(value)
end
|
.inner_type ⇒ Object
275
276
277
|
# File 'lib/crystalruby/types/type.rb', line 275
def self.inner_type
inner_types.first
end
|
.inspect ⇒ Object
295
296
297
|
# File 'lib/crystalruby/types/type.rb', line 295
def self.inspect
type_expr
end
|
.inspect_name ⇒ Object
61
62
63
|
# File 'lib/crystalruby/types/type.rb', line 61
def self.inspect_name
(name || "#{typename}").to_s.gsub(/^CrystalRuby::Types::[^::]+::/, "")
end
|
.named_type_expr ⇒ Object
83
84
85
86
87
88
89
90
91
|
# File 'lib/crystalruby/types/type.rb', line 83
def self.named_type_expr
if !inner_types
"::#{name || typename}"
elsif !inner_keys
"::#{name || typename}(#{inner_types.map(&:named_type_expr).join(", ")})"
else
"::#{name || typename}(#{inner_keys.zip(inner_types).map { |k, v| "#{k}: #{v.named_type_expr}" }.join(", ")})"
end
end
|
.native_type_expr ⇒ Object
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_types ⇒ Object
131
132
133
|
# File 'lib/crystalruby/types/type.rb', line 131
def self.nested_types
[self, *(inner_types || []).map(&:nested_types)].flatten.uniq
end
|
.numeric? ⇒ Boolean
155
156
157
|
# File 'lib/crystalruby/types/type.rb', line 155
def self.numeric?
false
end
|
.pointer_to_crystal_type_conversion(expr) ⇒ Object
135
136
137
|
# File 'lib/crystalruby/types/type.rb', line 135
def self.pointer_to_crystal_type_conversion(expr)
anonymous? ? "#{crystal_class_name}.new(#{expr}).native_decr" : "#{crystal_class_name}.new_decr(#{expr})"
end
|
.primitive? ⇒ Boolean
159
160
161
|
# File 'lib/crystalruby/types/type.rb', line 159
def self.primitive?
false
end
|
.subclass?(type) ⇒ Boolean
279
280
281
|
# File 'lib/crystalruby/types/type.rb', line 279
def self.subclass?(type)
type.is_a?(Class) && type < Types::Type
end
|
.template_name ⇒ Object
143
144
145
|
# File 'lib/crystalruby/types/type.rb', line 143
def self.template_name
typename || superclass.template_name
end
|
.type_defn ⇒ Object
147
148
149
150
151
152
153
|
# File 'lib/crystalruby/types/type.rb', line 147
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_digest ⇒ Object
127
128
129
|
# File 'lib/crystalruby/types/type.rb', line 127
def self.type_digest
Digest::MD5.hexdigest(native_type_expr.to_s)
end
|
.type_expr ⇒ Object
283
284
285
286
287
288
289
290
291
292
293
|
# File 'lib/crystalruby/types/type.rb', line 283
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_types ⇒ Object
65
66
67
|
# File 'lib/crystalruby/types/type.rb', line 65
def self.union_types
[self]
end
|
.valid? ⇒ Boolean
69
70
71
|
# File 'lib/crystalruby/types/type.rb', line 69
def self.valid?
true
end
|
.valid_cast?(raw) ⇒ Boolean
93
94
95
|
# File 'lib/crystalruby/types/type.rb', line 93
def self.valid_cast?(raw)
raw.is_a?(self) || convert_if.any? { |type| raw.is_a?(type) }
end
|
.validate!(type) ⇒ Object
267
268
269
270
271
272
273
|
# File 'lib/crystalruby/types/type.rb', line 267
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
163
164
165
|
# File 'lib/crystalruby/types/type.rb', line 163
def self.variable_width?
false
end
|
.|(other) ⇒ Object
261
262
263
264
265
|
# File 'lib/crystalruby/types/type.rb', line 261
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
175
176
177
|
# File 'lib/crystalruby/types/type.rb', line 175
def ==(other)
value(native: true) == (other.is_a?(Type) ? other.value(native: true) : other)
end
|
#coerce(other) ⇒ Object
183
184
185
|
# File 'lib/crystalruby/types/type.rb', line 183
def coerce(other)
[other, value]
end
|
#deep_dup ⇒ Object
Create a brand new copy of this object
200
201
202
|
# File 'lib/crystalruby/types/type.rb', line 200
def deep_dup
self.class.new(native)
end
|
#dup ⇒ Object
Create a new reference to this object.
205
206
207
|
# File 'lib/crystalruby/types/type.rb', line 205
def dup
self.class.new(@memory)
end
|
#inner_value ⇒ Object
195
196
197
|
# File 'lib/crystalruby/types/type.rb', line 195
def inner_value
@value
end
|
#inspect ⇒ Object
187
188
189
|
# File 'lib/crystalruby/types/type.rb', line 187
def inspect
value.inspect
end
|
#item_size ⇒ Object
242
243
244
|
# File 'lib/crystalruby/types/type.rb', line 242
def item_size
inner_types.map(&:memsize).sum
end
|
#native ⇒ Object
123
124
125
|
# File 'lib/crystalruby/types/type.rb', line 123
def native
value(native: true)
end
|
#nil? ⇒ Boolean
179
180
181
|
# File 'lib/crystalruby/types/type.rb', line 179
def nil?
value.nil?
end
|
#total_memsize ⇒ Object
246
247
248
|
# File 'lib/crystalruby/types/type.rb', line 246
def total_memsize
memsize
end
|