mt-lang 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,650 +1,652 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MilkTea
4
- module TypePredicates
5
- def method_dispatch_receiver_type(receiver_type)
6
- return receiver_type.definition if receiver_type.is_a?(Types::StructInstance) || receiver_type.is_a?(Types::VariantInstance)
7
-
8
- if receiver_type.is_a?(Types::Nullable)
9
- dispatch_base_type = method_dispatch_receiver_type(receiver_type.base)
10
- return receiver_type if dispatch_base_type == receiver_type.base
11
-
12
- return Types::Registry.nullable(dispatch_base_type)
13
- end
14
-
15
- case receiver_type
16
- when Types::Span
17
- normalized = Types::Registry.span(Types::TypeVar.new("__receiver_arg0"))
18
- return normalized == receiver_type ? receiver_type : normalized
19
- when Types::SoA
20
- normalized = Types::Registry.soa(Types::TypeVar.new("__receiver_arg0"), count: 0)
21
- return normalized == receiver_type ? receiver_type : normalized
22
- when Types::Simd
23
- normalized = Types::Registry.simd(Types::TypeVar.new("__receiver_arg0"), lane_count: 0)
24
- return normalized == receiver_type ? receiver_type : normalized
25
- when Types::Task
26
- normalized = Types::Registry.task(Types::TypeVar.new("__receiver_arg0"))
27
- return normalized == receiver_type ? receiver_type : normalized
28
- when Types::Dyn
29
- normalized = Types::Registry.dyn(Types::TypeVar.new("__receiver_arg0"))
30
- return normalized == receiver_type ? receiver_type : normalized
31
- end
32
-
33
- return receiver_type unless receiver_type.is_a?(Types::GenericInstance)
34
-
35
- dispatch_receiver_type = Types::Registry.generic_instance(
36
- receiver_type.name,
37
- receiver_type.arguments.each_with_index.map do |_argument, index|
38
- Types::TypeVar.new("__receiver_arg#{index}")
39
- end,
40
- )
41
- dispatch_receiver_type == receiver_type ? receiver_type : dispatch_receiver_type
42
- end
4
+ module Types
5
+ module Predicates
6
+ def method_dispatch_receiver_type(receiver_type)
7
+ return receiver_type.definition if receiver_type.is_a?(Types::StructInstance) || receiver_type.is_a?(Types::VariantInstance)
43
8
 
44
- def task_root_proc_type?(type)
45
- proc_type?(type) && type.params.empty? && type.return_type.is_a?(Types::Task)
46
- end
9
+ if receiver_type.is_a?(Types::Nullable)
10
+ dispatch_base_type = method_dispatch_receiver_type(receiver_type.base)
11
+ return receiver_type if dispatch_base_type == receiver_type.base
47
12
 
48
- def function_type_matches_proc_type?(function_type, proc_type)
49
- return false if function_type.receiver_type || function_type.variadic
50
- return false unless function_type.params.length == proc_type.params.length
51
- return false unless function_type.return_type == proc_type.return_type
13
+ return Types::Registry.nullable(dispatch_base_type)
14
+ end
52
15
 
53
- function_type.params.zip(proc_type.params).all? do |function_param, proc_param|
54
- next false unless function_param.mutable == proc_param.mutable
16
+ case receiver_type
17
+ when Types::Span
18
+ normalized = Types::Registry.span(Types::TypeVar.new("__receiver_arg0"))
19
+ return normalized == receiver_type ? receiver_type : normalized
20
+ when Types::SoA
21
+ normalized = Types::Registry.soa(Types::TypeVar.new("__receiver_arg0"), count: 0)
22
+ return normalized == receiver_type ? receiver_type : normalized
23
+ when Types::Simd
24
+ normalized = Types::Registry.simd(Types::TypeVar.new("__receiver_arg0"), lane_count: 0)
25
+ return normalized == receiver_type ? receiver_type : normalized
26
+ when Types::Task
27
+ normalized = Types::Registry.task(Types::TypeVar.new("__receiver_arg0"))
28
+ return normalized == receiver_type ? receiver_type : normalized
29
+ when Types::Dyn
30
+ normalized = Types::Registry.dyn(Types::TypeVar.new("__receiver_arg0"))
31
+ return normalized == receiver_type ? receiver_type : normalized
32
+ end
55
33
 
56
- function_param.type == proc_param.type ||
57
- same_external_opaque_handle_pointer_compatibility?(function_param.type, proc_param.type)
58
- end
59
- end
34
+ return receiver_type unless receiver_type.is_a?(Types::GenericInstance)
60
35
 
61
- def null_assignable_to?(actual_type, expected_type)
62
- return false unless actual_type.is_a?(Types::Null)
63
- return false unless expected_type.is_a?(Types::Nullable)
64
- return true unless actual_type.target_type
36
+ dispatch_receiver_type = Types::Registry.generic_instance(
37
+ receiver_type.name,
38
+ receiver_type.arguments.each_with_index.map do |_argument, index|
39
+ Types::TypeVar.new("__receiver_arg#{index}")
40
+ end,
41
+ )
42
+ dispatch_receiver_type == receiver_type ? receiver_type : dispatch_receiver_type
43
+ end
65
44
 
66
- actual_type.target_type == expected_type.base
67
- end
45
+ def task_root_proc_type?(type)
46
+ proc_type?(type) && type.params.empty? && type.return_type.is_a?(Types::Task)
47
+ end
68
48
 
69
- def external_typed_null_pointer_compatibility?(actual_type, expected_type)
70
- return false unless actual_type.is_a?(Types::Null)
71
- return false unless actual_type.target_type
72
- return false if expected_type.is_a?(Types::Nullable)
73
- return true if expected_type == Types::Registry.primitive("cstr") && char_pointer_type?(actual_type.target_type)
74
- return false unless pointer_type?(expected_type)
49
+ def function_type_matches_proc_type?(function_type, proc_type)
50
+ return false if function_type.receiver_type || function_type.variadic
51
+ return false unless function_type.params.length == proc_type.params.length
52
+ return false unless function_type.return_type == proc_type.return_type
75
53
 
76
- actual_type.target_type == expected_type
77
- end
54
+ function_type.params.zip(proc_type.params).all? do |function_param, proc_param|
55
+ next false unless function_param.mutable == proc_param.mutable
78
56
 
79
- def numeric_constant_fits_type?(value, expected_type)
80
- if expected_type.integer?
81
- integer_constant_fits_type?(value, expected_type)
82
- else
83
- float_constant_fits_type?(value, expected_type)
57
+ function_param.type == proc_param.type ||
58
+ same_external_opaque_handle_pointer_compatibility?(function_param.type, proc_param.type)
59
+ end
84
60
  end
85
- end
86
61
 
