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,423 +1,426 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
class SemanticAnalyzer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
class SemanticAnalyzer
|
|
5
|
+
class Checker
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def infer_receiver_type_substitutions(binding, receiver_type)
|
|
9
|
+
declared_receiver_type = binding.declared_receiver_type
|
|
10
|
+
return {} unless declared_receiver_type
|
|
11
|
+
case declared_receiver_type
|
|
12
|
+
when Types::Nullable
|
|
13
|
+
unless receiver_type.is_a?(Types::Nullable)
|
|
14
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
infer_receiver_type_substitutions(
|
|
18
|
+
binding.with(declared_receiver_type: declared_receiver_type.base),
|
|
19
|
+
receiver_type.base,
|
|
20
|
+
)
|
|
21
|
+
when Types::StructInstance
|
|
22
|
+
return {} unless declared_receiver_type.definition.is_a?(Types::GenericStructDefinition)
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
unless receiver_type.is_a?(Types::StructInstance) && receiver_type.definition == declared_receiver_type.definition
|
|
25
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
26
|
+
end
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
declared_receiver_type.definition.type_params.zip(receiver_type.arguments).to_h
|
|
29
|
+
when Types::VariantInstance
|
|
30
|
+
return {} unless declared_receiver_type.definition.is_a?(Types::GenericVariantDefinition)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
unless receiver_type.is_a?(Types::VariantInstance) && receiver_type.definition == declared_receiver_type.definition
|
|
33
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
34
|
+
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
declared_receiver_type.definition.type_params.zip(receiver_type.arguments).to_h
|
|
37
|
+
when Types::GenericInstance
|
|
38
|
+
unless receiver_type.is_a?(Types::GenericInstance) && receiver_type.name == declared_receiver_type.name && receiver_type.arguments.length == declared_receiver_type.arguments.length
|
|
39
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
40
|
+
end
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
declared_receiver_type.arguments.zip(receiver_type.arguments).each_with_object({}) do |(declared_argument, actual_argument), substitutions|
|
|
43
|
+
if declared_argument.is_a?(Types::TypeVar)
|
|
44
|
+
substitutions[declared_argument.name] = actual_argument
|
|
45
|
+
elsif declared_argument != actual_argument
|
|
46
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
when Types::Span
|
|
50
|
+
return {} unless receiver_type.is_a?(Types::Span)
|
|
51
|
+
|
|
52
|
+
substitutions = {}
|
|
53
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
54
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
55
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
45
56
|
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
46
57
|
end
|
|
58
|
+
substitutions
|
|
59
|
+
when Types::Task
|
|
60
|
+
return {} unless receiver_type.is_a?(Types::Task)
|
|
61
|
+
|
|
62
|
+
substitutions = {}
|
|
63
|
+
if declared_receiver_type.result_type.is_a?(Types::TypeVar)
|
|
64
|
+
substitutions[declared_receiver_type.result_type.name] = receiver_type.result_type
|
|
65
|
+
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
66
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
67
|
+
end
|
|
68
|
+
substitutions
|
|
69
|
+
when Types::SoA
|
|
70
|
+
return {} unless receiver_type.is_a?(Types::SoA)
|
|
71
|
+
|
|
72
|
+
substitutions = {}
|
|
73
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
74
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
75
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
76
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
77
|
+
end
|
|
78
|
+
substitutions
|
|
79
|
+
when Types::Simd
|
|
80
|
+
return {} unless receiver_type.is_a?(Types::Simd)
|
|
81
|
+
|
|
82
|
+
substitutions = {}
|
|
83
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
84
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
85
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
86
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
87
|
+
end
|
|
88
|
+
substitutions
|
|
89
|
+
else
|
|
90
|
+
{}
|
|
47
91
|
end
|
|
48
|
-
when Types::Span
|
|
49
|
-
return {} unless receiver_type.is_a?(Types::Span)
|
|
50
|
-
|
|
51
|
-
substitutions = {}
|
|
52
|
-
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
53
|
-
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
54
|
-
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
55
|
-
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
56
|
-
end
|
|
57
|
-
substitutions
|
|
58
|
-
when Types::Task
|
|
59
|
-
return {} unless receiver_type.is_a?(Types::Task)
|
|
60
|
-
|
|
61
|
-
substitutions = {}
|
|
62
|
-
if declared_receiver_type.result_type.is_a?(Types::TypeVar)
|
|
63
|
-
substitutions[declared_receiver_type.result_type.name] = receiver_type.result_type
|
|
64
|
-
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
65
|
-
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
66
|
-
end
|
|
67
|
-
substitutions
|
|
68
|
-
when Types::SoA
|
|
69
|
-
return {} unless receiver_type.is_a?(Types::SoA)
|
|
70
|
-
|
|
71
|
-
substitutions = {}
|
|
72
|
-
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
73
|
-
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
74
|
-
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
75
|
-
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
76
|
-
end
|
|
77
|
-
substitutions
|
|
78
|
-
when Types::Simd
|
|
79
|
-
return {} unless receiver_type.is_a?(Types::Simd)
|
|
80
|
-
|
|
81
|
-
substitutions = {}
|
|
82
|
-
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
83
|
-
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
84
|
-
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
85
|
-
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
86
|
-
end
|
|
87
|
-
substitutions
|
|
88
|
-
else
|
|
89
|
-
{}
|
|
90
92
|
end
|
|
91
|
-
end
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
def callable_receiver_type_for_specialization(callee, scopes:)
|
|
95
|
+
return unless callee.is_a?(AST::MemberAccess)
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
resolve_type_expression(callee.receiver)
|
|
98
|
+
end
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
def resolve_type_member(type, name)
|
|
101
|
+
case type
|
|
102
|
+
when Types::Enum, Types::Flags
|
|
103
|
+
type.member(name)
|
|
104
|
+
when Types::Variant
|
|
105
|
+
return type if type.arm_names.include?(name) && !type.has_payload?(name)
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
nil
|
|
108
|
+
end
|
|
107
109
|
end
|
|
108
|
-
end
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def resolve_specialized_callable_binding(expression, scopes:)
|
|
115
|
-
callable_kind = :function
|
|
116
|
-
receiver = nil
|
|
117
|
-
receiver_type = nil
|
|
118
|
-
binding = case expression.callee
|
|
119
|
-
when AST::Identifier
|
|
120
|
-
@ctx.top_level_functions[expression.callee.name]
|
|
121
|
-
when AST::MemberAccess
|
|
122
|
-
if expression.callee.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.callee.receiver.name)
|
|
123
|
-
imported_module = @ctx.imports.fetch(expression.callee.receiver.name)
|
|
124
|
-
imported_function = imported_module.functions[expression.callee.member]
|
|
125
|
-
if imported_function.nil? && imported_module.private_function?(expression.callee.member)
|
|
126
|
-
raise_sema_error("#{expression.callee.receiver.name}.#{expression.callee.member} is private to module #{imported_module.name}")
|
|
127
|
-
end
|
|
111
|
+
def function_type_for_name(name)
|
|
112
|
+
@ctx.top_level_functions.fetch(name).type
|
|
113
|
+
end
|
|
128
114
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
115
|
+
def resolve_specialized_callable_binding(expression, scopes:)
|
|
116
|
+
callable_kind = :function
|
|
117
|
+
receiver = nil
|
|
118
|
+
receiver_type = nil
|
|
119
|
+
binding = case expression.callee
|
|
120
|
+
when AST::Identifier
|
|
121
|
+
@ctx.top_level_functions[expression.callee.name]
|
|
122
|
+
when AST::MemberAccess
|
|
123
|
+
if expression.callee.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.callee.receiver.name)
|
|
124
|
+
imported_module = @ctx.imports.fetch(expression.callee.receiver.name)
|
|
125
|
+
imported_function = imported_module.functions[expression.callee.member]
|
|
126
|
+
if imported_function.nil? && imported_module.private_function?(expression.callee.member)
|
|
127
|
+
raise_sema_error("#{expression.callee.receiver.name}.#{expression.callee.member} is private to module #{imported_module.name}")
|
|
138
128
|
end
|
|
139
129
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
130
|
+
imported_function
|
|
131
|
+
elsif (type_expr = resolve_type_expression(expression.callee.receiver))
|
|
132
|
+
associated_function = lookup_method(type_expr, expression.callee.member)
|
|
133
|
+
if associated_function&.type&.receiver_type.nil?
|
|
134
|
+
receiver_type = type_expr
|
|
135
|
+
associated_function
|
|
136
|
+
else
|
|
137
|
+
if (imported_module = imported_module_with_private_method(type_expr, expression.callee.member))
|
|
138
|
+
raise_sema_error("#{type_expr}.#{expression.callee.member} is private to module #{imported_module.name}")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
nil
|
|
152
142
|
end
|
|
143
|
+
else
|
|
144
|
+
receiver_type = infer_method_receiver_type(expression.callee.receiver, scopes:, member_name: expression.callee.member)
|
|
145
|
+
method = lookup_method(receiver_type, expression.callee.member)
|
|
146
|
+
if method
|
|
147
|
+
callable_kind = :method
|
|
148
|
+
receiver = expression.callee.receiver
|
|
149
|
+
method
|
|
150
|
+
else
|
|
151
|
+
if (imported_module = imported_module_with_private_method(receiver_type, expression.callee.member))
|
|
152
|
+
raise_sema_error("#{receiver_type}.#{expression.callee.member} is private to module #{imported_module.name}")
|
|
153
|
+
end
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
nil
|
|
156
|
+
end
|
|
155
157
|
end
|
|
156
158
|
end
|
|
157
|
-
|
|
158
|
-
return nil unless binding
|
|
159
|
-
|
|
160
|
-
type_arguments = resolve_specialization_type_arguments(expression)
|
|
161
|
-
[callable_kind, instantiate_function_binding_with_receiver(binding, type_arguments, receiver_type:), receiver]
|
|
162
|
-
end
|
|
159
|
+
return nil unless binding
|
|
163
160
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
resolve_type_argument(argument.value, type_params: current_type_params)
|
|
161
|
+
type_arguments = resolve_specialization_type_arguments(expression)
|
|
162
|
+
[callable_kind, instantiate_function_binding_with_receiver(binding, type_arguments, receiver_type:), receiver]
|
|
167
163
|
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def specialize_function_binding(binding, arguments, scopes:, receiver_type: nil)
|
|
171
|
-
return binding if binding.type_params.empty?
|
|
172
164
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def instantiate_function_binding_with_receiver(binding, explicit_type_arguments, receiver_type: nil)
|
|
178
|
-
if binding.type_params.empty?
|
|
179
|
-
raise_sema_error("function #{binding.name} is not generic and cannot be specialized")
|
|
165
|
+
def resolve_specialization_type_arguments(expression)
|
|
166
|
+
expression.arguments.map do |argument|
|
|
167
|
+
resolve_type_argument(argument.value, type_params: current_type_params)
|
|
168
|
+
end
|
|
180
169
|
end
|
|
181
170
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
171
|
+
def specialize_function_binding(binding, arguments, scopes:, receiver_type: nil)
|
|
172
|
+
return binding if binding.type_params.empty?
|
|
173
|
+
|
|
174
|
+
type_arguments = infer_function_type_arguments(binding, arguments, scopes:, receiver_type:)
|
|
175
|
+
instantiate_function_binding(binding, type_arguments)
|
|
186
176
|
end
|
|
187
177
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
def instantiate_function_binding_with_receiver(binding, explicit_type_arguments, receiver_type: nil)
|
|
179
|
+
if binding.type_params.empty?
|
|
180
|
+
raise_sema_error("function #{binding.name} is not generic and cannot be specialized")
|
|
181
|
+
end
|
|
191
182
|
|
|
192
|
-
|
|
193
|
-
|
|
183
|
+
receiver_substitutions = infer_receiver_type_substitutions(binding, receiver_type)
|
|
184
|
+
remaining_type_params = binding.type_params.reject { |name| receiver_substitutions.key?(name) }
|
|
185
|
+
unless remaining_type_params.length == explicit_type_arguments.length
|
|
186
|
+
raise_sema_error("function #{binding.name} expects #{remaining_type_params.length} type arguments, got #{explicit_type_arguments.length}")
|
|
187
|
+
end
|
|
194
188
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
189
|
+
substitutions = receiver_substitutions.dup
|
|
190
|
+
remaining_type_params.zip(explicit_type_arguments).each do |name, type_argument|
|
|
191
|
+
raise_sema_error("generic function #{binding.name} cannot be instantiated with ref types") if contains_ref_type?(type_argument)
|
|
198
192
|
|
|
199
|
-
|
|
200
|
-
|
|
193
|
+
substitutions[name] = type_argument
|
|
194
|
+
end
|
|
201
195
|
|
|
202
|
-
|
|
203
|
-
|
|
196
|
+
type_arguments = binding.type_params.map do |name|
|
|
197
|
+
inferred = substitutions[name]
|
|
198
|
+
raise_sema_error("cannot infer type argument #{name} for function #{binding.name}") unless inferred
|
|
204
199
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
raise_sema_error("function #{binding.name} is not generic and cannot be specialized")
|
|
208
|
-
end
|
|
200
|
+
inferred
|
|
201
|
+
end
|
|
209
202
|
|
|
210
|
-
|
|
211
|
-
raise_sema_error("function #{binding.name} expects #{binding.type_params.length} type arguments, got #{type_arguments.length}")
|
|
203
|
+
instantiate_function_binding(binding, type_arguments)
|
|
212
204
|
end
|
|
213
205
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
206
|
+
def instantiate_function_binding(binding, type_arguments)
|
|
207
|
+
if binding.type_params.empty?
|
|
208
|
+
raise_sema_error("function #{binding.name} is not generic and cannot be specialized")
|
|
209
|
+
end
|
|
217
210
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
substitutions = binding.type_params.zip(type_arguments).to_h
|
|
222
|
-
validate_function_type_param_constraints!(binding, substitutions)
|
|
223
|
-
type = substitute_type(binding.type, substitutions)
|
|
224
|
-
body_params = binding.body_params.map { |param| substitute_value_binding(param, substitutions) }
|
|
225
|
-
validate_specialized_function_binding!(binding.name, type, body_params)
|
|
226
|
-
|
|
227
|
-
instance = FunctionBinding.new(
|
|
228
|
-
name: binding.name,
|
|
229
|
-
type:,
|
|
230
|
-
body_params:,
|
|
231
|
-
body_return_type: substitute_type(binding.body_return_type, substitutions),
|
|
232
|
-
ast: binding.ast,
|
|
233
|
-
external: binding.external,
|
|
234
|
-
async: binding.async,
|
|
235
|
-
type_params: [].freeze,
|
|
236
|
-
type_param_constraints: {}.freeze,
|
|
237
|
-
instances: {},
|
|
238
|
-
type_arguments: key,
|
|
239
|
-
owner: binding.owner,
|
|
240
|
-
specialization_owner: @current_specialization_owner || (binding.owner == self ? nil : self),
|
|
241
|
-
type_substitutions: substitutions.freeze,
|
|
242
|
-
declared_receiver_type: binding.declared_receiver_type ? substitute_type(binding.declared_receiver_type, substitutions) : nil,
|
|
243
|
-
)
|
|
244
|
-
binding.instances[key] = instance
|
|
245
|
-
end
|
|
211
|
+
unless binding.type_params.length == type_arguments.length
|
|
212
|
+
raise_sema_error("function #{binding.name} expects #{binding.type_params.length} type arguments, got #{type_arguments.length}")
|
|
213
|
+
end
|
|
246
214
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
raise_sema_error("cannot infer type argument #{name} for function #{binding.name}") unless actual_type
|
|
215
|
+
if type_arguments.any? { |type_argument| contains_ref_type?(type_argument) }
|
|
216
|
+
raise_sema_error("generic function #{binding.name} cannot be instantiated with ref types")
|
|
217
|
+
end
|
|
251
218
|
|
|
252
|
-
|
|
219
|
+
key = type_arguments.freeze
|
|
220
|
+
return binding.instances.fetch(key) if binding.instances.key?(key)
|
|
221
|
+
|
|
222
|
+
substitutions = binding.type_params.zip(type_arguments).to_h
|
|
223
|
+
validate_function_type_param_constraints!(binding, substitutions)
|
|
224
|
+
type = substitute_type(binding.type, substitutions)
|
|
225
|
+
body_params = binding.body_params.map { |param| substitute_value_binding(param, substitutions) }
|
|
226
|
+
validate_specialized_function_binding!(binding.name, type, body_params)
|
|
227
|
+
|
|
228
|
+
instance = FunctionBinding.new(
|
|
229
|
+
name: binding.name,
|
|
230
|
+
type:,
|
|
231
|
+
body_params:,
|
|
232
|
+
body_return_type: substitute_type(binding.body_return_type, substitutions),
|
|
233
|
+
ast: binding.ast,
|
|
234
|
+
external: binding.external,
|
|
235
|
+
async: binding.async,
|
|
236
|
+
type_params: [].freeze,
|
|
237
|
+
type_param_constraints: {}.freeze,
|
|
238
|
+
instances: {},
|
|
239
|
+
type_arguments: key,
|
|
240
|
+
owner: binding.owner,
|
|
241
|
+
specialization_owner: @current_specialization_owner || (binding.owner == self ? nil : self),
|
|
242
|
+
type_substitutions: substitutions.freeze,
|
|
243
|
+
declared_receiver_type: binding.declared_receiver_type ? substitute_type(binding.declared_receiver_type, substitutions) : nil,
|
|
244
|
+
)
|
|
245
|
+
binding.instances[key] = instance
|
|
253
246
|
end
|
|
254
|
-
end
|
|
255
247
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
end
|
|
248
|
+
def validate_function_type_param_constraints!(binding, substitutions)
|
|
249
|
+
binding.type_param_constraints.each do |name, constraints|
|
|
250
|
+
actual_type = substitutions[name]
|
|
251
|
+
raise_sema_error("cannot infer type argument #{name} for function #{binding.name}") unless actual_type
|
|
261
252
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
argument = arguments.fetch(index)
|
|
265
|
-
candidate_type = substitute_type(parameter.type, substitutions)
|
|
266
|
-
expected_argument_type = if callable_type?(candidate_type)
|
|
267
|
-
candidate_type
|
|
268
|
-
elsif contains_type_var?(candidate_type)
|
|
269
|
-
nil
|
|
270
|
-
else
|
|
271
|
-
candidate_type
|
|
272
|
-
end
|
|
273
|
-
actual_type = foreign_argument_actual_type(parameter, argument, scopes:, function_name: binding.name, expected_type: expected_argument_type)
|
|
274
|
-
collect_type_substitutions(parameter.type, actual_type, substitutions, binding.name)
|
|
253
|
+
validate_type_param_constraint_binding!(constraints, actual_type, context: "function #{binding.name}")
|
|
254
|
+
end
|
|
275
255
|
end
|
|
276
256
|
|
|
277
|
-
binding
|
|
278
|
-
|
|
279
|
-
|
|
257
|
+
def infer_function_type_arguments(binding, arguments, scopes:, receiver_type: nil)
|
|
258
|
+
expected_params = binding.type.params
|
|
259
|
+
unless call_arity_matches?(binding.type, arguments.length)
|
|
260
|
+
raise_sema_error(arity_error_message(binding.type, binding.name, arguments.length))
|
|
261
|
+
end
|
|
280
262
|
|
|
281
|
-
|
|
263
|
+
substitutions = infer_receiver_type_substitutions(binding, receiver_type)
|
|
264
|
+
expected_params.each_with_index do |parameter, index|
|
|
265
|
+
argument = arguments.fetch(index)
|
|
266
|
+
candidate_type = substitute_type(parameter.type, substitutions)
|
|
267
|
+
expected_argument_type = if callable_type?(candidate_type)
|
|
268
|
+
candidate_type
|
|
269
|
+
elsif contains_type_var?(candidate_type)
|
|
270
|
+
nil
|
|
271
|
+
else
|
|
272
|
+
candidate_type
|
|
273
|
+
end
|
|
274
|
+
actual_type = foreign_argument_actual_type(parameter, argument, scopes:, function_name: binding.name, expected_type: expected_argument_type)
|
|
275
|
+
collect_type_substitutions(parameter.type, actual_type, substitutions, binding.name)
|
|
276
|
+
end
|
|
282
277
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
278
|
+
binding.type_params.map do |name|
|
|
279
|
+
inferred = substitutions[name]
|
|
280
|
+
raise_sema_error("cannot infer type argument #{name} for function #{binding.name}") unless inferred
|
|
286
281
|
|
|
287
|
-
|
|
288
|
-
case pattern_type
|
|
289
|
-
when Types::TypeVar
|
|
290
|
-
existing = substitutions[pattern_type.name]
|
|
291
|
-
if existing && existing != actual_type
|
|
292
|
-
raise_sema_error("conflicting type argument #{pattern_type.name} for function #{function_name}: got #{existing} and #{actual_type}")
|
|
293
|
-
end
|
|
282
|
+
raise_sema_error("generic function #{binding.name} cannot be instantiated with ref types") if contains_ref_type?(inferred)
|
|
294
283
|
|
|
295
|
-
|
|
296
|
-
when Types::Nullable
|
|
297
|
-
candidate = actual_type.is_a?(Types::Nullable) ? actual_type.base : actual_type
|
|
298
|
-
collect_type_substitutions(pattern_type.base, candidate, substitutions, function_name)
|
|
299
|
-
when Types::GenericInstance
|
|
300
|
-
if ref_type?(pattern_type) && !ref_type?(actual_type)
|
|
301
|
-
collect_type_substitutions(referenced_type(pattern_type), actual_type, substitutions, function_name)
|
|
302
|
-
return
|
|
284
|
+
inferred
|
|
303
285
|
end
|
|
286
|
+
end
|
|
304
287
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
288
|
+
def collect_type_substitutions(pattern_type, actual_type, substitutions, function_name)
|
|
289
|
+
case pattern_type
|
|
290
|
+
when Types::TypeVar
|
|
291
|
+
existing = substitutions[pattern_type.name]
|
|
292
|
+
if existing && existing != actual_type
|
|
293
|
+
raise_sema_error("conflicting type argument #{pattern_type.name} for function #{function_name}: got #{existing} and #{actual_type}")
|
|
294
|
+
end
|
|
309
295
|
|
|
310
|
-
|
|
311
|
-
|
|
296
|
+
substitutions[pattern_type.name] ||= actual_type
|
|
297
|
+
when Types::Nullable
|
|
298
|
+
candidate = actual_type.is_a?(Types::Nullable) ? actual_type.base : actual_type
|
|
299
|
+
collect_type_substitutions(pattern_type.base, candidate, substitutions, function_name)
|
|
300
|
+
when Types::GenericInstance
|
|
301
|
+
if ref_type?(pattern_type) && !ref_type?(actual_type)
|
|
302
|
+
collect_type_substitutions(referenced_type(pattern_type), actual_type, substitutions, function_name)
|
|
303
|
+
return
|
|
304
|
+
end
|
|
312
305
|
|
|
313
|
-
|
|
314
|
-
|
|
306
|
+
if own_type?(actual_type) && (mutable_pointer_type?(pattern_type) || const_pointer_type?(pattern_type))
|
|
307
|
+
collect_type_substitutions(pointee_type(pattern_type), owned_referent_type(actual_type), substitutions, function_name)
|
|
308
|
+
return
|
|
309
|
+
end
|
|
315
310
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
when Types::VariantInstance
|
|
319
|
-
return unless actual_type.is_a?(Types::VariantInstance)
|
|
320
|
-
return unless actual_type.definition == pattern_type.definition || (actual_type.name == pattern_type.name && actual_type.arguments.length == pattern_type.arguments.length)
|
|
311
|
+
return unless actual_type.is_a?(Types::GenericInstance)
|
|
312
|
+
return unless actual_type.name == pattern_type.name && actual_type.arguments.length == pattern_type.arguments.length
|
|
321
313
|
|
|
322
|
-
|
|
323
|
-
|
|
314
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
315
|
+
next if expected_argument.is_a?(Types::LiteralTypeArg)
|
|
324
316
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
collect_type_substitutions(pattern_type.element_type, actual_type.element_type, substitutions, function_name)
|
|
331
|
-
when Types::Task
|
|
332
|
-
return unless actual_type.is_a?(Types::Task)
|
|
333
|
-
|
|
334
|
-
collect_type_substitutions(pattern_type.result_type, actual_type.result_type, substitutions, function_name)
|
|
335
|
-
when Types::Proc
|
|
336
|
-
if task_root_proc_type?(pattern_type) && actual_type.is_a?(Types::Task)
|
|
337
|
-
collect_type_substitutions(pattern_type.return_type, actual_type, substitutions, function_name)
|
|
338
|
-
return
|
|
339
|
-
end
|
|
317
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
318
|
+
end
|
|
319
|
+
when Types::VariantInstance
|
|
320
|
+
return unless actual_type.is_a?(Types::VariantInstance)
|
|
321
|
+
return unless actual_type.definition == pattern_type.definition || (actual_type.name == pattern_type.name && actual_type.arguments.length == pattern_type.arguments.length)
|
|
340
322
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
return unless actual_type.params.length == pattern_type.params.length
|
|
323
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
324
|
+
next if expected_argument.is_a?(Types::LiteralTypeArg)
|
|
344
325
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
326
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
327
|
+
end
|
|
328
|
+
when Types::Span
|
|
329
|
+
return unless actual_type.is_a?(Types::Span)
|
|
330
|
+
|
|
331
|
+
collect_type_substitutions(pattern_type.element_type, actual_type.element_type, substitutions, function_name)
|
|
332
|
+
when Types::Task
|
|
333
|
+
return unless actual_type.is_a?(Types::Task)
|
|
334
|
+
|
|
335
|
+
collect_type_substitutions(pattern_type.result_type, actual_type.result_type, substitutions, function_name)
|
|
336
|
+
when Types::Proc
|
|
337
|
+
if task_root_proc_type?(pattern_type) && actual_type.is_a?(Types::Task)
|
|
338
|
+
collect_type_substitutions(pattern_type.return_type, actual_type, substitutions, function_name)
|
|
339
|
+
return
|
|
340
|
+
end
|
|
349
341
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
end
|
|
342
|
+
actual_params = case actual_type
|
|
343
|
+
when Types::Proc
|
|
344
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
354
345
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
when Types::StructInstance
|
|
360
|
-
return unless actual_type.is_a?(Types::StructInstance)
|
|
361
|
-
return unless actual_type.definition == pattern_type.definition && actual_type.arguments.length == pattern_type.arguments.length
|
|
346
|
+
actual_type.params
|
|
347
|
+
when Types::Function
|
|
348
|
+
return if actual_type.receiver_type || actual_type.variadic
|
|
349
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
362
350
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
return unless actual_type.is_a?(Types::Function)
|
|
368
|
-
return unless actual_type.params.length == pattern_type.params.length
|
|
351
|
+
actual_type.params
|
|
352
|
+
else
|
|
353
|
+
return
|
|
354
|
+
end
|
|
369
355
|
|
|
370
|
-
|
|
371
|
-
|
|
356
|
+
pattern_type.params.zip(actual_params).each do |expected_param, actual_param|
|
|
357
|
+
collect_type_substitutions(expected_param.type, actual_param.type, substitutions, function_name)
|
|
358
|
+
end
|
|
359
|
+
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
360
|
+
when Types::StructInstance
|
|
361
|
+
return unless actual_type.is_a?(Types::StructInstance)
|
|
362
|
+
return unless actual_type.definition == pattern_type.definition && actual_type.arguments.length == pattern_type.arguments.length
|
|
363
|
+
|
|
364
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
365
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
366
|
+
end
|
|
367
|
+
when Types::Function
|
|
368
|
+
return unless actual_type.is_a?(Types::Function)
|
|
369
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
370
|
+
|
|
371
|
+
pattern_type.params.zip(actual_type.params).each do |expected_param, actual_param|
|
|
372
|
+
collect_type_substitutions(expected_param.type, actual_param.type, substitutions, function_name)
|
|
373
|
+
end
|
|
374
|
+
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
372
375
|
end
|
|
373
|
-
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
374
376
|
end
|
|
375
|
-
end
|
|
376
377
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
378
|
+
def substitute_value_binding(binding, substitutions)
|
|
379
|
+
ValueBinding.new(
|
|
380
|
+
id: binding.id,
|
|
381
|
+
name: binding.name,
|
|
382
|
+
storage_type: substitute_type(binding.storage_type, substitutions),
|
|
383
|
+
flow_type: binding.flow_type ? substitute_type(binding.flow_type, substitutions) : nil,
|
|
384
|
+
mutable: binding.mutable,
|
|
385
|
+
kind: binding.kind,
|
|
386
|
+
const_value: binding.const_value,
|
|
387
|
+
)
|
|
388
|
+
end
|
|
388
389
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
390
|
+
def validate_specialized_function_binding!(function_name, function_type, body_params)
|
|
391
|
+
function_type.params.each do |param|
|
|
392
|
+
validate_specialized_function_type!(param.type, function_name:, context: "parameter #{param.name}")
|
|
393
|
+
validate_specialized_function_type!(param.boundary_type, function_name:, context: "boundary parameter #{param.name}") if param.boundary_type
|
|
394
|
+
end
|
|
395
|
+
validate_specialized_function_type!(function_type.return_type, function_name:, context: "return type")
|
|
396
|
+
validate_specialized_function_type!(function_type.receiver_type, function_name:, context: "receiver type") if function_type.receiver_type
|
|
397
|
+
|
|
398
|
+
body_params.each do |param|
|
|
399
|
+
validate_specialized_function_type!(param.type, function_name:, context: "body parameter #{param.name}")
|
|
400
|
+
end
|
|
393
401
|
end
|
|
394
|
-
validate_specialized_function_type!(function_type.return_type, function_name:, context: "return type")
|
|
395
|
-
validate_specialized_function_type!(function_type.receiver_type, function_name:, context: "receiver type") if function_type.receiver_type
|
|
396
402
|
|
|
397
|
-
|
|
398
|
-
|
|
403
|
+
def validate_specialized_function_type!(type, function_name:, context:)
|
|
404
|
+
ValidateSpecializedTypeVisitor.new(
|
|
405
|
+
function_name:,
|
|
406
|
+
context:,
|
|
407
|
+
on_error: ->(msg) { raise_sema_error(msg) },
|
|
408
|
+
on_generic_instance: ->(name, args) { validate_generic_type!(name, args) },
|
|
409
|
+
).visit(type)
|
|
399
410
|
end
|
|
400
|
-
end
|
|
401
411
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
context:,
|
|
406
|
-
on_error: ->(msg) { raise_sema_error(msg) },
|
|
407
|
-
on_generic_instance: ->(name, args) { validate_generic_type!(name, args) },
|
|
408
|
-
).visit(type)
|
|
409
|
-
end
|
|
412
|
+
def substitute_type(type, substitutions)
|
|
413
|
+
SubstituteTypeVisitor.new(substitutions).apply(type)
|
|
414
|
+
end
|
|
410
415
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
416
|
+
def bitwise_type?(type)
|
|
417
|
+
type.respond_to?(:bitwise?) && type.bitwise?
|
|
418
|
+
end
|
|
414
419
|
|
|
415
|
-
|
|
416
|
-
|
|
420
|
+
def callable_type?(type)
|
|
421
|
+
type.is_a?(Types::Function) || type.is_a?(Types::Proc)
|
|
422
|
+
end
|
|
417
423
|
end
|
|
418
424
|
|
|
419
|
-
def callable_type?(type)
|
|
420
|
-
type.is_a?(Types::Function) || type.is_a?(Types::Proc)
|
|
421
|
-
end
|
|
422
425
|
end
|
|
423
426
|
end
|