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.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/c_backend/feature_detection.rb +27 -55
- data/lib/milk_tea/core/c_backend/format_helpers.rb +551 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +0 -542
- data/lib/milk_tea/core/c_backend/type_collectors.rb +51 -204
- data/lib/milk_tea/core/c_backend.rb +2 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +1 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +147 -141
- data/lib/milk_tea/core/lowering/block.rb +759 -725
- data/lib/milk_tea/core/lowering/expressions.rb +94 -0
- data/lib/milk_tea/core/lowering/loops.rb +49 -0
- data/lib/milk_tea/core/lowering/resolve.rb +221 -214
- data/lib/milk_tea/core/lowering/utils.rb +0 -222
- data/lib/milk_tea/core/module_loader.rb +29 -48
- data/lib/milk_tea/core/parser/declarations.rb +2 -2
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +3 -120
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +116 -113
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +346 -343
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +37 -12
- data/lib/milk_tea/core/types/predicates.rb +501 -499
- data/lib/milk_tea/core/types/visitor.rb +1 -1
- metadata +3 -2
|
@@ -1,650 +1,652 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
49
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
99
|
-
return
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
return true if expected_type.name == "double"
|
|
77
|
+
actual_type.target_type == expected_type
|
|
78
|
+
end
|
|
104
79
|
|
|
105
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
end
|
|
92
|
+
value_fits_integer_type?(integer_value, expected_type)
|
|
93
|
+
end
|
|
116
94
|
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
121
|
-
|
|
99
|
+
if expected_type.name == "float"
|
|
100
|
+
return value.abs <= (1 << 24) if value.is_a?(Integer)
|
|
122
101
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
130
|
-
|
|
106
|
+
false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
131
109
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
114
|
+
integer_value = value.to_i
|
|
115
|
+
integer_value.to_f == value ? integer_value : nil
|
|
116
|
+
end
|
|
139
117
|
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
145
|
-
|
|
121
|
+
width = expected_type.integer_width
|
|
122
|
+
return false if width.nil?
|
|
146
123
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
return false unless actual_type.numeric? && expected_type.numeric?
|
|
130
|
+
value >= min_value && value <= max_value
|
|
131
|
+
end
|
|
154
132
|
|
|
155
|
-
|
|
156
|
-
|
|
133
|
+
def exactly_representable_float32?(value)
|
|
134
|
+
[value].pack("f").unpack1("f") == value
|
|
135
|
+
end
|
|
157
136
|
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
165
|
-
return expected_type.integer_width >= actual_type.integer_width
|
|
145
|
+
false
|
|
166
146
|
end
|
|
167
147
|
|
|
168
|
-
|
|
148
|
+
def char_type?(type)
|
|
149
|
+
type.is_a?(Types::Primitive) && type.name == "char"
|
|
150
|
+
end
|
|
169
151
|
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
174
|
-
|
|
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
|
-
|
|
178
|
-
|
|
159
|
+
false
|
|
160
|
+
end
|
|
179
161
|
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
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
|
-
|
|
196
|
-
|
|
171
|
+
expected_type.signed_integer? && expected_type.integer_width > actual_type.integer_width
|
|
172
|
+
end
|
|
197
173
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
206
|
-
|
|
178
|
+
lossless_external_integer_compatibility?(actual_type, expected_type)
|
|
179
|
+
end
|
|
207
180
|
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
212
|
-
|
|
186
|
+
def contextual_int_to_float_target?(type)
|
|
187
|
+
type.is_a?(Types::Primitive) && type.float?
|
|
188
|
+
end
|
|
213
189
|
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
return true if str_buffer_type?(public_type)
|
|
196
|
+
pointee_type(actual_type) == pointee_type(expected_type)
|
|
197
|
+
end
|
|
220
198
|
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
-
|
|
230
|
-
|
|
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
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
247
|
-
return foreign_identity_projection_cast_compatible?(actual_type.base, expected_type.base)
|
|
222
|
+
false
|
|
248
223
|
end
|
|
249
224
|
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
|
|
230
|
+
foreign_identity_projection_compatible?(public_type, boundary_type)
|
|
231
|
+
end
|
|
254
232
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
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
|
|
262
|
-
|
|
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
|
-
|
|
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
|
-
|
|
270
|
-
|
|
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
|
-
|
|
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
|
-
|
|
278
|
-
|
|
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
|
-
|
|
282
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
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
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
305
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
end
|
|
305
|
+
foreign_opaque_c_name(actual_type) == foreign_opaque_c_name(expected_type)
|
|
306
|
+
end
|
|
310
307
|
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
317
|
-
|
|
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
|
-
|
|
320
|
-
|
|
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
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
331
|
-
|
|
331
|
+
key = [actual_type.object_id, expected_type.object_id]
|
|
332
|
+
return true if seen[key]
|
|
332
333
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
339
|
-
|
|
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
|
-
|
|
344
|
-
|
|
344
|
+
def foreign_external_layout_field_compatible?(actual_type, expected_type, seen)
|
|
345
|
+
return true if actual_type == expected_type
|
|
345
346
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
355
|
-
|
|
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
|
-
|
|
358
|
-
|
|
358
|
+
return foreign_external_layout_field_compatible?(array_element_type(actual_type), array_element_type(expected_type), seen)
|
|
359
|
+
end
|
|
359
360
|
|
|
360
|
-
|
|
361
|
-
|
|
361
|
+
foreign_external_layout_compatible?(actual_type, expected_type, seen)
|
|
362
|
+
end
|
|
362
363
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
def void_pointer_type?(type)
|
|
365
|
+
pointer_type?(type) && type.arguments.first == Types::Registry.primitive("void")
|
|
366
|
+
end
|
|
366
367
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
|
|
376
|
-
|
|
376
|
+
native_flat.zip(foreign_flat).all? { |nf, ff| nf == ff }
|
|
377
|
+
end
|
|
377
378
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
|
|
394
|
+
def char_pointer_type?(type)
|
|
395
|
+
pointer_type?(type) && type.arguments.first == Types::Registry.primitive("char")
|
|
396
|
+
end
|
|
396
397
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
def opaque_type?(type)
|
|
399
|
+
type.is_a?(Types::Opaque)
|
|
400
|
+
end
|
|
400
401
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
def pointer_type?(type)
|
|
403
|
+
mutable_pointer_type?(type) || const_pointer_type?(type) || own_type?(type)
|
|
404
|
+
end
|
|
404
405
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
406
|
+
def mutable_pointer_type?(type)
|
|
407
|
+
type.is_a?(Types::GenericInstance) && type.name == "ptr" && type.arguments.length == 1
|
|
408
|
+
end
|
|
408
409
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
414
|
+
def own_type?(type)
|
|
415
|
+
type.is_a?(Types::GenericInstance) && type.name == "own" && type.arguments.length == 1
|
|
416
|
+
end
|
|
416
417
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
418
|
+
def owned_referent_type(type)
|
|
419
|
+
type.arguments.first if own_type?(type)
|
|
420
|
+
end
|
|
420
421
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
426
|
+
def atomic_type?(type)
|
|
427
|
+
type.is_a?(Types::GenericInstance) && type.name == "atomic" && type.arguments.length == 1
|
|
428
|
+
end
|
|
428
429
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
430
|
+
def atomic_element_type(type)
|
|
431
|
+
type.arguments.first
|
|
432
|
+
end
|
|
432
433
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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
|
-
|
|
438
|
-
|
|
438
|
+
def ref_lifetime(type)
|
|
439
|
+
return unless type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 2
|
|
439
440
|
|
|
440
|
-
|
|
441
|
-
|
|
441
|
+
type.arguments.first
|
|
442
|
+
end
|
|
442
443
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
444
|
+
def dyn_type?(type)
|
|
445
|
+
type.is_a?(Types::Dyn)
|
|
446
|
+
end
|
|
446
447
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
448
|
+
def task_type?(type)
|
|
449
|
+
type.is_a?(Types::Task)
|
|
450
|
+
end
|
|
450
451
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
456
|
-
|
|
457
|
-
|
|
456
|
+
def proc_type?(type)
|
|
457
|
+
type.is_a?(Types::Proc)
|
|
458
|
+
end
|
|
458
459
|
|
|
459
|
-
|
|
460
|
-
|
|
460
|
+
def pointee_type(type)
|
|
461
|
+
return unless pointer_type?(type)
|
|
461
462
|
|
|
462
|
-
|
|
463
|
-
|
|
463
|
+
type.arguments.first
|
|
464
|
+
end
|
|
464
465
|
|
|
465
|
-
|
|
466
|
-
|
|
466
|
+
def referenced_type(type)
|
|
467
|
+
return unless ref_type?(type)
|
|
467
468
|
|
|
468
|
-
|
|
469
|
-
|
|
469
|
+
type.arguments.length == 1 ? type.arguments.first : type.arguments[1]
|
|
470
|
+
end
|
|
470
471
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
472
|
+
def const_pointer_to(type)
|
|
473
|
+
Types::Registry.generic_instance("const_ptr", [type])
|
|
474
|
+
end
|
|
474
475
|
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
|
|
479
|
-
|
|
479
|
+
actual_count == function_type.params.length
|
|
480
|
+
end
|
|
480
481
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
def string_builder_ref_type?(type)
|
|
497
|
+
ref_type?(type) && string_builder_type?(referenced_type(type))
|
|
498
|
+
end
|
|
498
499
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
520
|
+
def contains_type_var?(type)
|
|
521
|
+
visitor = ContainsTypeVarVisitor.new
|
|
522
|
+
visitor.visit(type)
|
|
523
|
+
visitor.found?
|
|
524
|
+
end
|
|
524
525
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
-
|
|
530
|
-
|
|
530
|
+
nil
|
|
531
|
+
end
|
|
531
532
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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
|
-
|
|
537
|
-
|
|
537
|
+
Types::Registry.generic_instance("ref", [element_type])
|
|
538
|
+
end
|
|
538
539
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
540
|
+
def collection_loop_ref_element_type?(type)
|
|
541
|
+
type.is_a?(Types::Struct)
|
|
542
|
+
end
|
|
542
543
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
544
|
+
def integer_type_argument?(argument)
|
|
545
|
+
argument.is_a?(Types::LiteralTypeArg) && argument.value.is_a?(Integer)
|
|
546
|
+
end
|
|
546
547
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
548
|
+
def generic_integer_type_argument?(argument)
|
|
549
|
+
integer_type_argument?(argument) || argument.is_a?(Types::TypeVar)
|
|
550
|
+
end
|
|
550
551
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
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
|
-
|
|
618
|
+
private
|
|
618
619
|
|
|
619
|
-
|
|
620
|
-
|
|
620
|
+
def char_array_text_type?(type)
|
|
621
|
+
return false unless array_type?(type)
|
|
621
622
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
623
|
+
element = array_element_type(type)
|
|
624
|
+
element.is_a?(Types::Primitive) && element.name == "char"
|
|
625
|
+
end
|
|
625
626
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
|
|
635
|
-
|
|
636
|
-
|
|
635
|
+
def soa_type?(type)
|
|
636
|
+
type.is_a?(Types::SoA)
|
|
637
|
+
end
|
|
637
638
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
639
|
+
def simd_type?(type)
|
|
640
|
+
type.is_a?(Types::Simd)
|
|
641
|
+
end
|
|
641
642
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
643
|
+
def array_length(type)
|
|
644
|
+
type.arguments[1].value
|
|
645
|
+
end
|
|
645
646
|
|
|
646
|
-
|
|
647
|
-
|
|
647
|
+
def array_element_type(type)
|
|
648
|
+
type.arguments.first
|
|
649
|
+
end
|
|
648
650
|
end
|
|
649
651
|
end
|
|
650
652
|
end
|