87
- def integer_constant_fits_type?(value, expected_type)
88
- integer_value = exact_integer_constant_value(value)
89
- return false if integer_value.nil?
62
+ def null_assignable_to?(actual_type, expected_type)
63
+ return false unless actual_type.is_a?(Types::Null)
64
+ return false unless expected_type.is_a?(Types::Nullable)
65
+ return true unless actual_type.target_type
90
66
 
91
- value_fits_integer_type?(integer_value, expected_type)
92
- end
93
-
94
- def float_constant_fits_type?(value, expected_type)
95
- return false unless value.is_a?(Numeric)
96
- return false unless value.finite?
67
+ actual_type.target_type == expected_type.base
68
+ end
97
69
 
98
- if expected_type.name == "float"
99
- return value.abs <= (1 << 24) if value.is_a?(Integer)
70
+ def external_typed_null_pointer_compatibility?(actual_type, expected_type)
71
+ return false unless actual_type.is_a?(Types::Null)
72
+ return false unless actual_type.target_type
73
+ return false if expected_type.is_a?(Types::Nullable)
74
+ return true if expected_type == Types::Registry.primitive("cstr") && char_pointer_type?(actual_type.target_type)
75
+ return false unless pointer_type?(expected_type)
100
76
 
101
- exactly_representable_float32?(value.to_f)
102
- else
103
- return true if expected_type.name == "double"
77
+ actual_type.target_type == expected_type
78
+ end
104
79
 
105
- false
80
+ def numeric_constant_fits_type?(value, expected_type)
81
+ if expected_type.integer?
82
+ integer_constant_fits_type?(value, expected_type)
83
+ else
84
+ float_constant_fits_type?(value, expected_type)
85
+ end
106
86
  end
107
- end
108
87
 
109
- def exact_integer_constant_value(value)
110
- return value if value.is_a?(Integer)
111
- return nil unless value.is_a?(Float) && value.finite?
88
+ def integer_constant_fits_type?(value, expected_type)
89
+ integer_value = exact_integer_constant_value(value)
90
+ return false if integer_value.nil?
112
91
 
113
- integer_value = value.to_i
114
- integer_value.to_f == value ? integer_value : nil
115
- end
92
+ value_fits_integer_type?(integer_value, expected_type)
93
+ end
116
94
 
117
- def value_fits_integer_type?(value, expected_type)
118
- return false unless expected_type.is_a?(Types::Primitive) && expected_type.integer?
95
+ def float_constant_fits_type?(value, expected_type)
96
+ return false unless value.is_a?(Numeric)
97
+ return false unless value.finite?
119
98
 
120
- width = expected_type.integer_width
121
- return false if width.nil?
99
+ if expected_type.name == "float"
100
+ return value.abs <= (1 << 24) if value.is_a?(Integer)
122
101
 
123
- min_value, max_value = if expected_type.signed_integer?
124
- [-(1 << (width - 1)), (1 << (width - 1)) - 1]
125
- else
126
- [0, (1 << width) - 1]
127
- end
102
+ exactly_representable_float32?(value.to_f)
103
+ else
104
+ return true if expected_type.name == "double"
128
105
 
129
- value >= min_value && value <= max_value
130
- end
106
+ false
107
+ end
108
+ end
131
109
 
132
- def exactly_representable_float32?(value)
133
- [value].pack("f").unpack1("f") == value
134
- end
110
+ def exact_integer_constant_value(value)
111
+ return value if value.is_a?(Integer)
112
+ return nil unless value.is_a?(Float) && value.finite?
135
113
 
136
- def integer_to_char_compatibility?(actual_type, expected_type)
137
- char_type?(expected_type) && integer_like_char_source_type?(actual_type)
138
- end
114
+ integer_value = value.to_i
115
+ integer_value.to_f == value ? integer_value : nil
116
+ end
139
117
 
140
- def integer_like_char_source_type?(type)
141
- return true if type.is_a?(Types::Primitive) && type.integer?
142
- return true if type.is_a?(Types::EnumBase) && type.backing_type.is_a?(Types::Primitive) && type.backing_type.integer?
118
+ def value_fits_integer_type?(value, expected_type)
119
+ return false unless expected_type.is_a?(Types::Primitive) && expected_type.integer?
143
120
 
144
- false
145
- end
121
+ width = expected_type.integer_width
122
+ return false if width.nil?
146
123
 
147
- def char_type?(type)
148
- type.is_a?(Types::Primitive) && type.name == "char"
149
- end
124
+ min_value, max_value = if expected_type.signed_integer?
125
+ [-(1 << (width - 1)), (1 << (width - 1)) - 1]
126
+ else
127
+ [0, (1 << width) - 1]
128
+ end
150
129
 
151
- def external_numeric_compatibility?(actual_type, expected_type)
152
- return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
153
- return false unless actual_type.numeric? && expected_type.numeric?
130
+ value >= min_value && value <= max_value
131
+ end
154
132
 
155
- return lossless_external_integer_compatibility?(actual_type, expected_type) if actual_type.integer? && expected_type.integer?
156
- return expected_type.float_width >= actual_type.float_width if actual_type.float? && expected_type.float?
133
+ def exactly_representable_float32?(value)
134
+ [value].pack("f").unpack1("f") == value
135
+ end
157
136
 
158
- false
159
- end
137
+ def integer_to_char_compatibility?(actual_type, expected_type)
138
+ char_type?(expected_type) && integer_like_char_source_type?(actual_type)
139
+ end
160
140
 
161
- def lossless_external_integer_compatibility?(actual_type, expected_type)
162
- return false unless actual_type.fixed_width_integer? && expected_type.fixed_width_integer?
141
+ def integer_like_char_source_type?(type)
142
+ return true if type.is_a?(Types::Primitive) && type.integer?
143
+ return true if type.is_a?(Types::EnumBase) && type.backing_type.is_a?(Types::Primitive) && type.backing_type.integer?
163
144
 
164
- if actual_type.signed_integer? == expected_type.signed_integer?
165
- return expected_type.integer_width >= actual_type.integer_width
145
+ false
166
146
  end
167
147
 
168
- return false if actual_type.signed_integer?
148
+ def char_type?(type)
149
+ type.is_a?(Types::Primitive) && type.name == "char"
150
+ end
169
151
 
170
- expected_type.signed_integer? && expected_type.integer_width > actual_type.integer_width
171
- end
152
+ def external_numeric_compatibility?(actual_type, expected_type)
153
+ return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
154
+ return false unless actual_type.numeric? && expected_type.numeric?
172
155
 
173
- def lossless_integer_compatibility?(actual_type, expected_type)
174
- return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
175
- return false unless actual_type.integer? && expected_type.integer?
156
+ return lossless_external_integer_compatibility?(actual_type, expected_type) if actual_type.integer? && expected_type.integer?
157
+ return expected_type.float_width >= actual_type.float_width if actual_type.float? && expected_type.float?
176
158
 
177
- lossless_external_integer_compatibility?(actual_type, expected_type)
178
- end
159
+ false
160
+ end
179
161
 
180
- def contextual_int_to_float_compatibility?(actual_type, expected_type)
181
- actual_type.is_a?(Types::Primitive) && actual_type.integer? &&
182
- expected_type.is_a?(Types::Primitive) && expected_type.float?
183
- end
162
+ def lossless_external_integer_compatibility?(actual_type, expected_type)
163
+ return false unless actual_type.fixed_width_integer? && expected_type.fixed_width_integer?
184
164
 
185
- def contextual_int_to_float_target?(type)
186
- type.is_a?(Types::Primitive) && type.float?
187
- end
165
+ if actual_type.signed_integer? == expected_type.signed_integer?
166
+ return expected_type.integer_width >= actual_type.integer_width
167
+ end
188
168
 
189
- def mutable_to_const_pointer_compatibility?(actual_type, expected_type)
190
- return mutable_to_const_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
191
- return mutable_to_const_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
192
- return false if actual_type.is_a?(Types::Nullable)
193
- return false unless (mutable_pointer_type?(actual_type) || own_type?(actual_type)) && const_pointer_type?(expected_type)
169
+ return false if actual_type.signed_integer?
194
170
 
195
- pointee_type(actual_type) == pointee_type(expected_type)
196
- end
171
+ expected_type.signed_integer? && expected_type.integer_width > actual_type.integer_width
172
+ end
197
173
 
198
- def own_to_raw_pointer_compatibility?(actual_type, expected_type)
199
- return own_to_raw_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
200
- return own_to_raw_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
201
- return false if actual_type.is_a?(Types::Nullable)
202
- return false unless own_type?(actual_type)
203
- return false unless mutable_pointer_type?(expected_type) || const_pointer_type?(expected_type)
174
+ def lossless_integer_compatibility?(actual_type, expected_type)
175
+ return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
176
+ return false unless actual_type.integer? && expected_type.integer?
204
177
 
205
- pointee_type(actual_type) == pointee_type(expected_type)
206
- end
178
+ lossless_external_integer_compatibility?(actual_type, expected_type)
179
+ end
207
180
 
208
- def foreign_span_boundary_compatible?(public_type, boundary_type)
209
- return false unless public_type.is_a?(Types::Span) && boundary_type.is_a?(Types::Span)
181
+ def contextual_int_to_float_compatibility?(actual_type, expected_type)
182
+ actual_type.is_a?(Types::Primitive) && actual_type.integer? &&
183
+ expected_type.is_a?(Types::Primitive) && expected_type.float?
184
+ end
210
185
 
211
- foreign_boundary_element_compatible?(public_type.element_type, boundary_type.element_type)
212
- end
186
+ def contextual_int_to_float_target?(type)
187
+ type.is_a?(Types::Primitive) && type.float?
188
+ end
213
189
 
214
- def foreign_char_pointer_buffer_boundary_compatible?(public_type, boundary_type)
215
- return false unless char_pointer_type?(boundary_type)
190
+ def mutable_to_const_pointer_compatibility?(actual_type, expected_type)
191
+ return mutable_to_const_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
192
+ return mutable_to_const_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
193
+ return false if actual_type.is_a?(Types::Nullable)
194
+ return false unless (mutable_pointer_type?(actual_type) || own_type?(actual_type)) && const_pointer_type?(expected_type)
216
195
 
217
- return true if public_type.is_a?(Types::Span) && public_type.element_type == Types::Registry.primitive("char")
218
- return true if char_array_text_type?(public_type)
219
- return true if str_buffer_type?(public_type)
196
+ pointee_type(actual_type) == pointee_type(expected_type)
197
+ end
220
198
 
221
- false
222
- end
199
+ def own_to_raw_pointer_compatibility?(actual_type, expected_type)
200
+ return own_to_raw_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
201
+ return own_to_raw_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
202
+ return false if actual_type.is_a?(Types::Nullable)
203
+ return false unless own_type?(actual_type)
204
+ return false unless mutable_pointer_type?(expected_type) || const_pointer_type?(expected_type)
223
205
 
224
- def foreign_boundary_element_compatible?(public_type, boundary_type)
225
- return true if public_type == boundary_type
226
- return true if public_type == Types::Registry.string_view && boundary_type == Types::Registry.primitive("cstr")
227
- return true if public_type == Types::Registry.string_view && char_pointer_type?(boundary_type)
206
+ pointee_type(actual_type) == pointee_type(expected_type)
207
+ end
228
208
 
229
- foreign_identity_projection_compatible?(public_type, boundary_type)
230
- end
209
+ def foreign_span_boundary_compatible?(public_type, boundary_type)
210
+ return false unless public_type.is_a?(Types::Span) && boundary_type.is_a?(Types::Span)
231
211
 
232
- def foreign_identity_projection_compatible?(actual_type, expected_type)
233
- foreign_identity_projection_cast_compatible?(actual_type, expected_type) ||
234
- foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
235
- end
212
+ foreign_boundary_element_compatible?(public_type.element_type, boundary_type.element_type)
213
+ end
214
+
215
+ def foreign_char_pointer_buffer_boundary_compatible?(public_type, boundary_type)
216
+ return false unless char_pointer_type?(boundary_type)
236
217
 
237
- def foreign_identity_projection_cast_compatible?(actual_type, expected_type)
238
- return true if actual_type == expected_type
239
- return true if mutable_to_const_pointer_compatibility?(actual_type, expected_type)
240
- return true if same_external_opaque_c_name?(actual_type, expected_type)
241
- return true if foreign_function_type_projection_compatible?(actual_type, expected_type)
242
- return true if native_foreign_layout_compatible?(actual_type, expected_type)
243
- return true if native_foreign_layout_compatible?(expected_type, actual_type)
244
- return true if quat_vec4_layout_compatible?(actual_type, expected_type)
218
+ return true if public_type.is_a?(Types::Span) && public_type.element_type == Types::Registry.primitive("char")
219
+ return true if char_array_text_type?(public_type)
220
+ return true if str_buffer_type?(public_type)
245
221
 
246
- if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
247
- return foreign_identity_projection_cast_compatible?(actual_type.base, expected_type.base)
222
+ false
248
223
  end
249
224
 
250
- return foreign_identity_projection_cast_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
251
- return false if actual_type.is_a?(Types::Nullable)
225
+ def foreign_boundary_element_compatible?(public_type, boundary_type)
226
+ return true if public_type == boundary_type
227
+ return true if public_type == Types::Registry.string_view && boundary_type == Types::Registry.primitive("cstr")
228
+ return true if public_type == Types::Registry.string_view && char_pointer_type?(boundary_type)
252
229
 
253
- return true if same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
230
+ foreign_identity_projection_compatible?(public_type, boundary_type)
231
+ end
254
232
 
255
- if pointer_type?(actual_type) && pointer_type?(expected_type)
256
- return false if const_pointer_type?(actual_type) && mutable_pointer_type?(expected_type)
257
- return true if void_pointer_type?(actual_type) || void_pointer_type?(expected_type)
233
+ def foreign_identity_projection_compatible?(actual_type, expected_type)
234
+ foreign_identity_projection_cast_compatible?(actual_type, expected_type) ||
235
+ foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
236
+ end
258
237
 
259
- return true if foreign_identity_projection_cast_compatible?(actual_type.arguments.first, expected_type.arguments.first)
238
+ def foreign_identity_projection_cast_compatible?(actual_type, expected_type)
239
+ return true if actual_type == expected_type
240
+ return true if mutable_to_const_pointer_compatibility?(actual_type, expected_type)
241
+ return true if same_external_opaque_c_name?(actual_type, expected_type)
242
+ return true if foreign_function_type_projection_compatible?(actual_type, expected_type)
243
+ return true if native_foreign_layout_compatible?(actual_type, expected_type)
244
+ return true if native_foreign_layout_compatible?(expected_type, actual_type)
245
+ return true if quat_vec4_layout_compatible?(actual_type, expected_type)
246
+
247
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
248
+ return foreign_identity_projection_cast_compatible?(actual_type.base, expected_type.base)
249
+ end
260
250
 
261
- return foreign_external_layout_compatible?(actual_type.arguments.first, expected_type.arguments.first)
262
- end
251
+ return foreign_identity_projection_cast_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
252
+ return false if actual_type.is_a?(Types::Nullable)
263
253
 
264
- return true if void_pointer_type?(actual_type) && opaque_type?(expected_type)
265
- return true if opaque_type?(actual_type) && void_pointer_type?(expected_type)
266
- return true if char_pointer_type?(actual_type) && expected_type == Types::Registry.primitive("cstr")
267
- return true if actual_type == Types::Registry.primitive("cstr") && char_pointer_type?(expected_type)
254
+ return true if same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
268
255
 
269
- false
270
- end
256
+ if pointer_type?(actual_type) && pointer_type?(expected_type)
257
+ return false if const_pointer_type?(actual_type) && mutable_pointer_type?(expected_type)
258
+ return true if void_pointer_type?(actual_type) || void_pointer_type?(expected_type)
271
259
 
272
- def same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
273
- if actual_type.is_a?(Types::Opaque) && pointer_type?(expected_type)
274
- return same_external_opaque_c_name?(actual_type, expected_type.arguments.first)
275
- end
260
+ return true if foreign_identity_projection_cast_compatible?(actual_type.arguments.first, expected_type.arguments.first)
276
261
 
277
- if pointer_type?(actual_type) && expected_type.is_a?(Types::Opaque)
278
- return same_external_opaque_c_name?(actual_type.arguments.first, expected_type)
262
+ return foreign_external_layout_compatible?(actual_type.arguments.first, expected_type.arguments.first)
263
+ end
264
+
265
+ return true if void_pointer_type?(actual_type) && opaque_type?(expected_type)
266
+ return true if opaque_type?(actual_type) && void_pointer_type?(expected_type)
267
+ return true if char_pointer_type?(actual_type) && expected_type == Types::Registry.primitive("cstr")
268
+ return true if actual_type == Types::Registry.primitive("cstr") && char_pointer_type?(expected_type)
269
+
270
+ false
279
271
  end
280
272
 
281
- false
282
- end
273
+ def same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
274
+ if actual_type.is_a?(Types::Opaque) && pointer_type?(expected_type)
275
+ return same_external_opaque_c_name?(actual_type, expected_type.arguments.first)
276
+ end
283
277
 
284
- def foreign_function_type_projection_compatible?(actual_type, expected_type)
285
- return false unless actual_type.is_a?(Types::Function) && expected_type.is_a?(Types::Function)
286
- return false unless actual_type.receiver_type == expected_type.receiver_type
287
- return false unless actual_type.variadic == expected_type.variadic
288
- return false unless actual_type.params.length == expected_type.params.length
289
- return false unless foreign_identity_projection_compatible?(actual_type.return_type, expected_type.return_type)
278
+ if pointer_type?(actual_type) && expected_type.is_a?(Types::Opaque)
279
+ return same_external_opaque_c_name?(actual_type.arguments.first, expected_type)
280
+ end
290
281
 
291
- actual_type.params.zip(expected_type.params).all? do |actual_param, expected_param|
292
- actual_param.mutable == expected_param.mutable &&
293
- actual_param.passing_mode == expected_param.passing_mode &&
294
- actual_param.boundary_type == expected_param.boundary_type &&
295
- foreign_identity_projection_compatible?(actual_param.type, expected_param.type)
282
+ false
296
283
  end
297
- end
298
284
 
299
- def same_external_opaque_c_name?(actual_type, expected_type)
300
- return false unless actual_type.is_a?(Types::Opaque) && expected_type.is_a?(Types::Opaque)
301
- return false unless actual_type.external || actual_type.linkage_name
302
- return false unless expected_type.external || expected_type.linkage_name
285
+ def foreign_function_type_projection_compatible?(actual_type, expected_type)
286
+ return false unless actual_type.is_a?(Types::Function) && expected_type.is_a?(Types::Function)
287
+ return false unless actual_type.receiver_type == expected_type.receiver_type
288
+ return false unless actual_type.variadic == expected_type.variadic
289
+ return false unless actual_type.params.length == expected_type.params.length
290
+ return false unless foreign_identity_projection_compatible?(actual_type.return_type, expected_type.return_type)
291
+
292
+ actual_type.params.zip(expected_type.params).all? do |actual_param, expected_param|
293
+ actual_param.mutable == expected_param.mutable &&
294
+ actual_param.passing_mode == expected_param.passing_mode &&
295
+ actual_param.boundary_type == expected_param.boundary_type &&
296
+ foreign_identity_projection_compatible?(actual_param.type, expected_param.type)
297
+ end
298
+ end
303
299
 
304
- foreign_opaque_c_name(actual_type) == foreign_opaque_c_name(expected_type)
305
- end
300
+ def same_external_opaque_c_name?(actual_type, expected_type)
301
+ return false unless actual_type.is_a?(Types::Opaque) && expected_type.is_a?(Types::Opaque)
302
+ return false unless actual_type.external || actual_type.linkage_name
303
+ return false unless expected_type.external || expected_type.linkage_name
306
304
 
307
- def foreign_opaque_c_name(type)
308
- type.linkage_name || type.name
309
- end
305
+ foreign_opaque_c_name(actual_type) == foreign_opaque_c_name(expected_type)
306
+ end
310
307
 
311
- def foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
312
- if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
313
- return foreign_identity_projection_reinterpret_compatible?(actual_type.base, expected_type.base)
308
+ def foreign_opaque_c_name(type)
309
+ type.linkage_name || type.name
314
310
  end
315
311
 
316
- return foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
317
- return false if actual_type.is_a?(Types::Nullable)
312
+ def foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
313
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
314
+ return foreign_identity_projection_reinterpret_compatible?(actual_type.base, expected_type.base)
315
+ end
318
316
 
319
- foreign_external_layout_compatible?(actual_type, expected_type)
320
- end
317
+ return foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
318
+ return false if actual_type.is_a?(Types::Nullable)
321
319
 
322
- def foreign_external_layout_compatible?(actual_type, expected_type, seen = {})
323
- return false unless actual_type.is_a?(Types::Struct) && expected_type.is_a?(Types::Struct)
324
- return false if actual_type.is_a?(Types::Union) != expected_type.is_a?(Types::Union)
325
- return false unless actual_type.external && expected_type.external
326
- return false unless actual_type.name == expected_type.name
327
- return false unless actual_type.packed == expected_type.packed
328
- return false unless actual_type.alignment == expected_type.alignment
320
+ foreign_external_layout_compatible?(actual_type, expected_type)
321
+ end
322
+
323
+ def foreign_external_layout_compatible?(actual_type, expected_type, seen = {})
324
+ return false unless actual_type.is_a?(Types::Struct) && expected_type.is_a?(Types::Struct)
325
+ return false if actual_type.is_a?(Types::Union) != expected_type.is_a?(Types::Union)
326
+ return false unless actual_type.external && expected_type.external
327
+ return false unless actual_type.name == expected_type.name
328
+ return false unless actual_type.packed == expected_type.packed
329
+ return false unless actual_type.alignment == expected_type.alignment
329
330
 
330
- key = [actual_type.object_id, expected_type.object_id]
331
- return true if seen[key]
331
+ key = [actual_type.object_id, expected_type.object_id]
332
+ return true if seen[key]
332
333
 
333
- seen[key] = true
334
- actual_fields = actual_type.fields
335
- expected_fields = expected_type.fields
336
- return false unless actual_fields.keys == expected_fields.keys
334
+ seen[key] = true
335
+ actual_fields = actual_type.fields
336
+ expected_fields = expected_type.fields
337
+ return false unless actual_fields.keys == expected_fields.keys
337
338
 
338
- actual_fields.all? do |field_name, field_type|
339
- foreign_external_layout_field_compatible?(field_type, expected_fields.fetch(field_name), seen)
339
+ actual_fields.all? do |field_name, field_type|
340
+ foreign_external_layout_field_compatible?(field_type, expected_fields.fetch(field_name), seen)
341
+ end
340
342
  end
341
- end
342
343
 
343
- def foreign_external_layout_field_compatible?(actual_type, expected_type, seen)
344
- return true if actual_type == expected_type
344
+ def foreign_external_layout_field_compatible?(actual_type, expected_type, seen)
345
+ return true if actual_type == expected_type
345
346
 
346
- if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
347
- return foreign_external_layout_field_compatible?(actual_type.base, expected_type.base, seen)
348
- end
347
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
348
+ return foreign_external_layout_field_compatible?(actual_type.base, expected_type.base, seen)
349
+ end
349
350
 
350
- if pointer_type?(actual_type) && pointer_type?(expected_type)
351
- return foreign_external_layout_field_compatible?(actual_type.arguments.first, expected_type.arguments.first, seen)
352
- end
351
+ if pointer_type?(actual_type) && pointer_type?(expected_type)
352
+ return foreign_external_layout_field_compatible?(actual_type.arguments.first, expected_type.arguments.first, seen)
353
+ end
353
354
 
354
- if array_type?(actual_type) && array_type?(expected_type)
355
- return false unless array_length(actual_type) == array_length(expected_type)
355
+ if array_type?(actual_type) && array_type?(expected_type)
356
+ return false unless array_length(actual_type) == array_length(expected_type)
356
357
 
357
- return foreign_external_layout_field_compatible?(array_element_type(actual_type), array_element_type(expected_type), seen)
358
- end
358
+ return foreign_external_layout_field_compatible?(array_element_type(actual_type), array_element_type(expected_type), seen)
359
+ end
359
360
 
360
- foreign_external_layout_compatible?(actual_type, expected_type, seen)
361
- end
361
+ foreign_external_layout_compatible?(actual_type, expected_type, seen)
362
+ end
362
363
 
363
- def void_pointer_type?(type)
364
- pointer_type?(type) && type.arguments.first == Types::Registry.primitive("void")
365
- end
364
+ def void_pointer_type?(type)
365
+ pointer_type?(type) && type.arguments.first == Types::Registry.primitive("void")
366
+ end
366
367
 
367
- def native_foreign_layout_compatible?(native_type, foreign_type)
368
- return false unless (native_type.is_a?(Types::Vector) || native_type.is_a?(Types::Matrix) || native_type.is_a?(Types::Quaternion))
369
- return false unless foreign_type.is_a?(Types::Struct) && foreign_type.external
368
+ def native_foreign_layout_compatible?(native_type, foreign_type)
369
+ return false unless (native_type.is_a?(Types::Vector) || native_type.is_a?(Types::Matrix) || native_type.is_a?(Types::Quaternion))
370
+ return false unless foreign_type.is_a?(Types::Struct) && foreign_type.external
370
371
 
371
- native_flat = flatten_field_types(native_type)
372
- foreign_flat = flatten_field_types(foreign_type)
373
- return false unless native_flat.size == foreign_flat.size
372
+ native_flat = flatten_field_types(native_type)
373
+ foreign_flat = flatten_field_types(foreign_type)
374
+ return false unless native_flat.size == foreign_flat.size
374
375
 
375
- native_flat.zip(foreign_flat).all? { |nf, ff| nf == ff }
376
- end
376
+ native_flat.zip(foreign_flat).all? { |nf, ff| nf == ff }
377
+ end
377
378
 
378
- def quat_vec4_layout_compatible?(a, b)
379
- (a.is_a?(Types::Quaternion) && b.is_a?(Types::Vector) && b.width == 4 && b.element_type.name == "float") ||
380
- (b.is_a?(Types::Quaternion) && a.is_a?(Types::Vector) && a.width == 4 && a.element_type.name == "float")
381
- end
379
+ def quat_vec4_layout_compatible?(a, b)
380
+ (a.is_a?(Types::Quaternion) && b.is_a?(Types::Vector) && b.width == 4 && b.element_type.name == "float") ||
381
+ (b.is_a?(Types::Quaternion) && a.is_a?(Types::Vector) && a.width == 4 && a.element_type.name == "float")
382
+ end
382
383
 
383
- def flatten_field_types(type)
384
- if type.is_a?(Types::Primitive)
385
- [type]
386
- elsif type.respond_to?(:fields) && type.fields
387
- type.fields.values.flat_map { |ft| flatten_field_types(ft) }
388
- else
389
- [type]
384
+ def flatten_field_types(type)
385
+ if type.is_a?(Types::Primitive)
386
+ [type]
387
+ elsif type.respond_to?(:fields) && type.fields
388
+ type.fields.values.flat_map { |ft| flatten_field_types(ft) }
389
+ else
390
+ [type]
391
+ end
390
392
  end
391
- end
392
393
 
393
- def char_pointer_type?(type)
394
- pointer_type?(type) && type.arguments.first == Types::Registry.primitive("char")
395
- end
394
+ def char_pointer_type?(type)
395
+ pointer_type?(type) && type.arguments.first == Types::Registry.primitive("char")
396
+ end
396
397
 
397
- def opaque_type?(type)
398
- type.is_a?(Types::Opaque)
399
- end
398
+ def opaque_type?(type)
399
+ type.is_a?(Types::Opaque)
400
+ end
400
401
 
401
- def pointer_type?(type)
402
- mutable_pointer_type?(type) || const_pointer_type?(type) || own_type?(type)
403
- end
402
+ def pointer_type?(type)
403
+ mutable_pointer_type?(type) || const_pointer_type?(type) || own_type?(type)
404
+ end
404
405
 
405
- def mutable_pointer_type?(type)
406
- type.is_a?(Types::GenericInstance) && type.name == "ptr" && type.arguments.length == 1
407
- end
406
+ def mutable_pointer_type?(type)
407
+ type.is_a?(Types::GenericInstance) && type.name == "ptr" && type.arguments.length == 1
408
+ end
408
409
 
409
- def const_pointer_type?(type)
410
- type.is_a?(Types::GenericInstance) && type.name == "const_ptr" && type.arguments.length == 1
411
- end
410
+ def const_pointer_type?(type)
411
+ type.is_a?(Types::GenericInstance) && type.name == "const_ptr" && type.arguments.length == 1
412
+ end
412
413
 
413
- def own_type?(type)
414
- type.is_a?(Types::GenericInstance) && type.name == "own" && type.arguments.length == 1
415
- end
414
+ def own_type?(type)
415
+ type.is_a?(Types::GenericInstance) && type.name == "own" && type.arguments.length == 1
416
+ end
416
417
 
417
- def owned_referent_type(type)
418
- type.arguments.first if own_type?(type)
419
- end
418
+ def owned_referent_type(type)
419
+ type.arguments.first if own_type?(type)
420
+ end
420
421
 
421
- def ref_type?(type)
422
- type.is_a?(Types::GenericInstance) && type.name == "ref" && [1, 2].include?(type.arguments.length)
423
- end
422
+ def ref_type?(type)
423
+ type.is_a?(Types::GenericInstance) && type.name == "ref" && [1, 2].include?(type.arguments.length)
424
+ end
424
425
 
425
- def atomic_type?(type)
426
- type.is_a?(Types::GenericInstance) && type.name == "atomic" && type.arguments.length == 1
427
- end
426
+ def atomic_type?(type)
427
+ type.is_a?(Types::GenericInstance) && type.name == "atomic" && type.arguments.length == 1
428
+ end
428
429
 
429
- def atomic_element_type(type)
430
- type.arguments.first
431
- end
430
+ def atomic_element_type(type)
431
+ type.arguments.first
432
+ end
432
433
 
433
- def ref_type_without_lifetime?(type)
434
- type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 1
435
- end
434
+ def ref_type_without_lifetime?(type)
435
+ type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 1
436
+ end
436
437
 
437
- def ref_lifetime(type)
438
- return unless type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 2
438
+ def ref_lifetime(type)
439
+ return unless type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 2
439
440
 
440
- type.arguments.first
441
- end
441
+ type.arguments.first
442
+ end
442
443
 
443
- def dyn_type?(type)
444
- type.is_a?(Types::Dyn)
445
- end
444
+ def dyn_type?(type)
445
+ type.is_a?(Types::Dyn)
446
+ end
446
447
 
447
- def task_type?(type)
448
- type.is_a?(Types::Task)
449
- end
448
+ def task_type?(type)
449
+ type.is_a?(Types::Task)
450
+ end
450
451
 
451
- def struct_with_target_type?(type)
452
- type.is_a?(Types::Struct) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
453
- end
452
+ def struct_with_target_type?(type)
453
+ type.is_a?(Types::Struct) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
454
+ end
454
455
 
455
- def proc_type?(type)
456
- type.is_a?(Types::Proc)
457
- end
456
+ def proc_type?(type)
457
+ type.is_a?(Types::Proc)
458
+ end
458
459
 
459
- def pointee_type(type)
460
- return unless pointer_type?(type)
460
+ def pointee_type(type)
461
+ return unless pointer_type?(type)
461
462
 
462
- type.arguments.first
463
- end
463
+ type.arguments.first
464
+ end
464
465
 
465
- def referenced_type(type)
466
- return unless ref_type?(type)
466
+ def referenced_type(type)
467
+ return unless ref_type?(type)
467
468
 
468
- type.arguments.length == 1 ? type.arguments.first : type.arguments[1]
469
- end
469
+ type.arguments.length == 1 ? type.arguments.first : type.arguments[1]
470
+ end
470
471
 
471
- def const_pointer_to(type)
472
- Types::Registry.generic_instance("const_ptr", [type])
473
- end
472
+ def const_pointer_to(type)
473
+ Types::Registry.generic_instance("const_ptr", [type])
474
+ end
474
475
 
475
- def call_arity_matches?(function_type, actual_count)
476
- return actual_count >= function_type.params.length if function_type.is_a?(Types::Function) && function_type.variadic
476
+ def call_arity_matches?(function_type, actual_count)
477
+ return actual_count >= function_type.params.length if function_type.is_a?(Types::Function) && function_type.variadic
477
478
 
478
- actual_count == function_type.params.length
479
- end
479
+ actual_count == function_type.params.length
480
+ end
480
481
 
481
- def arity_error_message(function_type, name, actual_count, required_count: nil)
482
- if function_type.is_a?(Types::Function) && function_type.variadic
483
- "function #{name} expects at least #{function_type.params.length} arguments, got #{actual_count}"
484
- elsif required_count && required_count < function_type.params.length
485
- "function #{name} expects #{required_count}..#{function_type.params.length} arguments, got #{actual_count}"
486
- else
487
- "function #{name} expects #{function_type.params.length} arguments, got #{actual_count}"
482
+ def arity_error_message(function_type, name, actual_count, required_count: nil)
483
+ if function_type.is_a?(Types::Function) && function_type.variadic
484
+ "function #{name} expects at least #{function_type.params.length} arguments, got #{actual_count}"
485
+ elsif required_count && required_count < function_type.params.length
486
+ "function #{name} expects #{required_count}..#{function_type.params.length} arguments, got #{actual_count}"
487
+ else
488
+ "function #{name} expects #{function_type.params.length} arguments, got #{actual_count}"
489
+ end
488
490
  end
489
- end
490
491
 
491
- def string_builder_type?(type)
492
- type.respond_to?(:name) && type.respond_to?(:module_name) && type.name == "String" && type.module_name == "std.string"
493
- end
492
+ def string_builder_type?(type)
493
+ type.respond_to?(:name) && type.respond_to?(:module_name) && type.name == "String" && type.module_name == "std.string"
494
+ end
494
495
 
495
- def string_builder_ref_type?(type)
496
- ref_type?(type) && string_builder_type?(referenced_type(type))
497
- end
496
+ def string_builder_ref_type?(type)
497
+ ref_type?(type) && string_builder_type?(referenced_type(type))
498
+ end
498
499
 
499
- def callable_param_ref_supported?(type)
500
- case type
501
- when Types::Proc
502
- type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
503
- !contains_ref_type?(type.return_type)
504
- when Types::Function
505
- type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
506
- !contains_ref_type?(type.return_type) &&
507
- (type.receiver_type.nil? || !contains_ref_type?(type.receiver_type))
508
- else
509
- false
500
+ def callable_param_ref_supported?(type)
501
+ case type
502
+ when Types::Proc
503
+ type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
504
+ !contains_ref_type?(type.return_type)
505
+ when Types::Function
506
+ type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
507
+ !contains_ref_type?(type.return_type) &&
508
+ (type.receiver_type.nil? || !contains_ref_type?(type.receiver_type))
509
+ else
510
+ false
511
+ end
510
512
  end
511
- end
512
513
 
513
- def contains_ref_type?(type, visited = {}, allow_lifetimes: [])
514
- visitor = ContainsRefTypeVisitor.new(allow_lifetimes:)
515
- visitor.visit(type)
516
- visitor.found?
517
- end
514
+ def contains_ref_type?(type, visited = {}, allow_lifetimes: [])
515
+ visitor = ContainsRefTypeVisitor.new(allow_lifetimes:)
516
+ visitor.visit(type)
517
+ visitor.found?
518
+ end
518
519
 
519
- def contains_type_var?(type)
520
- visitor = ContainsTypeVarVisitor.new
521
- visitor.visit(type)
522
- visitor.found?
523
- end
520
+ def contains_type_var?(type)
521
+ visitor = ContainsTypeVarVisitor.new
522
+ visitor.visit(type)
523
+ visitor.found?
524
+ end
524
525
 
525
- def collection_loop_type(type)
526
- return type.arguments.first if Types.array_type?(type)
527
- return type.element_type if type.is_a?(Types::Span)
526
+ def collection_loop_type(type)
527
+ return type.arguments.first if Types.array_type?(type)
528
+ return type.element_type if type.is_a?(Types::Span)
528
529
 
529
- nil
530
- end
530
+ nil
531
+ end
531
532
 
532
- def collection_loop_binding_type(iterable_type, element_type)
533
- return nil unless Types.array_type?(iterable_type) || iterable_type.is_a?(Types::Span)
534
- return nil unless collection_loop_ref_element_type?(element_type)
533
+ def collection_loop_binding_type(iterable_type, element_type)
534
+ return nil unless Types.array_type?(iterable_type) || iterable_type.is_a?(Types::Span)
535
+ return nil unless collection_loop_ref_element_type?(element_type)
535
536
 
536
- Types::Registry.generic_instance("ref", [element_type])
537
- end
537
+ Types::Registry.generic_instance("ref", [element_type])
538
+ end
538
539
 
539
- def collection_loop_ref_element_type?(type)
540
- type.is_a?(Types::Struct)
541
- end
540
+ def collection_loop_ref_element_type?(type)
541
+ type.is_a?(Types::Struct)
542
+ end
542
543
 
543
- def integer_type_argument?(argument)
544
- argument.is_a?(Types::LiteralTypeArg) && argument.value.is_a?(Integer)
545
- end
544
+ def integer_type_argument?(argument)
545
+ argument.is_a?(Types::LiteralTypeArg) && argument.value.is_a?(Integer)
546
+ end
546
547
 
547
- def generic_integer_type_argument?(argument)
548
- integer_type_argument?(argument) || argument.is_a?(Types::TypeVar)
549
- end
548
+ def generic_integer_type_argument?(argument)
549
+ integer_type_argument?(argument) || argument.is_a?(Types::TypeVar)
550
+ end
550
551
 
551
- def validate_generic_type!(name, arguments, &error)
552
- case name
553
- when "ptr"
554
- error.call("ptr requires exactly one type argument") unless arguments.length == 1
555
- error.call("ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
556
- when "const_ptr"
557
- error.call("const_ptr requires exactly one type argument") unless arguments.length == 1
558
- error.call("const_ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
559
- error.call("const_ptr cannot target ref types") if contains_ref_type?(arguments.first)
560
- when "own"
561
- error.call("own requires exactly one type argument") unless arguments.length == 1
562
- error.call("own type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
563
- when "ref"
564
- unless [1, 2].include?(arguments.length)
565
- error.call("ref requires exactly one type argument")
566
- end
567
- type_arg = arguments.length == 1 ? arguments.first : arguments[1]
568
- error.call("ref type argument must be a type") if type_arg.is_a?(Types::LiteralTypeArg)
569
- error.call("ref cannot target void") if type_arg.is_a?(Types::Primitive) && type_arg.void?
570
- if contains_ref_type?(type_arg)
571
- unless (type_arg.is_a?(Types::Struct) || type_arg.is_a?(Types::StructInstance)) && type_arg.lifetime_params&.any?
572
- error.call("ref cannot target another ref type")
552
+ def validate_generic_type!(name, arguments, &error)
553
+ case name
554
+ when "ptr"
555
+ error.call("ptr requires exactly one type argument") unless arguments.length == 1
556
+ error.call("ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
557
+ when "const_ptr"
558
+ error.call("const_ptr requires exactly one type argument") unless arguments.length == 1
559
+ error.call("const_ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
560
+ error.call("const_ptr cannot target ref types") if contains_ref_type?(arguments.first)
561
+ when "own"
562
+ error.call("own requires exactly one type argument") unless arguments.length == 1
563
+ error.call("own type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
564
+ when "ref"
565
+ unless [1, 2].include?(arguments.length)
566
+ error.call("ref requires exactly one type argument")
573
567
  end
568
+ type_arg = arguments.length == 1 ? arguments.first : arguments[1]
569
+ error.call("ref type argument must be a type") if type_arg.is_a?(Types::LiteralTypeArg)
570
+ error.call("ref cannot target void") if type_arg.is_a?(Types::Primitive) && type_arg.void?
571
+ if contains_ref_type?(type_arg)
572
+ unless (type_arg.is_a?(Types::Struct) || type_arg.is_a?(Types::StructInstance)) && type_arg.lifetime_params&.any?
573
+ error.call("ref cannot target another ref type")
574
+ end
575
+ end
576
+ when "span"
577
+ error.call("span requires exactly one type argument") unless arguments.length == 1
578
+ error.call("span element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
579
+ when "array"
580
+ error.call("array requires exactly two type arguments") unless arguments.length == 2
581
+ error.call("array element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
582
+ error.call("array length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
583
+ error.call("array length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
584
+ when "SoA"
585
+ error.call("SoA requires exactly two type arguments") unless arguments.length == 2
586
+ error.call("SoA element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
587
+ error.call("SoA element type must be a struct with fields") unless arguments.first.respond_to?(:fields) && arguments.first.fields.any?
588
+ error.call("SoA length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
589
+ error.call("SoA length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
590
+ when "simd"
591
+ error.call("simd requires exactly two type arguments") unless arguments.length == 2
592
+ error.call("simd element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
593
+ error.call("simd element type must be a numeric primitive") unless arguments.first.is_a?(Types::Primitive) && arguments.first.numeric?
594
+ error.call("simd lane count must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
595
+ error.call("simd lane count must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
596
+ if integer_type_argument?(arguments[1])
597
+ width_bytes = arguments.first.name == "double" || arguments.first.name == "long" || arguments.first.name == "ulong" ? arguments[1].value * 8 : arguments.first.name == "int" || arguments.first.name == "uint" || arguments.first.name == "float" ? arguments[1].value * 4 : arguments.first.name == "short" || arguments.first.name == "ushort" ? arguments[1].value * 2 : arguments[1].value
598
+ valid = [16, 32].include?(width_bytes)
599
+ error.call("simd width must be 128 or 256 bits, got #{width_bytes * 8}") unless valid
600
+ end
601
+ when "str_buffer"
602
+ error.call("str_buffer requires exactly one type argument") unless arguments.length == 1
603
+ error.call("str_buffer capacity must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments.first)
604
+ error.call("str_buffer capacity must be positive") if integer_type_argument?(arguments.first) && !arguments.first.value.positive?
605
+ when "Task"
606
+ error.call("Task requires exactly one type argument") unless arguments.length == 1
607
+ error.call("Task result type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
608
+ when "atomic"
609
+ error.call("atomic requires exactly one type argument") unless arguments.length == 1
610
+ arg = arguments.first
611
+ error.call("atomic type argument must be a type") if arg.is_a?(Types::LiteralTypeArg)
612
+ error.call("atomic type argument must be a primitive integer or bool") unless arg.is_a?(Types::Primitive) && (arg.integer? || arg.boolean?)
613
+ else
614
+ error.call("unknown generic type #{name}")
574
615
  end
575
- when "span"
576
- error.call("span requires exactly one type argument") unless arguments.length == 1
577
- error.call("span element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
578
- when "array"
579
- error.call("array requires exactly two type arguments") unless arguments.length == 2
580
- error.call("array element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
581
- error.call("array length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
582
- error.call("array length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
583
- when "SoA"
584
- error.call("SoA requires exactly two type arguments") unless arguments.length == 2
585
- error.call("SoA element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
586
- error.call("SoA element type must be a struct with fields") unless arguments.first.respond_to?(:fields) && arguments.first.fields.any?
587
- error.call("SoA length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
588
- error.call("SoA length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
589
- when "simd"
590
- error.call("simd requires exactly two type arguments") unless arguments.length == 2
591
- error.call("simd element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
592
- error.call("simd element type must be a numeric primitive") unless arguments.first.is_a?(Types::Primitive) && arguments.first.numeric?
593
- error.call("simd lane count must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
594
- error.call("simd lane count must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
595
- if integer_type_argument?(arguments[1])
596
- width_bytes = arguments.first.name == "double" || arguments.first.name == "long" || arguments.first.name == "ulong" ? arguments[1].value * 8 : arguments.first.name == "int" || arguments.first.name == "uint" || arguments.first.name == "float" ? arguments[1].value * 4 : arguments.first.name == "short" || arguments.first.name == "ushort" ? arguments[1].value * 2 : arguments[1].value
597
- valid = [16, 32].include?(width_bytes)
598
- error.call("simd width must be 128 or 256 bits, got #{width_bytes * 8}") unless valid
599
- end
600
- when "str_buffer"
601
- error.call("str_buffer requires exactly one type argument") unless arguments.length == 1
602
- error.call("str_buffer capacity must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments.first)
603
- error.call("str_buffer capacity must be positive") if integer_type_argument?(arguments.first) && !arguments.first.value.positive?
604
- when "Task"
605
- error.call("Task requires exactly one type argument") unless arguments.length == 1
606
- error.call("Task result type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
607
- when "atomic"
608
- error.call("atomic requires exactly one type argument") unless arguments.length == 1
609
- arg = arguments.first
610
- error.call("atomic type argument must be a type") if arg.is_a?(Types::LiteralTypeArg)
611
- error.call("atomic type argument must be a primitive integer or bool") unless arg.is_a?(Types::Primitive) && (arg.integer? || arg.boolean?)
612
- else
613
- error.call("unknown generic type #{name}")
614
616
  end
615
- end
616
617
 
617
- private
618
+ private
618
619
 
619
- def char_array_text_type?(type)
620
- return false unless array_type?(type)
620
+ def char_array_text_type?(type)
621
+ return false unless array_type?(type)
621
622
 
622
- element = array_element_type(type)
623
- element.is_a?(Types::Primitive) && element.name == "char"
624
- end
623
+ element = array_element_type(type)
624
+ element.is_a?(Types::Primitive) && element.name == "char"
625
+ end
625
626
 
626
- def str_buffer_type?(type)
627
- type.arguments.length == 1 && type.arguments.first.is_a?(Types::LiteralTypeArg) && type.arguments.first.value.is_a?(Integer)
628
- end
627
+ def str_buffer_type?(type)
628
+ type.arguments.length == 1 && type.arguments.first.is_a?(Types::LiteralTypeArg) && type.arguments.first.value.is_a?(Integer)
629
+ end
629
630
 
630
- def array_type?(type)
631
- type.arguments.length == 2 && type.arguments[1].is_a?(Types::LiteralTypeArg) && type.arguments[1].value.is_a?(Integer)
632
- end
631
+ def array_type?(type)
632
+ type.arguments.length == 2 && type.arguments[1].is_a?(Types::LiteralTypeArg) && type.arguments[1].value.is_a?(Integer)
633
+ end
633
634
 
634
- def soa_type?(type)
635
- type.is_a?(Types::SoA)
636
- end
635
+ def soa_type?(type)
636
+ type.is_a?(Types::SoA)
637
+ end
637
638
 
638
- def simd_type?(type)
639
- type.is_a?(Types::Simd)
640
- end
639
+ def simd_type?(type)
640
+ type.is_a?(Types::Simd)
641
+ end
641
642
 
642
- def array_length(type)
643
- type.arguments[1].value
644
- end
643
+ def array_length(type)
644
+ type.arguments[1].value
645
+ end
645
646
 
646
- def array_element_type(type)
647
- type.arguments.first
647
+ def array_element_type(type)
648
+ type.arguments.first
649
+ end
648
650
  end
649
651
  end
650
652
  end