mt-lang 0.3.24 → 0.3.26
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/bindings/attribute_binding.rb +51 -49
- data/lib/milk_tea/core/bindings/function_binding.rb +3 -1
- data/lib/milk_tea/core/bindings/module_binding.rb +42 -40
- data/lib/milk_tea/core/bindings/value_binding.rb +16 -14
- data/lib/milk_tea/core/bindings.rb +4 -9
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +11 -11
- data/lib/milk_tea/core/c_backend/expressions.rb +11 -11
- data/lib/milk_tea/core/c_backend/feature_detection.rb +15 -19
- data/lib/milk_tea/core/c_backend/format_helpers.rb +1 -1
- data/lib/milk_tea/core/c_backend/reinterpret.rb +10 -10
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1 -1
- data/lib/milk_tea/core/c_backend/statements.rb +20 -20
- data/lib/milk_tea/core/c_backend/type_declaration.rb +4 -4
- data/lib/milk_tea/core/c_backend/type_system.rb +1 -1
- data/lib/milk_tea/core/c_backend.rb +3 -3
- data/lib/milk_tea/core/compile_time.rb +41 -70
- data/lib/milk_tea/core/control_flow/builder.rb +3 -3
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +1 -1
- data/lib/milk_tea/core/control_flow/graph.rb +1 -1
- data/lib/milk_tea/core/control_flow/termination.rb +1 -1
- data/lib/milk_tea/core/cst.rb +16 -0
- data/lib/milk_tea/core/flow_scope.rb +13 -0
- data/lib/milk_tea/core/lexer/character_classes.rb +2 -2
- data/lib/milk_tea/core/lexer/format_strings.rb +5 -5
- data/lib/milk_tea/core/lexer/heredocs.rb +6 -6
- data/lib/milk_tea/core/lexer/indentation.rb +4 -4
- data/lib/milk_tea/core/lexer/numbers.rb +1 -1
- data/lib/milk_tea/core/lexer/strings.rb +4 -4
- data/lib/milk_tea/core/lexer/symbols.rb +3 -3
- data/lib/milk_tea/core/lexer/trivia.rb +4 -4
- data/lib/milk_tea/core/lexer.rb +17 -17
- data/lib/milk_tea/core/lowering/async/analysis.rb +210 -208
- data/lib/milk_tea/core/lowering/async/async_lowering.rb +1406 -0
- data/lib/milk_tea/core/lowering/async/frame_builder.rb +615 -613
- data/lib/milk_tea/core/lowering/async/normalization.rb +410 -408
- data/lib/milk_tea/core/lowering/block.rb +982 -980
- data/lib/milk_tea/core/lowering/calls.rb +1360 -1358
- data/lib/milk_tea/core/lowering/declarations.rb +175 -173
- data/lib/milk_tea/core/lowering/dyn.rb +171 -169
- data/lib/milk_tea/core/lowering/events.rb +946 -944
- data/lib/milk_tea/core/lowering/expressions.rb +1514 -1512
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +180 -178
- data/lib/milk_tea/core/lowering/functions.rb +186 -184
- data/lib/milk_tea/core/lowering/loops.rb +1004 -1002
- data/lib/milk_tea/core/lowering/lowering_context.rb +1 -1
- data/lib/milk_tea/core/lowering/proc.rb +355 -353
- data/lib/milk_tea/core/lowering/resolve.rb +2127 -2125
- data/lib/milk_tea/core/lowering/scans.rb +162 -168
- data/lib/milk_tea/core/lowering/str_buffer.rb +104 -102
- data/lib/milk_tea/core/lowering/utils.rb +964 -963
- data/lib/milk_tea/core/lowering.rb +22 -22
- data/lib/milk_tea/core/module_binder.rb +1 -1
- data/lib/milk_tea/core/module_loader.rb +2 -2
- data/lib/milk_tea/core/parser/attributes.rb +1 -1
- data/lib/milk_tea/core/parser/blocks.rb +2 -2
- data/lib/milk_tea/core/parser/declarations.rb +15 -15
- data/lib/milk_tea/core/parser/expressions.rb +20 -20
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser/statements.rb +3 -3
- data/lib/milk_tea/core/parser/types.rb +4 -4
- data/lib/milk_tea/core/parser.rb +39 -21
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +6 -6
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +5 -5
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +2 -2
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +37 -37
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +7 -7
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +59 -59
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +3 -3
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +12 -12
- data/lib/milk_tea/core/types/layout.rb +3 -1
- data/lib/milk_tea/core/types/visitor.rb +351 -349
- data/lib/milk_tea/core.rb +0 -2
- data/lib/milk_tea/tooling/cli/commands/bindgen.rb +1 -1
- data/lib/milk_tea/tooling/cli/commands/check.rb +5 -5
- data/lib/milk_tea/tooling/cli/commands/debug.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/deps.rb +1 -1
- data/lib/milk_tea/tooling/cli/commands/emit_c.rb +2 -2
- data/lib/milk_tea/tooling/cli/commands/format.rb +6 -6
- data/lib/milk_tea/tooling/cli/commands/lint.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/lower.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/parse.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/test.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/toolchain.rb +1 -1
- data/lib/milk_tea/tooling/cli.rb +22 -34
- data/lib/milk_tea/tooling/linter/flow_rules.rb +3 -3
- metadata +4 -5
- data/lib/milk_tea/core/cst_builder.rb +0 -19
- data/lib/milk_tea/core/lowering/async/lowering.rb +0 -1404
- data/lib/milk_tea/core/token_stream.rb +0 -30
|
@@ -1,2622 +1,2624 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
COMPILE_TIME_BUILTINS = %w[
|
|
15
|
-
field_of callable_of has_attribute attribute_of
|
|
16
|
-
].freeze
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def direct_function_to_proc_contextual_compatibility?(expression, actual_type, env:, expected_type:)
|
|
20
|
-
return false unless actual_type.is_a?(Types::Function) && proc_type?(expected_type)
|
|
21
|
-
return false unless direct_function_identity_expression?(expression, env)
|
|
22
|
-
|
|
23
|
-
function_type_matches_proc_type?(actual_type, expected_type)
|
|
24
|
-
end
|
|
4
|
+
module Lowering
|
|
5
|
+
module Resolve
|
|
6
|
+
PASS_THROUGH_BUILTINS = {
|
|
7
|
+
"fatal" => :fatal,
|
|
8
|
+
"ref_of" => :ref_of,
|
|
9
|
+
"const_ptr_of" => :const_ptr_of,
|
|
10
|
+
"read" => :read,
|
|
11
|
+
"ptr_of" => :ptr_of,
|
|
12
|
+
"get" => :get,
|
|
13
|
+
}.freeze
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
38
|
-
return false unless imported_module.functions.key?(expression.member)
|
|
39
|
-
|
|
40
|
-
binding = imported_module.functions.fetch(expression.member)
|
|
41
|
-
!binding.type_params.any? && !foreign_function_binding?(binding)
|
|
42
|
-
when AST::Specialization
|
|
43
|
-
callable_resolution = resolve_specialized_callable_binding(expression, env:)
|
|
44
|
-
return false unless callable_resolution
|
|
45
|
-
|
|
46
|
-
callable_kind, binding, = callable_resolution
|
|
47
|
-
callable_kind == :function && !foreign_function_binding?(binding)
|
|
48
|
-
else
|
|
49
|
-
false
|
|
15
|
+
COMPILE_TIME_BUILTINS = %w[
|
|
16
|
+
field_of callable_of has_attribute attribute_of
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def direct_function_to_proc_contextual_compatibility?(expression, actual_type, env:, expected_type:)
|
|
21
|
+
return false unless actual_type.is_a?(Types::Function) && proc_type?(expected_type)
|
|
22
|
+
return false unless direct_function_identity_expression?(expression, env)
|
|
23
|
+
|
|
24
|
+
function_type_matches_proc_type?(actual_type, expected_type)
|
|
50
25
|
end
|
|
51
|
-
end
|
|
52
26
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
release_linkage_name = "#{@ctx.module_prefix}__proc_#{proc_id}__release"
|
|
59
|
-
retain_c_name = "#{@ctx.module_prefix}__proc_#{proc_id}__retain"
|
|
60
|
-
|
|
61
|
-
@artifacts.synthetic_functions << build_direct_function_proc_invoke_function(source_expression, source_function.name, source_function.type, expected_type, invoke_c_name)
|
|
62
|
-
@artifacts.synthetic_functions << build_proc_noop_release_function(release_linkage_name)
|
|
63
|
-
@artifacts.synthetic_functions << build_proc_noop_retain_function(retain_c_name)
|
|
64
|
-
|
|
65
|
-
IR::AggregateLiteral.new(
|
|
66
|
-
type: expected_type,
|
|
67
|
-
fields: [
|
|
68
|
-
IR::AggregateField.new(name: "env", value: IR::NullLiteral.new(type: proc_env_pointer_type)),
|
|
69
|
-
IR::AggregateField.new(name: "invoke", value: IR::Name.new(name: invoke_c_name, type: proc_invoke_function_type(expected_type), pointer: false)),
|
|
70
|
-
IR::AggregateField.new(name: "release", value: IR::Name.new(name: release_linkage_name, type: proc_release_function_type, pointer: false)),
|
|
71
|
-
IR::AggregateField.new(name: "retain", value: IR::Name.new(name: retain_c_name, type: proc_retain_function_type, pointer: false)),
|
|
72
|
-
],
|
|
73
|
-
)
|
|
74
|
-
end
|
|
27
|
+
def direct_function_identity_expression?(expression, env)
|
|
28
|
+
case expression
|
|
29
|
+
when AST::Identifier
|
|
30
|
+
return false if lookup_value(expression.name, env)
|
|
31
|
+
return false unless @ctx.functions.key?(expression.name)
|
|
75
32
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
value: IR::Name.new(name: input_linkage_name, type: param.type, pointer: false),
|
|
93
|
-
)
|
|
94
|
-
call_arguments << IR::Name.new(name: linkage_name, type: param.type, pointer: false)
|
|
33
|
+
binding = @ctx.functions.fetch(expression.name)
|
|
34
|
+
!binding.type_params.any? && !foreign_function_binding?(binding)
|
|
35
|
+
when AST::MemberAccess
|
|
36
|
+
return false unless expression.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.receiver.name)
|
|
37
|
+
|
|
38
|
+
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
39
|
+
return false unless imported_module.functions.key?(expression.member)
|
|
40
|
+
|
|
41
|
+
binding = imported_module.functions.fetch(expression.member)
|
|
42
|
+
!binding.type_params.any? && !foreign_function_binding?(binding)
|
|
43
|
+
when AST::Specialization
|
|
44
|
+
callable_resolution = resolve_specialized_callable_binding(expression, env:)
|
|
45
|
+
return false unless callable_resolution
|
|
46
|
+
|
|
47
|
+
callable_kind, binding, = callable_resolution
|
|
48
|
+
callable_kind == :function && !foreign_function_binding?(binding)
|
|
95
49
|
else
|
|
96
|
-
|
|
97
|
-
params << IR::Param.new(name: param.name || "arg#{index}", linkage_name:, type: param.type, pointer: false)
|
|
98
|
-
call_arguments << IR::Name.new(name: linkage_name, type: param.type, pointer: false)
|
|
50
|
+
false
|
|
99
51
|
end
|
|
100
52
|
end
|
|
101
53
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
parameter_setup + [IR::ExpressionStmt.new(expression: call), IR::ReturnStmt.new(value: nil)]
|
|
105
|
-
else
|
|
106
|
-
parameter_setup + [IR::ReturnStmt.new(value: call)]
|
|
107
|
-
end
|
|
54
|
+
def lower_fn_to_proc_expression(source_expression, source_function, env:, expected_type:)
|
|
55
|
+
raise LoweringError.new("function-to-proc coercion requires a direct function name", line: 0, column: 0, path: @ctx.current_analysis_path) unless source_function.is_a?(IR::Name)
|
|
108
56
|
|
|
109
|
-
|
|
110
|
-
|
|
57
|
+
proc_id = fresh_proc_symbol
|
|
58
|
+
invoke_c_name = "#{@ctx.module_prefix}__proc_#{proc_id}__invoke"
|
|
59
|
+
release_linkage_name = "#{@ctx.module_prefix}__proc_#{proc_id}__release"
|
|
60
|
+
retain_c_name = "#{@ctx.module_prefix}__proc_#{proc_id}__retain"
|
|
111
61
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
name: "
|
|
121
|
-
value: IR::
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
62
|
+
@artifacts.synthetic_functions << build_direct_function_proc_invoke_function(source_expression, source_function.name, source_function.type, expected_type, invoke_c_name)
|
|
63
|
+
@artifacts.synthetic_functions << build_proc_noop_release_function(release_linkage_name)
|
|
64
|
+
@artifacts.synthetic_functions << build_proc_noop_retain_function(retain_c_name)
|
|
65
|
+
|
|
66
|
+
IR::AggregateLiteral.new(
|
|
67
|
+
type: expected_type,
|
|
68
|
+
fields: [
|
|
69
|
+
IR::AggregateField.new(name: "env", value: IR::NullLiteral.new(type: proc_env_pointer_type)),
|
|
70
|
+
IR::AggregateField.new(name: "invoke", value: IR::Name.new(name: invoke_c_name, type: proc_invoke_function_type(expected_type), pointer: false)),
|
|
71
|
+
IR::AggregateField.new(name: "release", value: IR::Name.new(name: release_linkage_name, type: proc_release_function_type, pointer: false)),
|
|
72
|
+
IR::AggregateField.new(name: "retain", value: IR::Name.new(name: retain_c_name, type: proc_retain_function_type, pointer: false)),
|
|
73
|
+
],
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def build_direct_function_proc_invoke_function(source_expression, function_c_name, function_type, proc_type, invoke_c_name)
|
|
78
|
+
env = empty_env
|
|
79
|
+
params = [IR::Param.new(name: "env", linkage_name: "__mt_proc_env", type: proc_env_pointer_type, pointer: false)]
|
|
80
|
+
parameter_setup = []
|
|
81
|
+
call_arguments = []
|
|
82
|
+
|
|
83
|
+
proc_type.params.each_with_index do |param, index|
|
|
84
|
+
linkage_name = c_local_name(param.name || "arg#{index}")
|
|
85
|
+
if array_type?(param.type)
|
|
86
|
+
input_linkage_name = "#{linkage_name}_input"
|
|
87
|
+
params << IR::Param.new(name: param.name || "arg#{index}", linkage_name: input_linkage_name, type: param.type, pointer: false)
|
|
88
|
+
env[:scopes].last[param.name || "arg#{index}"] = local_binding(type: param.type, linkage_name:, mutable: param.mutable, pointer: false)
|
|
89
|
+
parameter_setup << IR::LocalDecl.new(
|
|
90
|
+
name: param.name || "arg#{index}",
|
|
91
|
+
linkage_name:,
|
|
92
|
+
type: param.type,
|
|
93
|
+
value: IR::Name.new(name: input_linkage_name, type: param.type, pointer: false),
|
|
94
|
+
)
|
|
95
|
+
call_arguments << IR::Name.new(name: linkage_name, type: param.type, pointer: false)
|
|
96
|
+
else
|
|
97
|
+
env[:scopes].last[param.name || "arg#{index}"] = local_binding(type: param.type, linkage_name:, mutable: param.mutable, pointer: false)
|
|
98
|
+
params << IR::Param.new(name: param.name || "arg#{index}", linkage_name:, type: param.type, pointer: false)
|
|
99
|
+
call_arguments << IR::Name.new(name: linkage_name, type: param.type, pointer: false)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
call = IR::Call.new(callee: function_c_name, arguments: call_arguments, type: proc_type.return_type)
|
|
104
|
+
body = if proc_type.return_type == @ctx.types.fetch("void")
|
|
105
|
+
parameter_setup + [IR::ExpressionStmt.new(expression: call), IR::ReturnStmt.new(value: nil)]
|
|
106
|
+
else
|
|
107
|
+
parameter_setup + [IR::ReturnStmt.new(value: call)]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
IR::Function.new(name: invoke_c_name, linkage_name: invoke_c_name, params:, return_type: proc_type.return_type, body:, entry_point: false)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def lower_array_to_span_expression(expression, target_type)
|
|
114
|
+
array_type = expression.type
|
|
115
|
+
array_type = referenced_type(array_type) if ref_type?(array_type)
|
|
116
|
+
|
|
117
|
+
IR::AggregateLiteral.new(
|
|
118
|
+
type: target_type,
|
|
119
|
+
fields: [
|
|
120
|
+
IR::AggregateField.new(
|
|
121
|
+
name: "data",
|
|
122
|
+
value: IR::AddressOf.new(
|
|
123
|
+
expression: IR::Index.new(
|
|
124
|
+
receiver: expression,
|
|
125
|
+
index: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
|
|
126
|
+
type: target_type.element_type,
|
|
127
|
+
),
|
|
128
|
+
type: pointer_to(target_type.element_type),
|
|
126
129
|
),
|
|
127
|
-
type: pointer_to(target_type.element_type),
|
|
128
130
|
),
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end
|
|
131
|
+
IR::AggregateField.new(
|
|
132
|
+
name: "len",
|
|
133
|
+
value: IR::IntegerLiteral.new(value: array_length(array_type), type: @ctx.types.fetch("ptr_uint")),
|
|
134
|
+
),
|
|
135
|
+
],
|
|
136
|
+
)
|
|
137
|
+
end
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
139
|
+
def lower_str_buffer_to_span_expression(expression, target_type)
|
|
140
|
+
IR::AggregateLiteral.new(
|
|
141
|
+
type: target_type,
|
|
142
|
+
fields: [
|
|
143
|
+
IR::AggregateField.new(
|
|
144
|
+
name: "data",
|
|
145
|
+
value: IR::Call.new(
|
|
146
|
+
callee: "mt_str_buffer_prepare_write",
|
|
147
|
+
arguments: [
|
|
148
|
+
lower_str_buffer_data_pointer_from_lowered(expression),
|
|
149
|
+
IR::IntegerLiteral.new(value: str_buffer_capacity(expression.type), type: @ctx.types.fetch("ptr_uint")),
|
|
150
|
+
lower_str_buffer_dirty_pointer_from_lowered(expression),
|
|
151
|
+
],
|
|
152
|
+
type: pointer_to(target_type.element_type),
|
|
153
|
+
),
|
|
152
154
|
),
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
end
|
|
155
|
+
IR::AggregateField.new(
|
|
156
|
+
name: "len",
|
|
157
|
+
value: IR::IntegerLiteral.new(value: str_buffer_storage_capacity(expression.type), type: @ctx.types.fetch("ptr_uint")),
|
|
158
|
+
),
|
|
159
|
+
],
|
|
160
|
+
)
|
|
161
|
+
end
|
|
161
162
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
def contextual_numeric_compatibility?(expression, actual_type, expected_type, env:, external_numeric: false, contextual_int_to_float: false)
|
|
164
|
+
return true if exact_compile_time_numeric_compatibility?(actual_type, expression, expected_type, env:)
|
|
165
|
+
return true if integer_to_char_compatibility?(actual_type, expected_type)
|
|
166
|
+
return true if external_numeric && external_numeric_compatibility?(actual_type, expected_type)
|
|
167
|
+
return true if contextual_int_to_float && contextual_int_to_float_compatibility?(actual_type, expected_type)
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
|
|
169
|
+
false
|
|
170
|
+
end
|
|
170
171
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
172
|
+
def cstr_backed_expression?(expression, env)
|
|
173
|
+
return true if infer_expression_type(expression, env:) == @ctx.types.fetch("cstr")
|
|
174
|
+
|
|
175
|
+
case expression
|
|
176
|
+
when AST::StringLiteral
|
|
177
|
+
true
|
|
178
|
+
when AST::Identifier
|
|
179
|
+
binding_cstr_backed?(lookup_value(expression.name, env))
|
|
180
|
+
when AST::IfExpr
|
|
181
|
+
then_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: true, env:))
|
|
182
|
+
else_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: false, env:))
|
|
183
|
+
cstr_backed_expression?(expression.then_expression, then_env) &&
|
|
184
|
+
cstr_backed_expression?(expression.else_expression, else_env)
|
|
185
|
+
when AST::UnsafeExpr
|
|
186
|
+
cstr_backed_expression?(expression.expression, env)
|
|
187
|
+
else
|
|
188
|
+
false
|
|
189
|
+
end
|
|
190
|
+
rescue LoweringError
|
|
187
191
|
false
|
|
188
192
|
end
|
|
189
|
-
rescue LoweringError
|
|
190
|
-
false
|
|
191
|
-
end
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
194
|
+
def cstr_list_backed_expression?(expression, env)
|
|
195
|
+
actual_type = infer_expression_type(expression, env:)
|
|
196
|
+
return false unless array_type?(actual_type)
|
|
197
|
+
|
|
198
|
+
element_type = array_element_type(actual_type)
|
|
199
|
+
return false unless element_type == @ctx.types.fetch("str") || element_type == @ctx.types.fetch("cstr")
|
|
200
|
+
|
|
201
|
+
case expression
|
|
202
|
+
when AST::Identifier
|
|
203
|
+
binding_cstr_list_backed?(lookup_value(expression.name, env))
|
|
204
|
+
when AST::Call
|
|
205
|
+
expression.arguments.all? { |argument| cstr_backed_expression?(argument.value, env) }
|
|
206
|
+
when AST::IfExpr
|
|
207
|
+
then_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: true, env:))
|
|
208
|
+
else_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: false, env:))
|
|
209
|
+
cstr_list_backed_expression?(expression.then_expression, then_env) &&
|
|
210
|
+
cstr_list_backed_expression?(expression.else_expression, else_env)
|
|
211
|
+
when AST::UnsafeExpr
|
|
212
|
+
cstr_list_backed_expression?(expression.expression, env)
|
|
213
|
+
else
|
|
214
|
+
false
|
|
215
|
+
end
|
|
216
|
+
rescue LoweringError
|
|
213
217
|
false
|
|
214
218
|
end
|
|
215
|
-
rescue LoweringError
|
|
216
|
-
false
|
|
217
|
-
end
|
|
218
219
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
def cstr_backed_storage_value?(type, expression, env)
|
|
221
|
+
return false unless expression
|
|
222
|
+
return true if type == @ctx.types.fetch("cstr")
|
|
223
|
+
return false unless type == @ctx.types.fetch("str")
|
|
223
224
|
|
|
224
|
-
|
|
225
|
-
|
|
225
|
+
cstr_backed_expression?(expression, env)
|
|
226
|
+
end
|
|
226
227
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
def cstr_list_backed_storage_value?(type, expression, env)
|
|
229
|
+
return false unless expression
|
|
230
|
+
return false unless cstr_list_trackable_type?(type)
|
|
230
231
|
|
|
231
|
-
|
|
232
|
-
|
|
232
|
+
cstr_list_backed_expression?(expression, env)
|
|
233
|
+
end
|
|
233
234
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
def update_cstr_metadata_for_assignment!(statement, prepared_value, env)
|
|
236
|
+
if statement.target.is_a?(AST::Identifier)
|
|
237
|
+
binding = lookup_value(statement.target.name, env)
|
|
238
|
+
return unless binding
|
|
238
239
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
240
|
+
replace_binding_cstr_metadata!(
|
|
241
|
+
statement.target.name,
|
|
242
|
+
env,
|
|
243
|
+
cstr_backed: statement.operator == "=" ? cstr_backed_storage_value?(binding[:type], prepared_value, env) : false,
|
|
244
|
+
cstr_list_backed: statement.operator == "=" ? cstr_list_backed_storage_value?(binding[:type], prepared_value, env) : false,
|
|
245
|
+
)
|
|
246
|
+
return
|
|
247
|
+
end
|
|
247
248
|
|
|
248
|
-
|
|
249
|
+
return unless statement.target.is_a?(AST::IndexAccess) && statement.target.receiver.is_a?(AST::Identifier)
|
|
249
250
|
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
binding = lookup_value(statement.target.receiver.name, env)
|
|
252
|
+
return unless binding && cstr_list_trackable_type?(binding[:type])
|
|
252
253
|
|
|
253
|
-
|
|
254
|
-
|
|
254
|
+
replace_binding_cstr_metadata!(statement.target.receiver.name, env, cstr_backed: binding_cstr_backed?(binding), cstr_list_backed: false)
|
|
255
|
+
end
|
|
255
256
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
def merge_cstr_metadata_after_if_statement!(statement, env)
|
|
258
|
+
exit_envs = cstr_metadata_exit_envs_for_if_statement(statement, env)
|
|
259
|
+
return if exit_envs.empty?
|
|
259
260
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
trackable_binding_names(env).each do |name|
|
|
262
|
+
binding = lookup_value(name, env)
|
|
263
|
+
next unless binding
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
265
|
+
replace_binding_cstr_metadata!(
|
|
266
|
+
name,
|
|
267
|
+
env,
|
|
268
|
+
cstr_backed: cstr_trackable_type?(binding[:type]) && exit_envs.all? { |exit_env| binding_cstr_backed?(lookup_value(name, exit_env)) },
|
|
269
|
+
cstr_list_backed: cstr_list_trackable_type?(binding[:type]) && exit_envs.all? { |exit_env| binding_cstr_list_backed?(lookup_value(name, exit_env)) },
|
|
270
|
+
)
|
|
271
|
+
end
|
|
270
272
|
end
|
|
271
|
-
end
|
|
272
273
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
def cstr_metadata_exit_envs_for_if_statement(statement, env)
|
|
275
|
+
false_refinements = {}
|
|
276
|
+
exit_envs = []
|
|
276
277
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
statement.branches.each do |branch|
|
|
279
|
+
branch_env = env_with_refinements(env, false_refinements)
|
|
280
|
+
true_refinements = merge_refinements(false_refinements, flow_refinements(branch.condition, truthy: true, env: branch_env))
|
|
281
|
+
simulated = simulate_cstr_metadata_block(branch.body, env: env_with_refinements(env, true_refinements))
|
|
282
|
+
exit_envs << simulated if simulated
|
|
283
|
+
false_refinements = merge_refinements(false_refinements, flow_refinements(branch.condition, truthy: false, env: branch_env))
|
|
284
|
+
end
|
|
284
285
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
if statement.else_body
|
|
287
|
+
simulated = simulate_cstr_metadata_block(statement.else_body, env: env_with_refinements(env, false_refinements))
|
|
288
|
+
exit_envs << simulated if simulated
|
|
289
|
+
else
|
|
290
|
+
exit_envs << env
|
|
291
|
+
end
|
|
291
292
|
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
exit_envs
|
|
294
|
+
end
|
|
294
295
|
|
|
295
|
-
|
|
296
|
-
|
|
296
|
+
def simulate_cstr_metadata_block(statements, env:)
|
|
297
|
+
simulated_env = duplicate_env(env)
|
|
297
298
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
299
|
+
statements.each do |statement|
|
|
300
|
+
case statement
|
|
301
|
+
when AST::LocalDecl
|
|
302
|
+
storage_type = if statement.else_body
|
|
303
|
+
infer_expression_type(statement.value, env: simulated_env)
|
|
304
|
+
elsif statement.type
|
|
305
|
+
resolve_type_ref(statement.type)
|
|
306
|
+
else
|
|
307
|
+
infer_expression_type(statement.value, env: simulated_env)
|
|
308
|
+
end
|
|
309
|
+
type = if statement.else_body
|
|
310
|
+
statement.type ? resolve_type_ref(statement.type) : let_else_success_type(storage_type)
|
|
311
|
+
else
|
|
312
|
+
storage_type
|
|
313
|
+
end
|
|
314
|
+
unless let_else_discards_binding?(statement)
|
|
315
|
+
current_actual_scope(simulated_env[:scopes])[statement.name] = local_binding(
|
|
316
|
+
type:,
|
|
317
|
+
storage_type:,
|
|
318
|
+
linkage_name: c_local_name(statement.name),
|
|
319
|
+
mutable: statement.kind == :var,
|
|
320
|
+
pointer: false,
|
|
321
|
+
projection: statement.else_body ? let_else_binding_projection(storage_type) : nil,
|
|
322
|
+
cstr_backed: cstr_backed_storage_value?(storage_type, statement.value, simulated_env),
|
|
323
|
+
cstr_list_backed: cstr_list_backed_storage_value?(storage_type, statement.value, simulated_env),
|
|
324
|
+
const_value: statement.else_body ? nil : statement.kind == :let && statement.value ? compile_time_const_value(statement.value, env: simulated_env) : nil,
|
|
325
|
+
)
|
|
326
|
+
end
|
|
327
|
+
when AST::Assignment
|
|
328
|
+
update_cstr_metadata_for_assignment!(statement, statement.value, simulated_env)
|
|
329
|
+
when AST::IfStmt
|
|
330
|
+
merge_cstr_metadata_after_if_statement!(statement, simulated_env)
|
|
331
|
+
when AST::UnsafeStmt
|
|
332
|
+
nested_env = simulate_cstr_metadata_block(statement.body, env: simulated_env)
|
|
333
|
+
return nil unless nested_env
|
|
334
|
+
|
|
335
|
+
copy_cstr_metadata!(simulated_env, nested_env)
|
|
336
|
+
when AST::ReturnStmt, AST::BreakStmt, AST::ContinueStmt
|
|
337
|
+
return nil
|
|
325
338
|
end
|
|
326
|
-
when AST::Assignment
|
|
327
|
-
update_cstr_metadata_for_assignment!(statement, statement.value, simulated_env)
|
|
328
|
-
when AST::IfStmt
|
|
329
|
-
merge_cstr_metadata_after_if_statement!(statement, simulated_env)
|
|
330
|
-
when AST::UnsafeStmt
|
|
331
|
-
nested_env = simulate_cstr_metadata_block(statement.body, env: simulated_env)
|
|
332
|
-
return nil unless nested_env
|
|
333
|
-
|
|
334
|
-
copy_cstr_metadata!(simulated_env, nested_env)
|
|
335
|
-
when AST::ReturnStmt, AST::BreakStmt, AST::ContinueStmt
|
|
336
|
-
return nil
|
|
337
339
|
end
|
|
340
|
+
|
|
341
|
+
simulated_env
|
|
338
342
|
end
|
|
339
343
|
|
|
340
|
-
|
|
341
|
-
|
|
344
|
+
def copy_cstr_metadata!(target_env, source_env)
|
|
345
|
+
trackable_binding_names(target_env).each do |name|
|
|
346
|
+
binding = lookup_value(name, target_env)
|
|
347
|
+
source_binding = lookup_value(name, source_env)
|
|
348
|
+
next unless binding && source_binding
|
|
342
349
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
name,
|
|
351
|
-
target_env,
|
|
352
|
-
cstr_backed: binding_cstr_backed?(source_binding),
|
|
353
|
-
cstr_list_backed: binding_cstr_list_backed?(source_binding),
|
|
354
|
-
)
|
|
350
|
+
replace_binding_cstr_metadata!(
|
|
351
|
+
name,
|
|
352
|
+
target_env,
|
|
353
|
+
cstr_backed: binding_cstr_backed?(source_binding),
|
|
354
|
+
cstr_list_backed: binding_cstr_list_backed?(source_binding),
|
|
355
|
+
)
|
|
356
|
+
end
|
|
355
357
|
end
|
|
356
|
-
end
|
|
357
358
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
359
|
+
def replace_binding_cstr_metadata!(name, env, cstr_backed:, cstr_list_backed:)
|
|
360
|
+
env[:scopes].reverse_each do |scope|
|
|
361
|
+
next if scope.is_a?(FlowScope)
|
|
362
|
+
next unless scope.key?(name)
|
|
362
363
|
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
scope[name] = scope.fetch(name).merge(cstr_backed:, cstr_list_backed:)
|
|
365
|
+
return
|
|
366
|
+
end
|
|
365
367
|
end
|
|
366
|
-
end
|
|
367
368
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
def trackable_binding_names(env)
|
|
370
|
+
env[:scopes].each_with_object([]) do |scope, names|
|
|
371
|
+
next if scope.is_a?(FlowScope)
|
|
371
372
|
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
scope.each do |name, binding|
|
|
374
|
+
next unless cstr_trackable_type?(binding[:type]) || cstr_list_trackable_type?(binding[:type])
|
|
374
375
|
|
|
375
|
-
|
|
376
|
+
names << name unless names.include?(name)
|
|
377
|
+
end
|
|
376
378
|
end
|
|
377
379
|
end
|
|
378
|
-
end
|
|
379
380
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
381
|
+
def binding_cstr_backed?(binding)
|
|
382
|
+
binding && binding[:cstr_backed]
|
|
383
|
+
end
|
|
383
384
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
385
|
+
def binding_cstr_list_backed?(binding)
|
|
386
|
+
binding && binding[:cstr_list_backed]
|
|
387
|
+
end
|
|
387
388
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
389
|
+
def exact_compile_time_numeric_compatibility?(actual_type, expression, expected_type, env: nil)
|
|
390
|
+
return false unless expected_type.is_a?(Types::Primitive) && expected_type.numeric?
|
|
391
|
+
return false if actual_type.is_a?(Types::EnumBase)
|
|
391
392
|
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
value = compile_time_const_value(expression, env:)
|
|
394
|
+
return false unless value.is_a?(Numeric)
|
|
394
395
|
|
|
395
|
-
|
|
396
|
-
|
|
396
|
+
numeric_constant_fits_type?(value, expected_type)
|
|
397
|
+
end
|
|
397
398
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
399
|
+
def external_numeric_assignment_target?(expression, env:)
|
|
400
|
+
case expression
|
|
401
|
+
when AST::MemberAccess
|
|
402
|
+
receiver_type = infer_field_receiver_type(expression.receiver, env:)
|
|
403
|
+
receiver_type.respond_to?(:external) && receiver_type.external
|
|
404
|
+
else
|
|
405
|
+
false
|
|
406
|
+
end
|
|
405
407
|
end
|
|
406
|
-
end
|
|
407
408
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
409
|
+
def resolve_callee(callee, env, arguments: nil)
|
|
410
|
+
case callee
|
|
411
|
+
when AST::Identifier
|
|
412
|
+
resolve_identifier_callee(callee, env, arguments)
|
|
413
|
+
when AST::MemberAccess
|
|
414
|
+
resolve_member_access_callee(callee, env, arguments)
|
|
415
|
+
when AST::Specialization
|
|
416
|
+
resolve_specialization_callee(callee, env)
|
|
417
|
+
else
|
|
418
|
+
resolve_expression_callee(callee, env)
|
|
419
|
+
end
|
|
418
420
|
end
|
|
419
|
-
end
|
|
420
421
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
422
|
+
def resolve_identifier_callee(callee, env, arguments)
|
|
423
|
+
if (binding = lookup_value(callee.name, env))
|
|
424
|
+
return [:callable_value, nil, nil, binding[:type], nil] if callable_type?(binding[:type])
|
|
424
425
|
|
|
425
|
-
|
|
426
|
-
|
|
426
|
+
raise LoweringError.new("#{callee.name} is not callable", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
427
|
+
end
|
|
427
428
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
429
|
+
if @ctx.functions.key?(callee.name)
|
|
430
|
+
binding = specialize_function_binding(@ctx.functions.fetch(callee.name), arguments, env)
|
|
431
|
+
callee_name = if binding.external
|
|
432
|
+
external_function_c_name(binding)
|
|
433
|
+
else
|
|
434
|
+
function_binding_c_name(binding, module_name: @ctx.module_name)
|
|
435
|
+
end
|
|
436
|
+
return [:function, callee_name, nil, binding.type, binding]
|
|
437
|
+
end
|
|
437
438
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
439
|
+
if (kind = PASS_THROUGH_BUILTINS[callee.name])
|
|
440
|
+
return [kind, nil, nil, nil]
|
|
441
|
+
end
|
|
441
442
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
if COMPILE_TIME_BUILTINS.include?(callee.name)
|
|
444
|
+
return [:compile_time_builtin, callee.name, nil, compile_time_builtin_function_type(callee.name, arguments, env)]
|
|
445
|
+
end
|
|
445
446
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
447
|
+
type = @ctx.types[callee.name]
|
|
448
|
+
if type.is_a?(Types::Struct) || type.is_a?(Types::StringView) || task_type?(type) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
|
|
449
|
+
return [:struct_literal, nil, nil, type]
|
|
450
|
+
end
|
|
450
451
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
453
|
+
raise LoweringError.new("generic type #{callee.name} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
454
|
+
end
|
|
454
455
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
456
|
+
emit_fn = @artifacts.emitted_declarations.find { |d| d.is_a?(IR::Function) && d.name == callee.name }
|
|
457
|
+
if emit_fn
|
|
458
|
+
return [:function, emit_fn.linkage_name, nil, emit_fn.return_type, nil]
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
raise LoweringError.new("unknown callee #{callee.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
458
462
|
end
|
|
459
463
|
|
|
460
|
-
|
|
461
|
-
|
|
464
|
+
def resolve_member_access_callee(callee, env, arguments)
|
|
465
|
+
if callee.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(callee.receiver.name)
|
|
466
|
+
imported_module = @ctx.imports.fetch(callee.receiver.name)
|
|
462
467
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
468
|
+
if imported_module.functions.key?(callee.member)
|
|
469
|
+
binding = specialize_function_binding(imported_module.functions.fetch(callee.member), arguments, env)
|
|
470
|
+
unless binding.owner
|
|
471
|
+
binding = binding.with(owner: imported_module.respond_to?(:analysis) ? imported_module.analysis : imported_module)
|
|
472
|
+
end
|
|
473
|
+
return [:function, function_binding_c_name(binding, module_name: imported_module.name), nil, binding.type, binding] unless binding.external
|
|
466
474
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
475
|
+
return [:function, external_function_c_name(binding), nil, binding.type, binding]
|
|
476
|
+
end
|
|
477
|
+
imported_type = imported_module.types[callee.member]
|
|
478
|
+
if imported_type.is_a?(Types::GenericStructDefinition) || imported_type.is_a?(Types::GenericVariantDefinition)
|
|
479
|
+
raise LoweringError.new("generic type #{callee.receiver.name}.#{callee.member} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
471
480
|
end
|
|
472
|
-
return [:function, function_binding_c_name(binding, module_name: imported_module.name), nil, binding.type, binding] unless binding.external
|
|
473
481
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
if imported_type.is_a?(Types::GenericStructDefinition) || imported_type.is_a?(Types::GenericVariantDefinition)
|
|
478
|
-
raise LoweringError.new("generic type #{callee.receiver.name}.#{callee.member} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
479
|
-
end
|
|
482
|
+
if imported_type.is_a?(Types::Struct) || imported_type.is_a?(Types::StringView) || task_type?(imported_type) || imported_type.is_a?(Types::Vector) || imported_type.is_a?(Types::Matrix) || imported_type.is_a?(Types::Quaternion)
|
|
483
|
+
return [:struct_literal, nil, nil, imported_module.types.fetch(callee.member)]
|
|
484
|
+
end
|
|
480
485
|
|
|
481
|
-
|
|
482
|
-
|
|
486
|
+
if imported_type.is_a?(Types::Variant) && imported_type.arm_names.include?(callee.member)
|
|
487
|
+
arm_name = callee.member
|
|
488
|
+
return [:variant_arm_ctor, nil, nil, imported_type, [imported_type, arm_name]]
|
|
489
|
+
end
|
|
483
490
|
end
|
|
484
491
|
|
|
485
|
-
if
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
492
|
+
if (type_expr = resolve_type_expression(callee.receiver))
|
|
493
|
+
if type_expr.is_a?(Types::Variant) && type_expr.arm_names.include?(callee.member)
|
|
494
|
+
arm_name = callee.member
|
|
495
|
+
return [:variant_arm_ctor, nil, nil, type_expr, [type_expr, arm_name]]
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
if type_expr.respond_to?(:nested_types) && type_expr.nested_types.key?(callee.member)
|
|
499
|
+
return [:struct_literal, nil, nil, type_expr.nested_types[callee.member]]
|
|
500
|
+
end
|
|
490
501
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
502
|
+
dispatch_receiver_type = method_dispatch_receiver_type(type_expr)
|
|
503
|
+
method_entry_receiver_type = type_expr
|
|
504
|
+
method_entry = @method_definitions[[type_expr, callee.member]]
|
|
505
|
+
method_entry ||= @method_definitions[[type_expr, "static:#{callee.member}"]]
|
|
506
|
+
unless method_entry || dispatch_receiver_type == type_expr
|
|
507
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
508
|
+
method_entry = @method_definitions[[dispatch_receiver_type, callee.member]]
|
|
509
|
+
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{callee.member}"]]
|
|
510
|
+
end
|
|
511
|
+
if method_entry
|
|
512
|
+
method_analysis, method_ast = method_entry
|
|
513
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
514
|
+
if method_binding.type.receiver_type.nil?
|
|
515
|
+
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: type_expr) if method_binding.type_params.any?
|
|
516
|
+
return [:associated_method, function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type), nil, method_binding.type, method_binding]
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
raise LoweringError.new("unknown associated function #{type_expr}.#{callee.member}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
495
521
|
end
|
|
496
522
|
|
|
497
|
-
|
|
498
|
-
|
|
523
|
+
resolved_receiver_type = infer_method_receiver_type(callee.receiver, env:, member_name: callee.member)
|
|
524
|
+
|
|
525
|
+
if dyn_type?(resolved_receiver_type)
|
|
526
|
+
interface = resolved_receiver_type.interface_binding
|
|
527
|
+
method_binding = interface.methods[callee.member]
|
|
528
|
+
raise LoweringError.new("no method '#{callee.member}' on interface #{interface.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless method_binding
|
|
529
|
+
return [:dyn_method, nil, callee.receiver, method_binding, nil]
|
|
499
530
|
end
|
|
500
531
|
|
|
501
|
-
dispatch_receiver_type = method_dispatch_receiver_type(
|
|
502
|
-
method_entry_receiver_type =
|
|
503
|
-
method_entry = @method_definitions[[
|
|
504
|
-
method_entry
|
|
505
|
-
unless method_entry || dispatch_receiver_type == type_expr
|
|
532
|
+
dispatch_receiver_type = method_dispatch_receiver_type(resolved_receiver_type)
|
|
533
|
+
method_entry_receiver_type = resolved_receiver_type
|
|
534
|
+
method_entry = @method_definitions[[resolved_receiver_type, callee.member]]
|
|
535
|
+
unless method_entry || dispatch_receiver_type == resolved_receiver_type
|
|
506
536
|
method_entry_receiver_type = dispatch_receiver_type
|
|
507
537
|
method_entry = @method_definitions[[dispatch_receiver_type, callee.member]]
|
|
508
|
-
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{callee.member}"]]
|
|
509
538
|
end
|
|
510
539
|
if method_entry
|
|
511
540
|
method_analysis, method_ast = method_entry
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
541
|
+
method_analysis_key = method_ast.kind == :static ? "static:#{method_ast.name}" : method_ast.name
|
|
542
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key)
|
|
543
|
+
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: resolved_receiver_type)
|
|
544
|
+
return [
|
|
545
|
+
:method,
|
|
546
|
+
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type),
|
|
547
|
+
callee.receiver,
|
|
548
|
+
method_binding.type,
|
|
549
|
+
method_binding,
|
|
550
|
+
]
|
|
517
551
|
end
|
|
518
552
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
553
|
+
if callee.member == "with" && struct_with_target_type?(resolved_receiver_type)
|
|
554
|
+
return [:struct_with, nil, callee.receiver, resolved_receiver_type]
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
if (precomputed = @ctx.resolved_call_kinds[@ctx.ast.node_ids[callee.object_id]])
|
|
558
|
+
case precomputed
|
|
559
|
+
when :str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
560
|
+
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr
|
|
561
|
+
return [precomputed, nil, callee.receiver, str_buffer_method_type(precomputed, resolved_receiver_type)]
|
|
562
|
+
when :event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait
|
|
563
|
+
event_type = infer_expression_type(callee.receiver, env:)
|
|
564
|
+
return [precomputed, nil, callee.receiver, event_method_type(precomputed, event_type)]
|
|
565
|
+
when :atomic_load, :atomic_store, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_compare_exchange
|
|
566
|
+
elem = atomic_element_type(resolved_receiver_type)
|
|
567
|
+
ret = case precomputed
|
|
568
|
+
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
569
|
+
when :atomic_store then @ctx.types.fetch("void")
|
|
570
|
+
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
571
|
+
end
|
|
572
|
+
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
573
|
+
when :simd_lane_with
|
|
574
|
+
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: resolved_receiver_type)]
|
|
575
|
+
end
|
|
576
|
+
end
|
|
523
577
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
raise LoweringError.new("no method '#{callee.member}' on interface #{interface.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless method_binding
|
|
528
|
-
return [:dyn_method, nil, callee.receiver, method_binding, nil]
|
|
529
|
-
end
|
|
578
|
+
if (str_buffer_method = str_buffer_method_kind(resolved_receiver_type, callee.member))
|
|
579
|
+
return [str_buffer_method, nil, callee.receiver, str_buffer_method_type(str_buffer_method, resolved_receiver_type)]
|
|
580
|
+
end
|
|
530
581
|
|
|
531
|
-
|
|
532
|
-
method_entry_receiver_type = resolved_receiver_type
|
|
533
|
-
method_entry = @method_definitions[[resolved_receiver_type, callee.member]]
|
|
534
|
-
unless method_entry || dispatch_receiver_type == resolved_receiver_type
|
|
535
|
-
method_entry_receiver_type = dispatch_receiver_type
|
|
536
|
-
method_entry = @method_definitions[[dispatch_receiver_type, callee.member]]
|
|
537
|
-
end
|
|
538
|
-
if method_entry
|
|
539
|
-
method_analysis, method_ast = method_entry
|
|
540
|
-
method_analysis_key = method_ast.kind == :static ? "static:#{method_ast.name}" : method_ast.name
|
|
541
|
-
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key)
|
|
542
|
-
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: resolved_receiver_type)
|
|
543
|
-
return [
|
|
544
|
-
:method,
|
|
545
|
-
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type),
|
|
546
|
-
callee.receiver,
|
|
547
|
-
method_binding.type,
|
|
548
|
-
method_binding,
|
|
549
|
-
]
|
|
550
|
-
end
|
|
551
|
-
|
|
552
|
-
if callee.member == "with" && struct_with_target_type?(resolved_receiver_type)
|
|
553
|
-
return [:struct_with, nil, callee.receiver, resolved_receiver_type]
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
if (precomputed = @ctx.resolved_call_kinds[@ctx.ast.node_ids[callee.object_id]])
|
|
557
|
-
case precomputed
|
|
558
|
-
when :str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
559
|
-
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr
|
|
560
|
-
return [precomputed, nil, callee.receiver, str_buffer_method_type(precomputed, resolved_receiver_type)]
|
|
561
|
-
when :event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait
|
|
582
|
+
if (event_method = event_method_kind(resolved_receiver_type, callee.member))
|
|
562
583
|
event_type = infer_expression_type(callee.receiver, env:)
|
|
563
|
-
return [
|
|
564
|
-
|
|
584
|
+
return [event_method, nil, callee.receiver, event_method_type(event_method, event_type)]
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
if (atomic_method = atomic_method_kind(resolved_receiver_type, callee.member))
|
|
565
588
|
elem = atomic_element_type(resolved_receiver_type)
|
|
566
|
-
ret = case
|
|
589
|
+
ret = case atomic_method
|
|
567
590
|
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
568
591
|
when :atomic_store then @ctx.types.fetch("void")
|
|
569
592
|
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
570
593
|
end
|
|
571
|
-
return [
|
|
572
|
-
when :simd_lane_with
|
|
573
|
-
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: resolved_receiver_type)]
|
|
594
|
+
return [atomic_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
574
595
|
end
|
|
575
|
-
end
|
|
576
|
-
|
|
577
|
-
if (str_buffer_method = str_buffer_method_kind(resolved_receiver_type, callee.member))
|
|
578
|
-
return [str_buffer_method, nil, callee.receiver, str_buffer_method_type(str_buffer_method, resolved_receiver_type)]
|
|
579
|
-
end
|
|
580
|
-
|
|
581
|
-
if (event_method = event_method_kind(resolved_receiver_type, callee.member))
|
|
582
|
-
event_type = infer_expression_type(callee.receiver, env:)
|
|
583
|
-
return [event_method, nil, callee.receiver, event_method_type(event_method, event_type)]
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
if (atomic_method = atomic_method_kind(resolved_receiver_type, callee.member))
|
|
587
|
-
elem = atomic_element_type(resolved_receiver_type)
|
|
588
|
-
ret = case atomic_method
|
|
589
|
-
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
590
|
-
when :atomic_store then @ctx.types.fetch("void")
|
|
591
|
-
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
592
|
-
end
|
|
593
|
-
return [atomic_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
if (simd_method = simd_method_kind(resolved_receiver_type, callee.member))
|
|
597
|
-
ret = case simd_method
|
|
598
|
-
when :simd_lane_with then resolved_receiver_type
|
|
599
|
-
end
|
|
600
|
-
return [simd_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
601
|
-
end
|
|
602
|
-
|
|
603
|
-
field_receiver_type = infer_field_receiver_type(callee.receiver, env:)
|
|
604
|
-
if array_type?(field_receiver_type) && callee.member == "as_span"
|
|
605
|
-
return [:array_as_span, nil, callee.receiver, Types::Registry.span(array_element_type(field_receiver_type))]
|
|
606
|
-
end
|
|
607
|
-
|
|
608
|
-
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
609
|
-
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
610
|
-
return [:callable_value, nil, nil, member_type, nil] if callable_type?(member_type)
|
|
611
596
|
|
|
612
|
-
|
|
613
|
-
|
|
597
|
+
if (simd_method = simd_method_kind(resolved_receiver_type, callee.member))
|
|
598
|
+
ret = case simd_method
|
|
599
|
+
when :simd_lane_with then resolved_receiver_type
|
|
600
|
+
end
|
|
601
|
+
return [simd_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
field_receiver_type = infer_field_receiver_type(callee.receiver, env:)
|
|
605
|
+
if array_type?(field_receiver_type) && callee.member == "as_span"
|
|
606
|
+
return [:array_as_span, nil, callee.receiver, Types::Registry.span(array_element_type(field_receiver_type))]
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
610
|
+
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
611
|
+
return [:callable_value, nil, nil, member_type, nil] if callable_type?(member_type)
|
|
612
|
+
|
|
613
|
+
raise LoweringError.new("unknown callee #{callee.receiver}.#{callee.member}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def resolve_specialization_callee(callee, env)
|
|
617
|
+
if callee.callee.is_a?(AST::Identifier)
|
|
618
|
+
case callee.callee.name
|
|
619
|
+
when "reinterpret"
|
|
620
|
+
target_type = resolve_type_ref(callee.arguments.fetch(0).value)
|
|
621
|
+
return [:reinterpret, nil, nil, Types::Registry.function("reinterpret", params: [Types::Registry.parameter("value", target_type)], return_type: target_type)]
|
|
622
|
+
when "array"
|
|
623
|
+
array_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["array"]), arguments: callee.arguments, nullable: false))
|
|
624
|
+
return [:array, nil, nil, array_type]
|
|
625
|
+
when "simd"
|
|
626
|
+
simd_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["simd"]), arguments: callee.arguments, nullable: false))
|
|
627
|
+
return [:simd, nil, nil, simd_type]
|
|
628
|
+
when "span"
|
|
629
|
+
span_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: callee.arguments, nullable: false))
|
|
630
|
+
return [:struct_literal, nil, nil, span_type]
|
|
631
|
+
when "zero"
|
|
632
|
+
target_type = resolve_type_ref(callee.arguments.fetch(0).value)
|
|
633
|
+
return [:zero, nil, nil, Types::Registry.function("zero", params: [], return_type: target_type)]
|
|
634
|
+
when "hash"
|
|
635
|
+
resolution = resolve_hash_specialization(callee, env:)
|
|
636
|
+
return [:hash, resolution.callee_name, nil, Types::Registry.function("hash", params: [Types::Registry.parameter("value", resolution.target_type)], return_type: @ctx.types.fetch("uint")), resolution.binding]
|
|
637
|
+
when "equal"
|
|
638
|
+
resolution = resolve_equal_specialization(callee, env:)
|
|
639
|
+
params = [
|
|
640
|
+
Types::Registry.parameter("left", resolution.target_type),
|
|
641
|
+
Types::Registry.parameter("right", resolution.target_type),
|
|
642
|
+
]
|
|
643
|
+
return [:equal, resolution.callee_name, nil, Types::Registry.function("equal", params:, return_type: @ctx.types.fetch("bool")), resolution.binding]
|
|
644
|
+
when "order"
|
|
645
|
+
resolution = resolve_order_specialization(callee, env:)
|
|
646
|
+
params = [
|
|
647
|
+
Types::Registry.parameter("left", resolution.target_type),
|
|
648
|
+
Types::Registry.parameter("right", resolution.target_type),
|
|
649
|
+
]
|
|
650
|
+
return [:order, resolution.callee_name, nil, Types::Registry.function("order", params:, return_type: @ctx.types.fetch("int")), resolution.binding]
|
|
651
|
+
when "attribute_arg"
|
|
652
|
+
return [:compile_time_builtin, "attribute_arg", nil, compile_time_builtin_specialization_function_type(callee)]
|
|
653
|
+
when "adapt"
|
|
654
|
+
raise LoweringError.new("adapt requires exactly one type argument", line: 0, column: 0, path: @ctx.current_analysis_path) unless callee.arguments.length == 1
|
|
655
|
+
|
|
656
|
+
type_arg = callee.arguments.first.value
|
|
657
|
+
raise LoweringError.new("adapt type argument must be a type", line: 0, column: 0, path: @ctx.current_analysis_path) unless type_arg.is_a?(AST::TypeRef)
|
|
658
|
+
|
|
659
|
+
parts = type_arg.name.parts
|
|
660
|
+
type_args = type_arg.arguments.map { |a| a.value }
|
|
661
|
+
interface = resolve_interface_ref(AST::QualifiedName.new(parts:, type_arguments: type_args))
|
|
662
|
+
dyn_type = Types::Dyn.new(interface, interface.respond_to?(:type_arguments) ? (interface.type_arguments || []) : [])
|
|
663
|
+
return [:adapt, nil, nil, dyn_type, interface]
|
|
664
|
+
end
|
|
665
|
+
end
|
|
614
666
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
return [:simd, nil, nil, simd_type]
|
|
627
|
-
when "span"
|
|
628
|
-
span_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: callee.arguments, nullable: false))
|
|
629
|
-
return [:struct_literal, nil, nil, span_type]
|
|
630
|
-
when "zero"
|
|
631
|
-
target_type = resolve_type_ref(callee.arguments.fetch(0).value)
|
|
632
|
-
return [:zero, nil, nil, Types::Registry.function("zero", params: [], return_type: target_type)]
|
|
633
|
-
when "hash"
|
|
634
|
-
resolution = resolve_hash_specialization(callee, env:)
|
|
635
|
-
return [:hash, resolution.callee_name, nil, Types::Registry.function("hash", params: [Types::Registry.parameter("value", resolution.target_type)], return_type: @ctx.types.fetch("uint")), resolution.binding]
|
|
636
|
-
when "equal"
|
|
637
|
-
resolution = resolve_equal_specialization(callee, env:)
|
|
638
|
-
params = [
|
|
639
|
-
Types::Registry.parameter("left", resolution.target_type),
|
|
640
|
-
Types::Registry.parameter("right", resolution.target_type),
|
|
641
|
-
]
|
|
642
|
-
return [:equal, resolution.callee_name, nil, Types::Registry.function("equal", params:, return_type: @ctx.types.fetch("bool")), resolution.binding]
|
|
643
|
-
when "order"
|
|
644
|
-
resolution = resolve_order_specialization(callee, env:)
|
|
645
|
-
params = [
|
|
646
|
-
Types::Registry.parameter("left", resolution.target_type),
|
|
647
|
-
Types::Registry.parameter("right", resolution.target_type),
|
|
648
|
-
]
|
|
649
|
-
return [:order, resolution.callee_name, nil, Types::Registry.function("order", params:, return_type: @ctx.types.fetch("int")), resolution.binding]
|
|
650
|
-
when "attribute_arg"
|
|
651
|
-
return [:compile_time_builtin, "attribute_arg", nil, compile_time_builtin_specialization_function_type(callee)]
|
|
652
|
-
when "adapt"
|
|
653
|
-
raise LoweringError.new("adapt requires exactly one type argument", line: 0, column: 0, path: @ctx.current_analysis_path) unless callee.arguments.length == 1
|
|
667
|
+
if (callable_resolution = resolve_specialized_callable_binding(callee, env:))
|
|
668
|
+
callable_kind, function_binding, receiver, method_entry_receiver_type = callable_resolution
|
|
669
|
+
if callable_kind == :method
|
|
670
|
+
return [
|
|
671
|
+
:method,
|
|
672
|
+
function_binding_c_name(function_binding, module_name: function_binding.owner.module_name, receiver_type: method_entry_receiver_type),
|
|
673
|
+
receiver,
|
|
674
|
+
function_binding.type,
|
|
675
|
+
function_binding,
|
|
676
|
+
]
|
|
677
|
+
end
|
|
654
678
|
|
|
655
|
-
|
|
656
|
-
|
|
679
|
+
if function_binding.external
|
|
680
|
+
return [:function, external_function_c_name(function_binding), nil, function_binding.type, function_binding]
|
|
681
|
+
end
|
|
657
682
|
|
|
658
|
-
|
|
659
|
-
type_args = type_arg.arguments.map { |a| a.value }
|
|
660
|
-
interface = resolve_interface_ref(AST::QualifiedName.new(parts:, type_arguments: type_args))
|
|
661
|
-
dyn_type = Types::Dyn.new(interface, interface.respond_to?(:type_arguments) ? (interface.type_arguments || []) : [])
|
|
662
|
-
return [:adapt, nil, nil, dyn_type, interface]
|
|
683
|
+
return [:function, function_binding_c_name(function_binding, module_name: function_binding.owner.module_name), nil, function_binding.type, function_binding]
|
|
663
684
|
end
|
|
664
|
-
end
|
|
665
685
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
return [
|
|
670
|
-
:method,
|
|
671
|
-
function_binding_c_name(function_binding, module_name: function_binding.owner.module_name, receiver_type: method_entry_receiver_type),
|
|
672
|
-
receiver,
|
|
673
|
-
function_binding.type,
|
|
674
|
-
function_binding,
|
|
675
|
-
]
|
|
686
|
+
if (type_ref = type_ref_from_specialization(callee))
|
|
687
|
+
specialized_type = resolve_type_ref(type_ref)
|
|
688
|
+
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
676
689
|
end
|
|
677
690
|
|
|
678
|
-
|
|
679
|
-
return [:function, external_function_c_name(function_binding), nil, function_binding.type, function_binding]
|
|
680
|
-
end
|
|
681
|
-
|
|
682
|
-
return [:function, function_binding_c_name(function_binding, module_name: function_binding.owner.module_name), nil, function_binding.type, function_binding]
|
|
683
|
-
end
|
|
684
|
-
|
|
685
|
-
if (type_ref = type_ref_from_specialization(callee))
|
|
686
|
-
specialized_type = resolve_type_ref(type_ref)
|
|
687
|
-
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
691
|
+
raise LoweringError.new("unsupported specialization callee", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
688
692
|
end
|
|
689
693
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
def resolve_expression_callee(callee, env)
|
|
694
|
-
callee_type = infer_expression_type(callee, env:)
|
|
695
|
-
return [:callable_value, nil, nil, callee_type, nil] if callable_type?(callee_type)
|
|
696
|
-
|
|
697
|
-
raise LoweringError.new("unsupported callee #{callee.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
698
|
-
end
|
|
694
|
+
def resolve_expression_callee(callee, env)
|
|
695
|
+
callee_type = infer_expression_type(callee, env:)
|
|
696
|
+
return [:callable_value, nil, nil, callee_type, nil] if callable_type?(callee_type)
|
|
699
697
|
|
|
700
|
-
|
|
701
|
-
if !@bypass_sema_type_cache && expected_type.nil? && (id = @ctx.ast.node_ids[expression.object_id]) && (resolved = @ctx.resolved_expr_types[id])
|
|
702
|
-
return resolved
|
|
698
|
+
raise LoweringError.new("unsupported callee #{callee.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
703
699
|
end
|
|
704
700
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
701
|
+
def infer_expression_type(expression, env:, expected_type: nil)
|
|
702
|
+
if !@bypass_sema_type_cache && expected_type.nil? && (id = @ctx.ast.node_ids[expression.object_id]) && (resolved = @ctx.resolved_expr_types[id])
|
|
703
|
+
return resolved
|
|
704
|
+
end
|
|
709
705
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
else
|
|
715
|
-
@ctx.types.fetch("int")
|
|
716
|
-
end
|
|
717
|
-
when AST::CharLiteral
|
|
718
|
-
@ctx.types.fetch("ubyte")
|
|
719
|
-
when AST::FloatLiteral
|
|
720
|
-
if expression.lexeme.end_with?("f")
|
|
721
|
-
@ctx.types.fetch("float")
|
|
722
|
-
elsif expression.lexeme.end_with?("d")
|
|
723
|
-
@ctx.types.fetch("double")
|
|
724
|
-
elsif expected_type.is_a?(Types::Primitive) && expected_type.float?
|
|
725
|
-
expected_type
|
|
726
|
-
else
|
|
727
|
-
@ctx.types.fetch("float")
|
|
728
|
-
end
|
|
729
|
-
when AST::SizeofExpr, AST::AlignofExpr, AST::OffsetofExpr
|
|
730
|
-
@ctx.types.fetch("ptr_uint")
|
|
731
|
-
when AST::StringLiteral
|
|
732
|
-
@ctx.types.fetch(expression.cstring ? "cstr" : "str")
|
|
733
|
-
when AST::FormatString
|
|
734
|
-
@ctx.types.fetch("str")
|
|
735
|
-
when AST::BooleanLiteral
|
|
736
|
-
@ctx.types.fetch("bool")
|
|
737
|
-
when AST::NullLiteral
|
|
738
|
-
infer_null_literal_type(expression, expected_type)
|
|
739
|
-
when AST::Identifier
|
|
740
|
-
binding = lookup_value(expression.name, env)
|
|
741
|
-
return binding[:type] if binding
|
|
742
|
-
return function_type_for_name(expression.name) if @ctx.functions.key?(expression.name)
|
|
743
|
-
|
|
744
|
-
raise LoweringError.new("unknown identifier #{expression.name}", line: expression.line, column: expression.column)
|
|
745
|
-
when AST::MemberAccess
|
|
746
|
-
if (type_expr = resolve_type_expression(expression.receiver))
|
|
747
|
-
member_type = resolve_type_member(type_expr, expression.member)
|
|
748
|
-
return member_type if member_type
|
|
706
|
+
case expression
|
|
707
|
+
when AST::AwaitExpr
|
|
708
|
+
task_type = infer_expression_type(expression.expression, env:)
|
|
709
|
+
raise LoweringError.new("await requires a Task value, got #{task_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless task_type.is_a?(Types::Task)
|
|
749
710
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
method_entry = @method_definitions[[dispatch_receiver_type, expression.member]]
|
|
757
|
-
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{expression.member}"]]
|
|
711
|
+
task_type.result_type
|
|
712
|
+
when AST::IntegerLiteral
|
|
713
|
+
if expected_type.is_a?(Types::Primitive) && expected_type.integer?
|
|
714
|
+
expected_type
|
|
715
|
+
else
|
|
716
|
+
@ctx.types.fetch("int")
|
|
758
717
|
end
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
718
|
+
when AST::CharLiteral
|
|
719
|
+
@ctx.types.fetch("ubyte")
|
|
720
|
+
when AST::FloatLiteral
|
|
721
|
+
if expression.lexeme.end_with?("f")
|
|
722
|
+
@ctx.types.fetch("float")
|
|
723
|
+
elsif expression.lexeme.end_with?("d")
|
|
724
|
+
@ctx.types.fetch("double")
|
|
725
|
+
elsif expected_type.is_a?(Types::Primitive) && expected_type.float?
|
|
726
|
+
expected_type
|
|
727
|
+
else
|
|
728
|
+
@ctx.types.fetch("float")
|
|
729
|
+
end
|
|
730
|
+
when AST::SizeofExpr, AST::AlignofExpr, AST::OffsetofExpr
|
|
731
|
+
@ctx.types.fetch("ptr_uint")
|
|
732
|
+
when AST::StringLiteral
|
|
733
|
+
@ctx.types.fetch(expression.cstring ? "cstr" : "str")
|
|
734
|
+
when AST::FormatString
|
|
735
|
+
@ctx.types.fetch("str")
|
|
736
|
+
when AST::BooleanLiteral
|
|
737
|
+
@ctx.types.fetch("bool")
|
|
738
|
+
when AST::NullLiteral
|
|
739
|
+
infer_null_literal_type(expression, expected_type)
|
|
740
|
+
when AST::Identifier
|
|
741
|
+
binding = lookup_value(expression.name, env)
|
|
742
|
+
return binding[:type] if binding
|
|
743
|
+
return function_type_for_name(expression.name) if @ctx.functions.key?(expression.name)
|
|
744
|
+
|
|
745
|
+
raise LoweringError.new("unknown identifier #{expression.name}", line: expression.line, column: expression.column)
|
|
746
|
+
when AST::MemberAccess
|
|
747
|
+
if (type_expr = resolve_type_expression(expression.receiver))
|
|
748
|
+
member_type = resolve_type_member(type_expr, expression.member)
|
|
749
|
+
return member_type if member_type
|
|
750
|
+
|
|
751
|
+
dispatch_receiver_type = method_dispatch_receiver_type(type_expr)
|
|
752
|
+
method_entry_receiver_type = type_expr
|
|
753
|
+
method_entry = @method_definitions[[type_expr, expression.member]]
|
|
754
|
+
method_entry ||= @method_definitions[[type_expr, "static:#{expression.member}"]]
|
|
755
|
+
unless method_entry || dispatch_receiver_type == type_expr
|
|
756
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
757
|
+
method_entry = @method_definitions[[dispatch_receiver_type, expression.member]]
|
|
758
|
+
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{expression.member}"]]
|
|
759
|
+
end
|
|
760
|
+
if method_entry
|
|
761
|
+
method_analysis, method_ast = method_entry
|
|
762
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
763
|
+
return method_binding.type if method_binding.type.receiver_type.nil?
|
|
764
|
+
end
|
|
765
|
+
end
|
|
766
|
+
if expression.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.receiver.name)
|
|
767
|
+
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
768
|
+
return imported_module.values.fetch(expression.member).type if imported_module.values.key?(expression.member)
|
|
769
|
+
return imported_module.functions.fetch(expression.member).type if imported_module.functions.key?(expression.member)
|
|
770
|
+
end
|
|
771
|
+
receiver_type = infer_field_receiver_type(expression.receiver, env:)
|
|
772
|
+
if (event_type = event_member_from_owner_type(receiver_type, expression.member))
|
|
773
|
+
return event_type
|
|
763
774
|
end
|
|
764
|
-
end
|
|
765
|
-
if expression.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.receiver.name)
|
|
766
|
-
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
767
|
-
return imported_module.values.fetch(expression.member).type if imported_module.values.key?(expression.member)
|
|
768
|
-
return imported_module.functions.fetch(expression.member).type if imported_module.functions.key?(expression.member)
|
|
769
|
-
end
|
|
770
|
-
receiver_type = infer_field_receiver_type(expression.receiver, env:)
|
|
771
|
-
if (event_type = event_member_from_owner_type(receiver_type, expression.member))
|
|
772
|
-
return event_type
|
|
773
|
-
end
|
|
774
775
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
776
|
+
if receiver_type == @ctx.types["field_handle"]
|
|
777
|
+
return infer_field_handle_member_type(expression)
|
|
778
|
+
end
|
|
779
|
+
if receiver_type == @ctx.types["member_handle"]
|
|
780
|
+
return infer_member_handle_member_type(expression)
|
|
781
|
+
end
|
|
781
782
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
783
|
+
return receiver_type.field(expression.member) if receiver_type.respond_to?(:field)
|
|
784
|
+
raise LoweringError.new("unknown member #{expression.member}", line: expression.line, column: expression.column)
|
|
785
|
+
when AST::IndexAccess
|
|
786
|
+
receiver_type = infer_expression_type(expression.receiver, env:)
|
|
787
|
+
index_type = infer_expression_type(expression.index, env:)
|
|
788
|
+
infer_index_result_type(receiver_type, index_type)
|
|
789
|
+
when AST::UnaryOp
|
|
790
|
+
return infer_result_propagation_type(expression, env:) if expression.operator == "?"
|
|
791
|
+
|
|
792
|
+
operand_type = infer_expression_type(expression.operand, env:, expected_type:)
|
|
793
|
+
case expression.operator
|
|
794
|
+
when "not"
|
|
795
|
+
@ctx.types.fetch("bool")
|
|
796
|
+
else
|
|
797
|
+
operand_type
|
|
798
|
+
end
|
|
799
|
+
when AST::BinaryOp
|
|
800
|
+
left_type, right_type = infer_binary_operand_types(expression, env:, expected_type: expected_type)
|
|
801
|
+
|
|
802
|
+
case expression.operator
|
|
803
|
+
when "and", "or", "<", "<=", ">", ">=", "==", "!="
|
|
804
|
+
@ctx.types.fetch("bool")
|
|
805
|
+
when "+", "-", "*", "/"
|
|
806
|
+
aggregate_arithmetic_result_type(expression.operator, left_type, right_type) || pointer_arithmetic_result_type(expression.operator, left_type, right_type) || common_numeric_type(left_type, right_type) || left_type
|
|
807
|
+
when "%"
|
|
808
|
+
common_integer_type(left_type, right_type) || left_type
|
|
809
|
+
else
|
|
810
|
+
left_type
|
|
811
|
+
end
|
|
812
|
+
when AST::IfExpr
|
|
813
|
+
then_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: true, env:))
|
|
814
|
+
else_env = env_with_refinements(env, flow_refinements(expression.condition, truthy: false, env:))
|
|
815
|
+
then_type = infer_expression_type(expression.then_expression, env: then_env, expected_type: expected_type)
|
|
816
|
+
else_type = infer_expression_type(expression.else_expression, env: else_env, expected_type: expected_type)
|
|
817
|
+
|
|
818
|
+
if expected_type &&
|
|
819
|
+
if_expression_branch_compatible?(then_type, expected_type) &&
|
|
820
|
+
if_expression_branch_compatible?(else_type, expected_type)
|
|
821
|
+
return expected_type
|
|
822
|
+
end
|
|
790
823
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
824
|
+
conditional_common_type(then_type, else_type) || raise(LoweringError, "if expression branches require compatible types, got #{then_type} and #{else_type}")
|
|
825
|
+
when AST::MatchExpr
|
|
826
|
+
scrutinee_type = infer_expression_type(expression.expression, env:)
|
|
827
|
+
arm_types = expression.arms.map do |arm|
|
|
828
|
+
arm_env = duplicate_env(env)
|
|
829
|
+
if scrutinee_type.is_a?(Types::Variant) && arm.binding_name && !wildcard_arm_pattern?(arm.pattern)
|
|
830
|
+
arm_name = variant_match_arm_name_from_pattern(arm.pattern)
|
|
831
|
+
if arm_name && scrutinee_type.has_payload?(arm_name)
|
|
832
|
+
fields = scrutinee_type.arm(arm_name)
|
|
833
|
+
payload_type = Types::VariantArmPayload.new(scrutinee_type, arm_name, fields)
|
|
834
|
+
arm_env[:scopes].last[arm.binding_name] = local_binding(type: payload_type, linkage_name: c_local_name(arm.binding_name), mutable: false, pointer: false)
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
infer_expression_type(arm.value, env: arm_env, expected_type: expected_type)
|
|
838
|
+
end
|
|
800
839
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
840
|
+
if expected_type && arm_types.all? { |arm_type| if_expression_branch_compatible?(arm_type, expected_type) }
|
|
841
|
+
return expected_type
|
|
842
|
+
end
|
|
843
|
+
|
|
844
|
+
common_type = arm_types.first
|
|
845
|
+
arm_types.drop(1).each do |arm_type|
|
|
846
|
+
common_type = conditional_common_type(common_type, arm_type) || raise(LoweringError, "match expression arms require compatible types, got #{common_type} and #{arm_type}")
|
|
847
|
+
end
|
|
848
|
+
common_type
|
|
849
|
+
when AST::UnsafeExpr
|
|
850
|
+
infer_expression_type(expression.expression, env:, expected_type:)
|
|
851
|
+
when AST::ProcExpr
|
|
852
|
+
resolve_type_ref(AST::ProcType.new(params: expression.params, return_type: expression.return_type))
|
|
853
|
+
when AST::Call
|
|
854
|
+
kind, _callee_name, _receiver, callee_type = resolve_callee(expression.callee, env, arguments: expression.arguments)
|
|
855
|
+
case kind
|
|
856
|
+
when :function, :method, :associated_method, :callable_value,
|
|
857
|
+
:str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
858
|
+
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr,
|
|
859
|
+
:event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait,
|
|
860
|
+
:compile_time_builtin,
|
|
861
|
+
:reinterpret, :zero, :hash, :equal, :order,
|
|
862
|
+
:dyn_method
|
|
863
|
+
callee_type.return_type
|
|
864
|
+
when :struct_literal, :struct_with, :array, :simd, :variant_arm_ctor, :adapt
|
|
865
|
+
callee_type
|
|
866
|
+
when :ref_of
|
|
867
|
+
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
868
|
+
Types::Registry.generic_instance("ref", [argument_type])
|
|
869
|
+
when :const_ptr_of
|
|
870
|
+
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
871
|
+
Types::Registry.generic_instance("const_ptr", [argument_type])
|
|
872
|
+
when :read
|
|
873
|
+
infer_value_type(expression.arguments.fetch(0).value, env:)
|
|
874
|
+
when :ptr_of
|
|
875
|
+
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
876
|
+
if ref_type?(argument_type)
|
|
877
|
+
Types::Registry.generic_instance("ptr", [referenced_type(argument_type)])
|
|
878
|
+
else
|
|
879
|
+
Types::Registry.generic_instance("ptr", [infer_expression_type(expression.arguments.fetch(0).value, env:, expected_type: expected_type && pointer_type?(expected_type) ? pointee_type(expected_type) : nil)])
|
|
834
880
|
end
|
|
881
|
+
when :array_as_span
|
|
882
|
+
callee_type
|
|
883
|
+
when :fatal
|
|
884
|
+
@ctx.types.fetch("void")
|
|
885
|
+
when :get
|
|
886
|
+
receiver_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
887
|
+
elem_type = if array_type?(receiver_type)
|
|
888
|
+
array_element_type(receiver_type)
|
|
889
|
+
else
|
|
890
|
+
receiver_type.element_type
|
|
891
|
+
end
|
|
892
|
+
Types::Registry.nullable(Types::Registry.generic_instance("ptr", [elem_type]))
|
|
893
|
+
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_store, :atomic_compare_exchange,
|
|
894
|
+
:simd_lane_with
|
|
895
|
+
callee_type.return_type
|
|
896
|
+
else
|
|
897
|
+
raise LoweringError.new("unsupported call kind #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
835
898
|
end
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
infer_expression_type(expression.expression, env:, expected_type:)
|
|
850
|
-
when AST::ProcExpr
|
|
851
|
-
resolve_type_ref(AST::ProcType.new(params: expression.params, return_type: expression.return_type))
|
|
852
|
-
when AST::Call
|
|
853
|
-
kind, _callee_name, _receiver, callee_type = resolve_callee(expression.callee, env, arguments: expression.arguments)
|
|
854
|
-
case kind
|
|
855
|
-
when :function, :method, :associated_method, :callable_value,
|
|
856
|
-
:str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
857
|
-
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr,
|
|
858
|
-
:event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait,
|
|
859
|
-
:compile_time_builtin,
|
|
860
|
-
:reinterpret, :zero, :hash, :equal, :order,
|
|
861
|
-
:dyn_method
|
|
862
|
-
callee_type.return_type
|
|
863
|
-
when :struct_literal, :struct_with, :array, :simd, :variant_arm_ctor, :adapt
|
|
864
|
-
callee_type
|
|
865
|
-
when :ref_of
|
|
866
|
-
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
867
|
-
Types::Registry.generic_instance("ref", [argument_type])
|
|
868
|
-
when :const_ptr_of
|
|
869
|
-
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
870
|
-
Types::Registry.generic_instance("const_ptr", [argument_type])
|
|
871
|
-
when :read
|
|
872
|
-
infer_value_type(expression.arguments.fetch(0).value, env:)
|
|
873
|
-
when :ptr_of
|
|
874
|
-
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
875
|
-
if ref_type?(argument_type)
|
|
876
|
-
Types::Registry.generic_instance("ptr", [referenced_type(argument_type)])
|
|
899
|
+
when AST::PrefixCast
|
|
900
|
+
resolve_type_ref(expression.target_type)
|
|
901
|
+
when AST::Specialization
|
|
902
|
+
if expression.callee.is_a?(AST::Identifier) && expression.callee.name == "zero"
|
|
903
|
+
_, _, _, function_type = resolve_callee(expression, env, arguments: [])
|
|
904
|
+
function_type.return_type
|
|
905
|
+
elsif expression.callee.is_a?(AST::Identifier) && expression.callee.name == "default"
|
|
906
|
+
resolve_default_specialization(expression, env:).target_type
|
|
907
|
+
elsif (callable_resolution = resolve_specialized_callable_binding(expression, env:))
|
|
908
|
+
callable_kind, function_binding, = callable_resolution
|
|
909
|
+
raise LoweringError.new("specialized method must be called", line: 0, column: 0, path: @ctx.current_analysis_path) if callable_kind == :method
|
|
910
|
+
|
|
911
|
+
function_binding.type
|
|
877
912
|
else
|
|
878
|
-
|
|
879
|
-
end
|
|
880
|
-
when
|
|
881
|
-
|
|
882
|
-
when
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
913
|
+
raise LoweringError.new("unsupported specialization", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
914
|
+
end
|
|
915
|
+
when AST::RangeExpr
|
|
916
|
+
raise LoweringError.new("range expression is not valid in this context; use it as a for-loop iterable", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
917
|
+
when AST::ExpressionList
|
|
918
|
+
names = []
|
|
919
|
+
element_types = []
|
|
920
|
+
expression.elements.each do |element|
|
|
921
|
+
if element.is_a?(AST::Argument)
|
|
922
|
+
names << element.name
|
|
923
|
+
element_types << infer_expression_type(element.value, env:)
|
|
924
|
+
else
|
|
925
|
+
names << nil
|
|
926
|
+
element_types << infer_expression_type(element, env:)
|
|
927
|
+
end
|
|
928
|
+
end
|
|
929
|
+
has_named = names.any?
|
|
930
|
+
Types::Registry.tuple(element_types, field_names: has_named ? names : nil)
|
|
931
|
+
when AST::DetachExpr
|
|
932
|
+
Types::Handle.new
|
|
895
933
|
else
|
|
896
|
-
raise LoweringError.new("unsupported
|
|
897
|
-
end
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
934
|
+
raise LoweringError.new("unsupported expression type #{expression.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
935
|
+
end
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
def infer_binary_operand_types(expression, env:, expected_type: nil)
|
|
939
|
+
propagated_type = propagating_expected_type(expression.operator, expected_type)
|
|
940
|
+
left_type = infer_expression_type(expression.left, env:, expected_type: propagated_type)
|
|
941
|
+
right_env = binary_right_env(expression, env)
|
|
942
|
+
right_expected_type = case expression.operator
|
|
943
|
+
when "<<", ">>"
|
|
944
|
+
propagated_type || left_type
|
|
945
|
+
when "+", "-", "*", "/", "%"
|
|
946
|
+
propagated_type || left_type
|
|
947
|
+
when "|", "&", "^"
|
|
948
|
+
left_type
|
|
949
|
+
else
|
|
950
|
+
left_type
|
|
951
|
+
end
|
|
952
|
+
right_type = infer_expression_type(expression.right, env: right_env, expected_type: right_expected_type)
|
|
953
|
+
left_type, right_type = harmonize_binary_float_literal_types(expression.left, expression.right, left_type, right_type, env: right_env)
|
|
954
|
+
harmonize_binary_integer_literal_types(expression.left, expression.right, left_type, right_type, env: right_env)
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
def binary_right_env(expression, env)
|
|
958
|
+
case expression.operator
|
|
959
|
+
when "and"
|
|
960
|
+
env_with_refinements(env, flow_refinements(expression.left, truthy: true, env:))
|
|
961
|
+
when "or"
|
|
962
|
+
env_with_refinements(env, flow_refinements(expression.left, truthy: false, env:))
|
|
911
963
|
else
|
|
912
|
-
|
|
913
|
-
end
|
|
914
|
-
when AST::RangeExpr
|
|
915
|
-
raise LoweringError.new("range expression is not valid in this context; use it as a for-loop iterable", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
916
|
-
when AST::ExpressionList
|
|
917
|
-
names = []
|
|
918
|
-
element_types = []
|
|
919
|
-
expression.elements.each do |element|
|
|
920
|
-
if element.is_a?(AST::Argument)
|
|
921
|
-
names << element.name
|
|
922
|
-
element_types << infer_expression_type(element.value, env:)
|
|
923
|
-
else
|
|
924
|
-
names << nil
|
|
925
|
-
element_types << infer_expression_type(element, env:)
|
|
926
|
-
end
|
|
964
|
+
env
|
|
927
965
|
end
|
|
928
|
-
has_named = names.any?
|
|
929
|
-
Types::Registry.tuple(element_types, field_names: has_named ? names : nil)
|
|
930
|
-
when AST::DetachExpr
|
|
931
|
-
Types::Handle.new
|
|
932
|
-
else
|
|
933
|
-
raise LoweringError.new("unsupported expression type #{expression.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
934
966
|
end
|
|
935
|
-
end
|
|
936
967
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
right_expected_type = case expression.operator
|
|
942
|
-
when "<<", ">>"
|
|
943
|
-
propagated_type || left_type
|
|
944
|
-
when "+", "-", "*", "/", "%"
|
|
945
|
-
propagated_type || left_type
|
|
946
|
-
when "|", "&", "^"
|
|
947
|
-
left_type
|
|
948
|
-
else
|
|
949
|
-
left_type
|
|
950
|
-
end
|
|
951
|
-
right_type = infer_expression_type(expression.right, env: right_env, expected_type: right_expected_type)
|
|
952
|
-
left_type, right_type = harmonize_binary_float_literal_types(expression.left, expression.right, left_type, right_type, env: right_env)
|
|
953
|
-
harmonize_binary_integer_literal_types(expression.left, expression.right, left_type, right_type, env: right_env)
|
|
954
|
-
end
|
|
968
|
+
def harmonize_binary_float_literal_types(left_expression, right_expression, left_type, right_type, env:)
|
|
969
|
+
if float_literal_expression?(left_expression) && right_type.is_a?(Types::Primitive) && right_type.float?
|
|
970
|
+
left_type = infer_expression_type(left_expression, env:, expected_type: right_type)
|
|
971
|
+
end
|
|
955
972
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
env_with_refinements(env, flow_refinements(expression.left, truthy: true, env:))
|
|
960
|
-
when "or"
|
|
961
|
-
env_with_refinements(env, flow_refinements(expression.left, truthy: false, env:))
|
|
962
|
-
else
|
|
963
|
-
env
|
|
964
|
-
end
|
|
965
|
-
end
|
|
973
|
+
if float_literal_expression?(right_expression) && left_type.is_a?(Types::Primitive) && left_type.float?
|
|
974
|
+
right_type = infer_expression_type(right_expression, env:, expected_type: left_type)
|
|
975
|
+
end
|
|
966
976
|
|
|
967
|
-
|
|
968
|
-
if float_literal_expression?(left_expression) && right_type.is_a?(Types::Primitive) && right_type.float?
|
|
969
|
-
left_type = infer_expression_type(left_expression, env:, expected_type: right_type)
|
|
977
|
+
[left_type, right_type]
|
|
970
978
|
end
|
|
971
979
|
|
|
972
|
-
|
|
973
|
-
|
|
980
|
+
def float_literal_expression?(expression)
|
|
981
|
+
expression.is_a?(AST::FloatLiteral) ||
|
|
982
|
+
(expression.is_a?(AST::UnaryOp) && ["+", "-"].include?(expression.operator) && float_literal_expression?(expression.operand))
|
|
974
983
|
end
|
|
975
984
|
|
|
976
|
-
|
|
977
|
-
|
|
985
|
+
def harmonize_binary_integer_literal_types(left_expression, right_expression, left_type, right_type, env:)
|
|
986
|
+
if integer_literal_expression?(left_expression) && right_type.is_a?(Types::Primitive) && right_type.integer?
|
|
987
|
+
if exact_compile_time_numeric_compatibility?(left_type, left_expression, right_type, env:)
|
|
988
|
+
left_type = infer_expression_type(left_expression, env:, expected_type: right_type)
|
|
989
|
+
end
|
|
990
|
+
end
|
|
978
991
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
992
|
+
if integer_literal_expression?(right_expression) && left_type.is_a?(Types::Primitive) && left_type.integer?
|
|
993
|
+
if exact_compile_time_numeric_compatibility?(right_type, right_expression, left_type, env:)
|
|
994
|
+
right_type = infer_expression_type(right_expression, env:, expected_type: left_type)
|
|
995
|
+
end
|
|
996
|
+
end
|
|
983
997
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
998
|
+
[left_type, right_type]
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
def integer_literal_expression?(expression)
|
|
1002
|
+
expression.is_a?(AST::IntegerLiteral)
|
|
1003
|
+
end
|
|
1004
|
+
|
|
1005
|
+
def propagating_expected_type(operator, expected_type)
|
|
1006
|
+
case operator
|
|
1007
|
+
when "+", "-", "*", "/", "%", "<<", ">>"
|
|
1008
|
+
return expected_type if expected_type.is_a?(Types::Primitive) && expected_type.numeric?
|
|
1009
|
+
when "|", "&", "^"
|
|
1010
|
+
return expected_type if expected_type.is_a?(Types::Primitive) && expected_type.integer?
|
|
1011
|
+
return expected_type if expected_type.is_a?(Types::Flags)
|
|
988
1012
|
end
|
|
1013
|
+
|
|
1014
|
+
nil
|
|
989
1015
|
end
|
|
990
1016
|
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1017
|
+
def promoted_binary_operand_type(operator, left_type, right_type)
|
|
1018
|
+
case operator
|
|
1019
|
+
when "+", "-", "*", "/", "<", "<=", ">", ">=", "==", "!="
|
|
1020
|
+
common_numeric_type(left_type, right_type)
|
|
1021
|
+
when "%"
|
|
1022
|
+
common_integer_type(left_type, right_type)
|
|
994
1023
|
end
|
|
995
1024
|
end
|
|
996
1025
|
|
|
997
|
-
|
|
998
|
-
|
|
1026
|
+
def cast_expression(expression, target_type)
|
|
1027
|
+
return expression if expression.type == target_type
|
|
999
1028
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1029
|
+
IR::Cast.new(target_type:, expression:, type: target_type)
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
def pointer_lowered_sync_method_receiver?(binding)
|
|
1033
|
+
return false if binding.async
|
|
1003
1034
|
|
|
1004
|
-
|
|
1005
|
-
case operator
|
|
1006
|
-
when "+", "-", "*", "/", "%", "<<", ">>"
|
|
1007
|
-
return expected_type if expected_type.is_a?(Types::Primitive) && expected_type.numeric?
|
|
1008
|
-
when "|", "&", "^"
|
|
1009
|
-
return expected_type if expected_type.is_a?(Types::Primitive) && expected_type.integer?
|
|
1010
|
-
return expected_type if expected_type.is_a?(Types::Flags)
|
|
1035
|
+
pointer_lowered_method_receiver?(binding.type, binding)
|
|
1011
1036
|
end
|
|
1012
1037
|
|
|
1013
|
-
|
|
1014
|
-
|
|
1038
|
+
def pointer_lowered_method_receiver?(callee_type, callee_binding)
|
|
1039
|
+
return true if callee_type.receiver_editable
|
|
1015
1040
|
|
|
1016
|
-
|
|
1017
|
-
case operator
|
|
1018
|
-
when "+", "-", "*", "/", "<", "<=", ">", ">=", "==", "!="
|
|
1019
|
-
common_numeric_type(left_type, right_type)
|
|
1020
|
-
when "%"
|
|
1021
|
-
common_integer_type(left_type, right_type)
|
|
1041
|
+
receiver_type_uses_pointer_lowering?(callee_type.receiver_type) && !callee_binding&.async
|
|
1022
1042
|
end
|
|
1023
|
-
end
|
|
1024
1043
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1044
|
+
def receiver_type_uses_pointer_lowering?(type)
|
|
1045
|
+
case type
|
|
1046
|
+
when Types::Nullable
|
|
1047
|
+
receiver_type_uses_pointer_lowering?(type.base)
|
|
1048
|
+
when Types::Struct, Types::StructInstance
|
|
1049
|
+
type_contains_array_storage?(type)
|
|
1050
|
+
else
|
|
1051
|
+
false
|
|
1052
|
+
end
|
|
1053
|
+
end
|
|
1027
1054
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1055
|
+
def type_contains_array_storage?(type, visited = Set.new)
|
|
1056
|
+
visitor = Types::ContainsArrayStorageVisitor.new
|
|
1057
|
+
visitor.visit(type)
|
|
1058
|
+
visitor.found?
|
|
1059
|
+
end
|
|
1030
1060
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1061
|
+
def reinterpret_expression(expression, target_type)
|
|
1062
|
+
return expression if expression.type == target_type
|
|
1033
1063
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1064
|
+
IR::ReinterpretExpr.new(target_type:, source_type: expression.type, expression:, type: target_type)
|
|
1065
|
+
end
|
|
1036
1066
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1067
|
+
def foreign_identity_projection_expression(expression, target_type)
|
|
1068
|
+
return expression if expression.type == target_type
|
|
1069
|
+
return cast_expression(expression, target_type) if foreign_identity_projection_cast_compatible?(expression.type, target_type)
|
|
1039
1070
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1071
|
+
if foreign_identity_projection_reinterpret_compatible?(expression.type, target_type)
|
|
1072
|
+
record_external_layout_assertion(expression.type, target_type)
|
|
1073
|
+
return reinterpret_expression(expression, target_type)
|
|
1074
|
+
end
|
|
1042
1075
|
|
|
1043
|
-
|
|
1044
|
-
case type
|
|
1045
|
-
when Types::Nullable
|
|
1046
|
-
receiver_type_uses_pointer_lowering?(type.base)
|
|
1047
|
-
when Types::Struct, Types::StructInstance
|
|
1048
|
-
type_contains_array_storage?(type)
|
|
1049
|
-
else
|
|
1050
|
-
false
|
|
1076
|
+
nil
|
|
1051
1077
|
end
|
|
1052
|
-
end
|
|
1053
1078
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1079
|
+
def record_external_layout_assertion(source_type, target_type)
|
|
1080
|
+
source_root = ffi_external_layout_root_type(source_type)
|
|
1081
|
+
target_root = ffi_external_layout_root_type(target_type)
|
|
1082
|
+
return unless source_root && target_root
|
|
1083
|
+
return unless source_root.external && target_root.external
|
|
1084
|
+
return if source_root.module_name == target_root.module_name
|
|
1059
1085
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1086
|
+
pair_key = [[source_root.module_name, source_root.name], [target_root.module_name, target_root.name]].sort.freeze
|
|
1087
|
+
return if @artifacts.emitted_external_layout_pairs[pair_key]
|
|
1062
1088
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1089
|
+
@artifacts.emitted_external_layout_pairs[pair_key] = true
|
|
1090
|
+
@artifacts.external_layout_assertions << IR::StaticAssert.new(
|
|
1091
|
+
condition: IR::Binary.new(
|
|
1092
|
+
operator: "==",
|
|
1093
|
+
left: IR::SizeofExpr.new(target_type: source_root, type: @ctx.types.fetch("ptr_uint")),
|
|
1094
|
+
right: IR::SizeofExpr.new(target_type: target_root, type: @ctx.types.fetch("ptr_uint")),
|
|
1095
|
+
type: @ctx.types.fetch("bool"),
|
|
1096
|
+
),
|
|
1097
|
+
message: IR::StringLiteral.new(
|
|
1098
|
+
value: "FFI layout mismatch: #{source_root} vs #{target_root}",
|
|
1099
|
+
type: @ctx.types.fetch("str"),
|
|
1100
|
+
cstring: false,
|
|
1101
|
+
),
|
|
1102
|
+
)
|
|
1103
|
+
end
|
|
1065
1104
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1105
|
+
def ffi_external_layout_root_type(type)
|
|
1106
|
+
type = type.base while type.is_a?(Types::Nullable)
|
|
1107
|
+
return pointee_type(type) if pointer_type?(type)
|
|
1069
1108
|
|
|
1070
|
-
|
|
1071
|
-
record_external_layout_assertion(expression.type, target_type)
|
|
1072
|
-
return reinterpret_expression(expression, target_type)
|
|
1109
|
+
type
|
|
1073
1110
|
end
|
|
1074
1111
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1112
|
+
def infer_null_literal_type(expression, expected_type)
|
|
1113
|
+
return Types::Null.new(resolve_type_ref(expression.type)) if expression.type
|
|
1077
1114
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
target_root = ffi_external_layout_root_type(target_type)
|
|
1081
|
-
return unless source_root && target_root
|
|
1082
|
-
return unless source_root.external && target_root.external
|
|
1083
|
-
return if source_root.module_name == target_root.module_name
|
|
1084
|
-
|
|
1085
|
-
pair_key = [[source_root.module_name, source_root.name], [target_root.module_name, target_root.name]].sort.freeze
|
|
1086
|
-
return if @artifacts.emitted_external_layout_pairs[pair_key]
|
|
1087
|
-
|
|
1088
|
-
@artifacts.emitted_external_layout_pairs[pair_key] = true
|
|
1089
|
-
@artifacts.external_layout_assertions << IR::StaticAssert.new(
|
|
1090
|
-
condition: IR::Binary.new(
|
|
1091
|
-
operator: "==",
|
|
1092
|
-
left: IR::SizeofExpr.new(target_type: source_root, type: @ctx.types.fetch("ptr_uint")),
|
|
1093
|
-
right: IR::SizeofExpr.new(target_type: target_root, type: @ctx.types.fetch("ptr_uint")),
|
|
1094
|
-
type: @ctx.types.fetch("bool"),
|
|
1095
|
-
),
|
|
1096
|
-
message: IR::StringLiteral.new(
|
|
1097
|
-
value: "FFI layout mismatch: #{source_root} vs #{target_root}",
|
|
1098
|
-
type: @ctx.types.fetch("str"),
|
|
1099
|
-
cstring: false,
|
|
1100
|
-
),
|
|
1101
|
-
)
|
|
1102
|
-
end
|
|
1115
|
+
expected_type || null_type
|
|
1116
|
+
end
|
|
1103
1117
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1118
|
+
def common_numeric_type(left_type, right_type)
|
|
1119
|
+
left_type = left_type.backing_type if left_type.is_a?(Types::EnumBase)
|
|
1120
|
+
right_type = right_type.backing_type if right_type.is_a?(Types::EnumBase)
|
|
1121
|
+
return left_type if left_type == right_type
|
|
1122
|
+
return unless left_type.is_a?(Types::Primitive) && right_type.is_a?(Types::Primitive)
|
|
1123
|
+
return unless left_type.numeric? && right_type.numeric?
|
|
1107
1124
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1125
|
+
return common_integer_type(left_type, right_type) if left_type.integer? && right_type.integer?
|
|
1126
|
+
return wider_float_type(left_type, right_type) if left_type.float? && right_type.float?
|
|
1110
1127
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1128
|
+
float_type, integer_type = left_type.float? ? [left_type, right_type] : [right_type, left_type]
|
|
1129
|
+
return unless integer_type.integer? && integer_type.fixed_width_integer?
|
|
1113
1130
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1131
|
+
float_type
|
|
1132
|
+
end
|
|
1116
1133
|
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1134
|
+
def common_integer_type(left_type, right_type)
|
|
1135
|
+
left_type = left_type.backing_type if left_type.is_a?(Types::EnumBase)
|
|
1136
|
+
right_type = right_type.backing_type if right_type.is_a?(Types::EnumBase)
|
|
1137
|
+
return left_type if left_type == right_type
|
|
1138
|
+
return unless left_type.is_a?(Types::Primitive) && right_type.is_a?(Types::Primitive)
|
|
1139
|
+
return unless left_type.integer? && right_type.integer?
|
|
1140
|
+
return unless left_type.fixed_width_integer? && right_type.fixed_width_integer?
|
|
1123
1141
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1142
|
+
# Mirrors the semantic analyzer's rule: same signedness picks the wider
|
|
1143
|
+
# type; mixed signed/unsigned promotes to the narrowest signed type that
|
|
1144
|
+
# holds both operands' full ranges (a strictly-wider signed type covers
|
|
1145
|
+
# an unsigned operand, otherwise widen to the next signed width). Mixing
|
|
1146
|
+
# with a 64-bit unsigned type has no safe signed common type.
|
|
1147
|
+
if left_type.signed_integer? == right_type.signed_integer?
|
|
1148
|
+
return left_type.integer_width >= right_type.integer_width ? left_type : right_type
|
|
1149
|
+
end
|
|
1126
1150
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1151
|
+
signed_type, unsigned_type = if left_type.signed_integer?
|
|
1152
|
+
[left_type, right_type]
|
|
1153
|
+
else
|
|
1154
|
+
[right_type, left_type]
|
|
1155
|
+
end
|
|
1129
1156
|
|
|
1130
|
-
|
|
1131
|
-
end
|
|
1157
|
+
return signed_type if signed_type.integer_width > unsigned_type.integer_width
|
|
1132
1158
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
right_type = right_type.backing_type if right_type.is_a?(Types::EnumBase)
|
|
1136
|
-
return left_type if left_type == right_type
|
|
1137
|
-
return unless left_type.is_a?(Types::Primitive) && right_type.is_a?(Types::Primitive)
|
|
1138
|
-
return unless left_type.integer? && right_type.integer?
|
|
1139
|
-
return unless left_type.fixed_width_integer? && right_type.fixed_width_integer?
|
|
1159
|
+
signed_type_above_width(unsigned_type.integer_width)
|
|
1160
|
+
end
|
|
1140
1161
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
return left_type.integer_width >= right_type.integer_width ? left_type : right_type
|
|
1162
|
+
def signed_type_above_width(width)
|
|
1163
|
+
case width
|
|
1164
|
+
when 8 then @ctx.types.fetch("short")
|
|
1165
|
+
when 16 then @ctx.types.fetch("int")
|
|
1166
|
+
when 32 then @ctx.types.fetch("long")
|
|
1167
|
+
end
|
|
1148
1168
|
end
|
|
1149
1169
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
else
|
|
1153
|
-
[right_type, left_type]
|
|
1170
|
+
def wider_float_type(left_type, right_type)
|
|
1171
|
+
left_type.float_width >= right_type.float_width ? left_type : right_type
|
|
1154
1172
|
end
|
|
1155
1173
|
|
|
1156
|
-
|
|
1174
|
+
def aggregate_arithmetic_result_type(operator, left_type, right_type)
|
|
1175
|
+
if left_type.is_a?(Types::Vector) && right_type.is_a?(Types::Vector) && left_type.name == right_type.name
|
|
1176
|
+
return left_type
|
|
1177
|
+
end
|
|
1178
|
+
if left_type.is_a?(Types::Matrix) && right_type.is_a?(Types::Matrix) && left_type.name == right_type.name
|
|
1179
|
+
return left_type
|
|
1180
|
+
end
|
|
1181
|
+
if left_type.is_a?(Types::Quaternion) && right_type.is_a?(Types::Quaternion)
|
|
1182
|
+
return left_type
|
|
1183
|
+
end
|
|
1157
1184
|
|
|
1158
|
-
|
|
1159
|
-
|
|
1185
|
+
scalar_result = aggregate_scalar_result(left_type, right_type)
|
|
1186
|
+
return scalar_result if scalar_result
|
|
1160
1187
|
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1188
|
+
case operator
|
|
1189
|
+
when "+", "-"
|
|
1190
|
+
nil
|
|
1191
|
+
when "*", "/"
|
|
1192
|
+
aggregate_scalar_result(right_type, left_type)
|
|
1193
|
+
else
|
|
1194
|
+
nil
|
|
1195
|
+
end
|
|
1166
1196
|
end
|
|
1167
|
-
end
|
|
1168
1197
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1198
|
+
def aggregate_scalar_result(aggregate_type, scalar_type)
|
|
1199
|
+
return nil unless aggregate_type.is_a?(Types::Vector) || aggregate_type.is_a?(Types::Matrix)
|
|
1200
|
+
return nil unless scalar_type.is_a?(Types::Primitive) && scalar_type.numeric?
|
|
1172
1201
|
|
|
1173
|
-
|
|
1174
|
-
if left_type.is_a?(Types::Vector) && right_type.is_a?(Types::Vector) && left_type.name == right_type.name
|
|
1175
|
-
return left_type
|
|
1176
|
-
end
|
|
1177
|
-
if left_type.is_a?(Types::Matrix) && right_type.is_a?(Types::Matrix) && left_type.name == right_type.name
|
|
1178
|
-
return left_type
|
|
1179
|
-
end
|
|
1180
|
-
if left_type.is_a?(Types::Quaternion) && right_type.is_a?(Types::Quaternion)
|
|
1181
|
-
return left_type
|
|
1202
|
+
aggregate_type
|
|
1182
1203
|
end
|
|
1183
1204
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1205
|
+
def pointer_arithmetic_result_type(operator, left_type, right_type)
|
|
1206
|
+
return left_type if pointer_type?(left_type) && integer_type?(right_type) && (operator == "+" || operator == "-")
|
|
1207
|
+
return right_type if operator == "+" && integer_type?(left_type) && pointer_type?(right_type)
|
|
1186
1208
|
|
|
1187
|
-
case operator
|
|
1188
|
-
when "+", "-"
|
|
1189
|
-
nil
|
|
1190
|
-
when "*", "/"
|
|
1191
|
-
aggregate_scalar_result(right_type, left_type)
|
|
1192
|
-
else
|
|
1193
1209
|
nil
|
|
1194
1210
|
end
|
|
1195
|
-
end
|
|
1196
1211
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1212
|
+
def resolve_type_expression(expression)
|
|
1213
|
+
case expression
|
|
1214
|
+
when AST::Identifier
|
|
1215
|
+
return current_type_params[expression.name] if current_type_params.key?(expression.name)
|
|
1200
1216
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1217
|
+
@ctx.types[expression.name]
|
|
1218
|
+
when AST::MemberAccess
|
|
1219
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
1203
1220
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
nil
|
|
1209
|
-
end
|
|
1221
|
+
if @ctx.imports.key?(expression.receiver.name)
|
|
1222
|
+
return @ctx.imports.fetch(expression.receiver.name).types[expression.member]
|
|
1223
|
+
end
|
|
1210
1224
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
when AST::Identifier
|
|
1214
|
-
return current_type_params[expression.name] if current_type_params.key?(expression.name)
|
|
1225
|
+
parent_type = @ctx.types[expression.receiver.name]
|
|
1226
|
+
return parent_type.nested_types[expression.member] if parent_type.respond_to?(:nested_types) && parent_type.nested_types.key?(expression.member)
|
|
1215
1227
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1228
|
+
nil
|
|
1229
|
+
when AST::Specialization
|
|
1230
|
+
type_ref = type_ref_from_specialization(expression)
|
|
1231
|
+
return nil unless type_ref
|
|
1219
1232
|
|
|
1220
|
-
|
|
1221
|
-
return @ctx.imports.fetch(expression.receiver.name).types[expression.member]
|
|
1233
|
+
resolve_type_ref(type_ref)
|
|
1222
1234
|
end
|
|
1223
|
-
|
|
1224
|
-
parent_type = @ctx.types[expression.receiver.name]
|
|
1225
|
-
return parent_type.nested_types[expression.member] if parent_type.respond_to?(:nested_types) && parent_type.nested_types.key?(expression.member)
|
|
1226
|
-
|
|
1227
|
-
nil
|
|
1228
|
-
when AST::Specialization
|
|
1229
|
-
type_ref = type_ref_from_specialization(expression)
|
|
1230
|
-
return nil unless type_ref
|
|
1231
|
-
|
|
1232
|
-
resolve_type_ref(type_ref)
|
|
1233
1235
|
end
|
|
1234
|
-
end
|
|
1235
1236
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1237
|
+
def resolve_type_member(type, name)
|
|
1238
|
+
case type
|
|
1239
|
+
when Types::Enum, Types::Flags
|
|
1240
|
+
type.member(name)
|
|
1241
|
+
when Types::Variant
|
|
1242
|
+
type if type.arm_names.include?(name)
|
|
1243
|
+
end
|
|
1242
1244
|
end
|
|
1243
|
-
end
|
|
1244
1245
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1246
|
+
def function_type_for_name(name)
|
|
1247
|
+
binding = @ctx.functions.fetch(name)
|
|
1248
|
+
raise LoweringError.new("generic function #{name} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if binding.type_params.any?
|
|
1249
|
+
raise LoweringError.new("foreign function #{name} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_function_binding?(binding)
|
|
1249
1250
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1251
|
+
binding.type
|
|
1252
|
+
end
|
|
1252
1253
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1254
|
+
def resolve_specialized_callable_binding(expression, env:)
|
|
1255
|
+
callable_kind = :function
|
|
1256
|
+
receiver = nil
|
|
1257
|
+
receiver_type = nil
|
|
1258
|
+
binding = case expression.callee
|
|
1259
|
+
when AST::Identifier
|
|
1260
|
+
@ctx.functions[expression.callee.name]
|
|
1261
|
+
when AST::MemberAccess
|
|
1262
|
+
if expression.callee.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(expression.callee.receiver.name)
|
|
1263
|
+
@ctx.imports.fetch(expression.callee.receiver.name).functions[expression.callee.member]
|
|
1264
|
+
elsif (type_expr = resolve_type_expression(expression.callee.receiver))
|
|
1265
|
+
dispatch_receiver_type = method_dispatch_receiver_type(type_expr)
|
|
1266
|
+
method_entry_receiver_type = type_expr
|
|
1267
|
+
method_entry = @method_definitions[[type_expr, expression.callee.member]]
|
|
1268
|
+
method_entry ||= @method_definitions[[type_expr, "static:#{expression.callee.member}"]]
|
|
1269
|
+
unless method_entry || dispatch_receiver_type == type_expr
|
|
1270
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
1271
|
+
method_entry = @method_definitions[[dispatch_receiver_type, expression.callee.member]]
|
|
1272
|
+
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{expression.callee.member}"]]
|
|
1273
|
+
end
|
|
1274
|
+
if method_entry
|
|
1275
|
+
method_analysis, method_ast = method_entry
|
|
1276
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
1277
|
+
if method_binding.type.receiver_type.nil?
|
|
1278
|
+
receiver_type = type_expr
|
|
1279
|
+
method_binding
|
|
1280
|
+
end
|
|
1281
|
+
end
|
|
1282
|
+
else
|
|
1283
|
+
resolved_receiver_type = infer_method_receiver_type(expression.callee.receiver, env:, member_name: expression.callee.member)
|
|
1284
|
+
dispatch_receiver_type = method_dispatch_receiver_type(resolved_receiver_type)
|
|
1285
|
+
method_entry_receiver_type = resolved_receiver_type
|
|
1286
|
+
method_entry = @method_definitions[[resolved_receiver_type, expression.callee.member]]
|
|
1287
|
+
unless method_entry || dispatch_receiver_type == resolved_receiver_type
|
|
1288
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
1289
|
+
method_entry = @method_definitions[[dispatch_receiver_type, expression.callee.member]]
|
|
1290
|
+
end
|
|
1291
|
+
if method_entry
|
|
1292
|
+
method_analysis, method_ast = method_entry
|
|
1293
|
+
callable_kind = :method
|
|
1294
|
+
receiver = expression.callee.receiver
|
|
1295
|
+
receiver_type = resolved_receiver_type
|
|
1296
|
+
method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
1279
1297
|
end
|
|
1280
|
-
end
|
|
1281
|
-
else
|
|
1282
|
-
resolved_receiver_type = infer_method_receiver_type(expression.callee.receiver, env:, member_name: expression.callee.member)
|
|
1283
|
-
dispatch_receiver_type = method_dispatch_receiver_type(resolved_receiver_type)
|
|
1284
|
-
method_entry_receiver_type = resolved_receiver_type
|
|
1285
|
-
method_entry = @method_definitions[[resolved_receiver_type, expression.callee.member]]
|
|
1286
|
-
unless method_entry || dispatch_receiver_type == resolved_receiver_type
|
|
1287
|
-
method_entry_receiver_type = dispatch_receiver_type
|
|
1288
|
-
method_entry = @method_definitions[[dispatch_receiver_type, expression.callee.member]]
|
|
1289
|
-
end
|
|
1290
|
-
if method_entry
|
|
1291
|
-
method_analysis, method_ast = method_entry
|
|
1292
|
-
callable_kind = :method
|
|
1293
|
-
receiver = expression.callee.receiver
|
|
1294
|
-
receiver_type = resolved_receiver_type
|
|
1295
|
-
method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
1296
1298
|
end
|
|
1297
1299
|
end
|
|
1298
|
-
|
|
1299
|
-
return nil unless binding
|
|
1300
|
+
return nil unless binding
|
|
1300
1301
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1302
|
+
type_arguments = resolve_specialization_type_arguments(expression)
|
|
1303
|
+
[callable_kind, instantiate_function_binding_with_receiver(binding, type_arguments, receiver_type:), receiver, method_entry_receiver_type]
|
|
1304
|
+
end
|
|
1304
1305
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1306
|
+
def resolve_default_specialization(expression, env:)
|
|
1307
|
+
target_type = resolve_type_ref(expression.arguments.fetch(0).value)
|
|
1307
1308
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1309
|
+
explicit_default = resolve_explicit_default_binding(target_type, context: "default[#{target_type}]")
|
|
1310
|
+
raise LoweringError.new("default[#{target_type}] requires associated function #{target_type}.default()", line: 0, column: 0, path: @ctx.current_analysis_path) unless explicit_default
|
|
1310
1311
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1312
|
+
DefaultResolution.new(target_type:, binding: explicit_default.binding, callee_name: explicit_default.callee_name)
|
|
1313
|
+
end
|
|
1313
1314
|
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1315
|
+
def resolve_hash_specialization(expression, env:)
|
|
1316
|
+
target_type = resolve_type_ref(expression.arguments.fetch(0).value)
|
|
1317
|
+
explicit_hash = resolve_explicit_hash_binding(target_type, context: "hash[#{target_type}]")
|
|
1318
|
+
raise LoweringError.new("hash[#{target_type}] requires associated function #{target_type}.hash(value: const_ptr[#{target_type}]) -> uint", line: 0, column: 0, path: @ctx.current_analysis_path) unless explicit_hash
|
|
1318
1319
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1320
|
+
HashResolution.new(target_type:, binding: explicit_hash.binding, callee_name: explicit_hash.callee_name)
|
|
1321
|
+
end
|
|
1321
1322
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1323
|
+
def resolve_equal_specialization(expression, env:)
|
|
1324
|
+
target_type = resolve_type_ref(expression.arguments.fetch(0).value)
|
|
1325
|
+
explicit_equal = resolve_explicit_equal_binding(target_type, context: "equal[#{target_type}]")
|
|
1326
|
+
raise LoweringError.new("equal[#{target_type}] requires associated function #{target_type}.equal(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> bool", line: 0, column: 0, path: @ctx.current_analysis_path) unless explicit_equal
|
|
1326
1327
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1328
|
+
EqualResolution.new(target_type:, binding: explicit_equal.binding, callee_name: explicit_equal.callee_name)
|
|
1329
|
+
end
|
|
1329
1330
|
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1331
|
+
def resolve_order_specialization(expression, env:)
|
|
1332
|
+
target_type = resolve_type_ref(expression.arguments.fetch(0).value)
|
|
1333
|
+
explicit_order = resolve_explicit_order_binding(target_type, context: "order[#{target_type}]")
|
|
1334
|
+
raise LoweringError.new("order[#{target_type}] requires associated function #{target_type}.order(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> int", line: 0, column: 0, path: @ctx.current_analysis_path) unless explicit_order
|
|
1334
1335
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1336
|
+
OrderResolution.new(target_type:, binding: explicit_order.binding, callee_name: explicit_order.callee_name)
|
|
1337
|
+
end
|
|
1337
1338
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1339
|
+
def resolve_explicit_default_binding(target_type, context:)
|
|
1340
|
+
requirement_message = "#{context} requires associated function #{target_type}.default()"
|
|
1341
|
+
resolve_explicit_associated_binding(target_type, "default", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1342
|
+
raise LoweringError.new("#{context} requires #{target_type}.default() to take 0 arguments", line: 0, column: 0, path: @ctx.current_analysis_path) unless method_binding.type.params.empty?
|
|
1343
|
+
unless method_binding.type.return_type == target_type
|
|
1344
|
+
raise LoweringError.new("#{context} requires #{target_type}.default() to return #{target_type}, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1345
|
+
end
|
|
1344
1346
|
end
|
|
1345
1347
|
end
|
|
1346
|
-
end
|
|
1347
1348
|
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1349
|
+
def resolve_explicit_hash_binding(target_type, context:)
|
|
1350
|
+
requirement_message = "#{context} requires associated function #{target_type}.hash(value: const_ptr[#{target_type}]) -> uint"
|
|
1351
|
+
resolve_explicit_associated_binding(target_type, "hash", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1352
|
+
unless method_binding.type.params.map(&:type) == [const_pointer_to(target_type)]
|
|
1353
|
+
raise LoweringError.new("#{context} requires #{target_type}.hash(value: const_ptr[#{target_type}]) -> uint", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1354
|
+
end
|
|
1355
|
+
unless method_binding.type.return_type == @ctx.types.fetch("uint")
|
|
1356
|
+
raise LoweringError.new("#{context} requires #{target_type}.hash(value: const_ptr[#{target_type}]) -> uint, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1357
|
+
end
|
|
1356
1358
|
end
|
|
1357
1359
|
end
|
|
1358
|
-
end
|
|
1359
1360
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1361
|
+
def resolve_explicit_equal_binding(target_type, context:)
|
|
1362
|
+
requirement_message = "#{context} requires associated function #{target_type}.equal(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> bool"
|
|
1363
|
+
resolve_explicit_associated_binding(target_type, "equal", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1364
|
+
expected_param_types = [const_pointer_to(target_type), const_pointer_to(target_type)]
|
|
1365
|
+
unless method_binding.type.params.map(&:type) == expected_param_types
|
|
1366
|
+
raise LoweringError.new("#{context} requires #{target_type}.equal(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> bool", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1367
|
+
end
|
|
1368
|
+
unless method_binding.type.return_type == @ctx.types.fetch("bool")
|
|
1369
|
+
raise LoweringError.new("#{context} requires #{target_type}.equal(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> bool, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1370
|
+
end
|
|
1369
1371
|
end
|
|
1370
1372
|
end
|
|
1371
|
-
end
|
|
1372
1373
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1374
|
+
def resolve_explicit_order_binding(target_type, context:)
|
|
1375
|
+
requirement_message = "#{context} requires associated function #{target_type}.order(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> int"
|
|
1376
|
+
resolve_explicit_associated_binding(target_type, "order", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1377
|
+
expected_param_types = [const_pointer_to(target_type), const_pointer_to(target_type)]
|
|
1378
|
+
unless method_binding.type.params.map(&:type) == expected_param_types
|
|
1379
|
+
raise LoweringError.new("#{context} requires #{target_type}.order(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> int", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1380
|
+
end
|
|
1381
|
+
unless method_binding.type.return_type == @ctx.types.fetch("int")
|
|
1382
|
+
raise LoweringError.new("#{context} requires #{target_type}.order(left: const_ptr[#{target_type}], right: const_ptr[#{target_type}]) -> int, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1383
|
+
end
|
|
1382
1384
|
end
|
|
1383
1385
|
end
|
|
1384
|
-
end
|
|
1385
1386
|
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1387
|
+
def resolve_explicit_format_binding(target_type, context:)
|
|
1388
|
+
length_binding = resolve_explicit_format_len_binding(target_type, context:)
|
|
1389
|
+
append_binding = resolve_explicit_format_append_binding(target_type, context:)
|
|
1389
1390
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1391
|
+
return ExplicitFormatBinding.new(
|
|
1392
|
+
length_binding: length_binding.fetch(:binding),
|
|
1393
|
+
length_callee_name: length_binding.fetch(:callee_name),
|
|
1394
|
+
append_binding: append_binding.fetch(:binding),
|
|
1395
|
+
append_callee_name: append_binding.fetch(:callee_name),
|
|
1396
|
+
) if length_binding && append_binding
|
|
1396
1397
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1398
|
+
if length_binding || append_binding
|
|
1399
|
+
raise LoweringError.new("#{context} requires methods #{target_type}.format_len() -> ptr_uint and #{target_type}.append_format(output: ref[std.string.String]) -> void", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1400
|
+
end
|
|
1400
1401
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1402
|
+
nil
|
|
1403
|
+
end
|
|
1403
1404
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1405
|
+
def resolve_explicit_format_len_binding(target_type, context:)
|
|
1406
|
+
requirement_message = "#{context} requires method #{target_type}.format_len() -> ptr_uint"
|
|
1407
|
+
resolve_explicit_instance_binding(target_type, "format_len", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1408
|
+
raise LoweringError.new("#{context} requires #{target_type}.format_len() to take 0 arguments", line: 0, column: 0, path: @ctx.current_analysis_path) unless method_binding.type.params.empty?
|
|
1409
|
+
raise LoweringError.new("#{context} requires #{target_type}.format_len() to be non-editable", line: 0, column: 0, path: @ctx.current_analysis_path) if method_binding.type.receiver_editable
|
|
1410
|
+
unless method_binding.type.return_type == @ctx.types.fetch("ptr_uint")
|
|
1411
|
+
raise LoweringError.new("#{context} requires #{target_type}.format_len() -> ptr_uint, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1412
|
+
end
|
|
1411
1413
|
end
|
|
1412
1414
|
end
|
|
1413
|
-
end
|
|
1414
1415
|
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1416
|
+
def resolve_explicit_format_append_binding(target_type, context:)
|
|
1417
|
+
requirement_message = "#{context} requires method #{target_type}.append_format(output: ref[std.string.String]) -> void"
|
|
1418
|
+
resolve_explicit_instance_binding(target_type, "append_format", requirement_message:) do |method_binding, _method_analysis, _method_entry_receiver_type|
|
|
1419
|
+
raise LoweringError.new("#{context} requires #{target_type}.append_format() to be non-editable", line: 0, column: 0, path: @ctx.current_analysis_path) if method_binding.type.receiver_editable
|
|
1420
|
+
unless method_binding.type.params.length == 1 && string_builder_ref_type?(method_binding.type.params.first.type)
|
|
1421
|
+
raise LoweringError.new("#{context} requires #{target_type}.append_format(output: ref[std.string.String]) -> void", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1422
|
+
end
|
|
1423
|
+
unless method_binding.type.return_type == @ctx.types.fetch("void")
|
|
1424
|
+
raise LoweringError.new("#{context} requires #{target_type}.append_format(output: ref[std.string.String]) -> void, got #{method_binding.type.return_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1425
|
+
end
|
|
1424
1426
|
end
|
|
1425
1427
|
end
|
|
1426
|
-
end
|
|
1427
1428
|
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
end
|
|
1431
|
-
|
|
1432
|
-
def resolve_explicit_associated_binding(target_type, method_name, requirement_message:)
|
|
1433
|
-
dispatch_receiver_type = method_dispatch_receiver_type(target_type)
|
|
1434
|
-
method_entry_receiver_type = target_type
|
|
1435
|
-
static_method_name = "static:#{method_name}"
|
|
1436
|
-
method_entry = @method_definitions[[target_type, static_method_name]]
|
|
1437
|
-
unless method_entry || dispatch_receiver_type == target_type
|
|
1438
|
-
method_entry_receiver_type = dispatch_receiver_type
|
|
1439
|
-
method_entry = @method_definitions[[dispatch_receiver_type, static_method_name]]
|
|
1429
|
+
def method_analysis_key(method_ast)
|
|
1430
|
+
method_ast.kind == :static ? "static:#{method_ast.name}" : method_ast.name
|
|
1440
1431
|
end
|
|
1441
|
-
return nil unless method_entry
|
|
1442
1432
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1433
|
+
def resolve_explicit_associated_binding(target_type, method_name, requirement_message:)
|
|
1434
|
+
dispatch_receiver_type = method_dispatch_receiver_type(target_type)
|
|
1435
|
+
method_entry_receiver_type = target_type
|
|
1436
|
+
static_method_name = "static:#{method_name}"
|
|
1437
|
+
method_entry = @method_definitions[[target_type, static_method_name]]
|
|
1438
|
+
unless method_entry || dispatch_receiver_type == target_type
|
|
1439
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
1440
|
+
method_entry = @method_definitions[[dispatch_receiver_type, static_method_name]]
|
|
1441
|
+
end
|
|
1442
|
+
return nil unless method_entry
|
|
1446
1443
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1444
|
+
method_analysis, method_ast = method_entry
|
|
1445
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
1446
|
+
raise LoweringError.new(requirement_message, line: 0, column: 0, path: @ctx.current_analysis_path) unless method_binding.type.receiver_type.nil?
|
|
1449
1447
|
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
else
|
|
1453
|
-
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type)
|
|
1454
|
-
end
|
|
1448
|
+
method_binding = instantiate_function_binding_with_receiver(method_binding, [], receiver_type: target_type) if method_binding.type_params.any?
|
|
1449
|
+
yield method_binding, method_analysis, method_entry_receiver_type
|
|
1455
1450
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
when "equal"
|
|
1462
|
-
ExplicitEqualBinding.new(binding: method_binding, callee_name:)
|
|
1463
|
-
when "order"
|
|
1464
|
-
ExplicitOrderBinding.new(binding: method_binding, callee_name:)
|
|
1465
|
-
else
|
|
1466
|
-
raise LoweringError.new("unsupported associated hook #{method_name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1467
|
-
end
|
|
1468
|
-
end
|
|
1451
|
+
callee_name = if method_binding.external
|
|
1452
|
+
external_function_c_name(method_binding)
|
|
1453
|
+
else
|
|
1454
|
+
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type)
|
|
1455
|
+
end
|
|
1469
1456
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1457
|
+
case method_name
|
|
1458
|
+
when "default"
|
|
1459
|
+
ExplicitDefaultBinding.new(binding: method_binding, callee_name:)
|
|
1460
|
+
when "hash"
|
|
1461
|
+
ExplicitHashBinding.new(binding: method_binding, callee_name:)
|
|
1462
|
+
when "equal"
|
|
1463
|
+
ExplicitEqualBinding.new(binding: method_binding, callee_name:)
|
|
1464
|
+
when "order"
|
|
1465
|
+
ExplicitOrderBinding.new(binding: method_binding, callee_name:)
|
|
1466
|
+
else
|
|
1467
|
+
raise LoweringError.new("unsupported associated hook #{method_name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1468
|
+
end
|
|
1477
1469
|
end
|
|
1478
|
-
return nil unless method_entry
|
|
1479
1470
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1471
|
+
def resolve_explicit_instance_binding(target_type, method_name, requirement_message:)
|
|
1472
|
+
dispatch_receiver_type = method_dispatch_receiver_type(target_type)
|
|
1473
|
+
method_entry_receiver_type = target_type
|
|
1474
|
+
method_entry = @method_definitions[[target_type, method_name]]
|
|
1475
|
+
unless method_entry || dispatch_receiver_type == target_type
|
|
1476
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
1477
|
+
method_entry = @method_definitions[[dispatch_receiver_type, method_name]]
|
|
1478
|
+
end
|
|
1479
|
+
return nil unless method_entry
|
|
1483
1480
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1481
|
+
method_analysis, method_ast = method_entry
|
|
1482
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
1483
|
+
raise LoweringError.new(requirement_message, line: 0, column: 0, path: @ctx.current_analysis_path) if method_binding.type.receiver_type.nil?
|
|
1486
1484
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
else
|
|
1490
|
-
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type)
|
|
1491
|
-
end
|
|
1485
|
+
method_binding = instantiate_function_binding_with_receiver(method_binding, [], receiver_type: target_type) if method_binding.type_params.any?
|
|
1486
|
+
yield method_binding, method_analysis, method_entry_receiver_type
|
|
1492
1487
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1488
|
+
callee_name = if method_binding.external
|
|
1489
|
+
external_function_c_name(method_binding)
|
|
1490
|
+
else
|
|
1491
|
+
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type)
|
|
1492
|
+
end
|
|
1498
1493
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1494
|
+
{
|
|
1495
|
+
binding: method_binding,
|
|
1496
|
+
callee_name: callee_name,
|
|
1497
|
+
}
|
|
1502
1498
|
end
|
|
1503
|
-
end
|
|
1504
1499
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
when AST::FunctionType, AST::ProcType, AST::TupleType
|
|
1510
|
-
resolve_type_ref(argument, type_params:)
|
|
1511
|
-
when AST::IntegerLiteral, AST::FloatLiteral
|
|
1512
|
-
Types::LiteralTypeArg.new(argument.value)
|
|
1513
|
-
else
|
|
1514
|
-
raise LoweringError.new("unsupported type argument #{argument.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1500
|
+
def resolve_specialization_type_arguments(expression)
|
|
1501
|
+
expression.arguments.map do |argument|
|
|
1502
|
+
resolve_type_argument(argument.value)
|
|
1503
|
+
end
|
|
1515
1504
|
end
|
|
1516
|
-
end
|
|
1517
1505
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1506
|
+
def resolve_type_argument(argument, type_params: current_type_params)
|
|
1507
|
+
case argument
|
|
1508
|
+
when AST::TypeRef
|
|
1509
|
+
resolve_type_argument_ref(argument, type_params:)
|
|
1510
|
+
when AST::FunctionType, AST::ProcType, AST::TupleType
|
|
1511
|
+
resolve_type_ref(argument, type_params:)
|
|
1512
|
+
when AST::IntegerLiteral, AST::FloatLiteral
|
|
1513
|
+
Types::LiteralTypeArg.new(argument.value)
|
|
1514
|
+
else
|
|
1515
|
+
raise LoweringError.new("unsupported type argument #{argument.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1516
|
+
end
|
|
1517
|
+
end
|
|
1520
1518
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1519
|
+
def resolve_type_argument_ref(type_ref, type_params:)
|
|
1520
|
+
return resolve_type_ref(type_ref, type_params:) unless literal_type_argument_name_candidate?(type_ref)
|
|
1523
1521
|
|
|
1524
|
-
|
|
1525
|
-
|
|
1522
|
+
result = try_resolve_type_ref(type_ref, type_params:)
|
|
1523
|
+
return result if result
|
|
1526
1524
|
|
|
1527
|
-
|
|
1528
|
-
|
|
1525
|
+
literal_type_argument = resolve_named_literal_type_argument(type_ref)
|
|
1526
|
+
return literal_type_argument if literal_type_argument
|
|
1529
1527
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
rescue LoweringError
|
|
1533
|
-
nil
|
|
1534
|
-
end
|
|
1528
|
+
resolve_type_ref(type_ref, type_params:)
|
|
1529
|
+
end
|
|
1535
1530
|
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1531
|
+
def try_resolve_type_ref(type_ref, type_params:)
|
|
1532
|
+
resolve_type_ref(type_ref, type_params:)
|
|
1533
|
+
rescue LoweringError
|
|
1534
|
+
nil
|
|
1535
|
+
end
|
|
1539
1536
|
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
resolve_current_module_const_value(type_ref.name.parts.first)
|
|
1544
|
-
when 2
|
|
1545
|
-
resolve_imported_module_const_value(type_ref.name.parts.first, type_ref.name.parts.last)
|
|
1546
|
-
end
|
|
1537
|
+
def literal_type_argument_name_candidate?(type_ref)
|
|
1538
|
+
type_ref.arguments.empty? && !type_ref.nullable
|
|
1539
|
+
end
|
|
1547
1540
|
|
|
1548
|
-
|
|
1541
|
+
def resolve_named_literal_type_argument(type_ref)
|
|
1542
|
+
value = case type_ref.name.parts.length
|
|
1543
|
+
when 1
|
|
1544
|
+
resolve_current_module_const_value(type_ref.name.parts.first)
|
|
1545
|
+
when 2
|
|
1546
|
+
resolve_imported_module_const_value(type_ref.name.parts.first, type_ref.name.parts.last)
|
|
1547
|
+
end
|
|
1549
1548
|
|
|
1550
|
-
|
|
1551
|
-
end
|
|
1549
|
+
return unless value.is_a?(Integer) || value.is_a?(Float)
|
|
1552
1550
|
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
return unless binding&.kind == :const
|
|
1551
|
+
Types::LiteralTypeArg.new(value)
|
|
1552
|
+
end
|
|
1556
1553
|
|
|
1557
|
-
|
|
1558
|
-
|
|
1554
|
+
def resolve_current_module_const_value(name)
|
|
1555
|
+
binding = @ctx.values[name]
|
|
1556
|
+
return unless binding&.kind == :const
|
|
1559
1557
|
|
|
1560
|
-
|
|
1561
|
-
imported_module = @ctx.imports[import_name]
|
|
1562
|
-
return unless imported_module
|
|
1563
|
-
if imported_module.private_value?(value_name)
|
|
1564
|
-
raise LoweringError.new("#{import_name}.#{value_name} is private to module #{imported_module.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1558
|
+
binding.const_value
|
|
1565
1559
|
end
|
|
1566
1560
|
|
|
1567
|
-
|
|
1568
|
-
|
|
1561
|
+
def resolve_imported_module_const_value(import_name, value_name)
|
|
1562
|
+
imported_module = @ctx.imports[import_name]
|
|
1563
|
+
return unless imported_module
|
|
1564
|
+
if imported_module.private_value?(value_name)
|
|
1565
|
+
raise LoweringError.new("#{import_name}.#{value_name} is private to module #{imported_module.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1566
|
+
end
|
|
1569
1567
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1568
|
+
binding = imported_module.values[value_name]
|
|
1569
|
+
return unless binding&.kind == :const
|
|
1572
1570
|
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return unless type.is_a?(Types::EnumBase)
|
|
1571
|
+
binding.const_value
|
|
1572
|
+
end
|
|
1576
1573
|
|
|
1577
|
-
|
|
1578
|
-
|
|
1574
|
+
def resolve_type_member_const_value(expression)
|
|
1575
|
+
type = resolve_type_expression(expression.receiver)
|
|
1576
|
+
return unless type.is_a?(Types::EnumBase)
|
|
1579
1577
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
value.is_a?(Integer) || value.is_a?(Float)
|
|
1583
|
-
end
|
|
1578
|
+
type.member_value(expression.member)
|
|
1579
|
+
end
|
|
1584
1580
|
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
# Resolve a bare type-parameter name (e.g. `T`) to its substituted
|
|
1598
|
-
# concrete type so `inline if T == int` folds during lowering too.
|
|
1599
|
-
current_type_params[identifier_expression.name] || @ctx.types[identifier_expression.name]
|
|
1600
|
-
end,
|
|
1601
|
-
resolve_member_access: lambda do |member_access_expression|
|
|
1602
|
-
if (receiver_value = CompileTime.evaluate(
|
|
1603
|
-
member_access_expression.receiver,
|
|
1604
|
-
resolve_identifier: lambda do |identifier_expression|
|
|
1605
|
-
if env
|
|
1606
|
-
binding = lookup_value(identifier_expression.name, env)
|
|
1607
|
-
return binding[:const_value] unless binding&.fetch(:const_value, nil).nil?
|
|
1608
|
-
end
|
|
1609
|
-
resolve_current_module_const_value(identifier_expression.name)
|
|
1610
|
-
end,
|
|
1611
|
-
resolve_member_access: lambda { |ma| nil },
|
|
1612
|
-
resolve_type_ref: lambda { |tr| resolve_type_ref(tr) },
|
|
1613
|
-
resolve_call: lambda { |ce| evaluate_compile_time_call(ce, env:) },
|
|
1614
|
-
))
|
|
1615
|
-
case receiver_value
|
|
1616
|
-
when Types::FieldHandle
|
|
1617
|
-
case member_access_expression.member
|
|
1618
|
-
when "name" then next receiver_value.field_name
|
|
1619
|
-
when "type" then next receiver_value.struct_handle.struct_type.field(receiver_value.field_name)
|
|
1620
|
-
end
|
|
1621
|
-
when Types::MemberHandle
|
|
1622
|
-
case member_access_expression.member
|
|
1623
|
-
when "name" then next receiver_value.member_name
|
|
1624
|
-
when "value" then next receiver_value.member_value
|
|
1625
|
-
end
|
|
1581
|
+
def compile_time_numeric_const_expression?(expression, env: nil)
|
|
1582
|
+
value = compile_time_const_value(expression, env:)
|
|
1583
|
+
value.is_a?(Integer) || value.is_a?(Float)
|
|
1584
|
+
end
|
|
1585
|
+
|
|
1586
|
+
def compile_time_const_value(expression, env: nil)
|
|
1587
|
+
CompileTime.evaluate(
|
|
1588
|
+
expression,
|
|
1589
|
+
resolve_identifier: lambda do |identifier_expression|
|
|
1590
|
+
if env
|
|
1591
|
+
binding = lookup_value(identifier_expression.name, env)
|
|
1592
|
+
return binding[:const_value] unless binding&.fetch(:const_value, nil).nil?
|
|
1626
1593
|
end
|
|
1627
|
-
end
|
|
1628
1594
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1595
|
+
value = resolve_current_module_const_value(identifier_expression.name)
|
|
1596
|
+
return value if value
|
|
1597
|
+
|
|
1598
|
+
# Resolve a bare type-parameter name (e.g. `T`) to its substituted
|
|
1599
|
+
# concrete type so `inline if T == int` folds during lowering too.
|
|
1600
|
+
current_type_params[identifier_expression.name] || @ctx.types[identifier_expression.name]
|
|
1601
|
+
end,
|
|
1602
|
+
resolve_member_access: lambda do |member_access_expression|
|
|
1603
|
+
if (receiver_value = CompileTime.evaluate(
|
|
1604
|
+
member_access_expression.receiver,
|
|
1605
|
+
resolve_identifier: lambda do |identifier_expression|
|
|
1606
|
+
if env
|
|
1607
|
+
binding = lookup_value(identifier_expression.name, env)
|
|
1608
|
+
return binding[:const_value] unless binding&.fetch(:const_value, nil).nil?
|
|
1609
|
+
end
|
|
1610
|
+
resolve_current_module_const_value(identifier_expression.name)
|
|
1611
|
+
end,
|
|
1612
|
+
resolve_member_access: lambda { |ma| nil },
|
|
1613
|
+
resolve_type_ref: lambda { |tr| resolve_type_ref(tr) },
|
|
1614
|
+
resolve_call: lambda { |ce| evaluate_compile_time_call(ce, env:) },
|
|
1615
|
+
))
|
|
1616
|
+
case receiver_value
|
|
1617
|
+
when Types::FieldHandle
|
|
1618
|
+
case member_access_expression.member
|
|
1619
|
+
when "name" then next receiver_value.field_name
|
|
1620
|
+
when "type" then next receiver_value.struct_handle.struct_type.field(receiver_value.field_name)
|
|
1621
|
+
end
|
|
1622
|
+
when Types::MemberHandle
|
|
1623
|
+
case member_access_expression.member
|
|
1624
|
+
when "name" then next receiver_value.member_name
|
|
1625
|
+
when "value" then next receiver_value.member_value
|
|
1626
|
+
end
|
|
1627
|
+
end
|
|
1628
|
+
end
|
|
1633
1629
|
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1630
|
+
value = if member_access_expression.receiver.is_a?(AST::Identifier)
|
|
1631
|
+
resolve_imported_module_const_value(member_access_expression.receiver.name, member_access_expression.member)
|
|
1632
|
+
end
|
|
1633
|
+
next value unless value.nil?
|
|
1634
|
+
|
|
1635
|
+
resolve_type_member_const_value(member_access_expression)
|
|
1636
|
+
end,
|
|
1637
|
+
resolve_type_ref: lambda do |type_ref|
|
|
1638
|
+
resolve_type_ref(type_ref)
|
|
1639
|
+
end,
|
|
1640
|
+
resolve_call: lambda do |call_expression|
|
|
1641
|
+
evaluate_compile_time_call(call_expression, env:)
|
|
1642
|
+
end,
|
|
1643
|
+
)
|
|
1644
|
+
end
|
|
1644
1645
|
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
else
|
|
1664
|
-
func = @ctx.functions[expression.callee.name]
|
|
1665
|
-
if func&.ast&.respond_to?(:const) && func.ast.const
|
|
1666
|
-
evaluate_const_function_body_lower(func, expression.arguments)
|
|
1646
|
+
def evaluate_compile_time_call(expression, env:)
|
|
1647
|
+
case expression.callee
|
|
1648
|
+
when AST::Identifier
|
|
1649
|
+
case expression.callee.name
|
|
1650
|
+
when "field_of"
|
|
1651
|
+
evaluate_field_of_call(expression.arguments, env:)
|
|
1652
|
+
when "fields_of"
|
|
1653
|
+
evaluate_fields_of_call(expression.arguments, env:)
|
|
1654
|
+
when "callable_of"
|
|
1655
|
+
evaluate_callable_of_call(expression.arguments)
|
|
1656
|
+
when "has_attribute"
|
|
1657
|
+
evaluate_has_attribute_call(expression.arguments, env:)
|
|
1658
|
+
when "attribute_of"
|
|
1659
|
+
evaluate_attribute_of_call(expression.arguments, env:)
|
|
1660
|
+
when "members_of"
|
|
1661
|
+
evaluate_members_of_call(expression.arguments, env:)
|
|
1662
|
+
when "attributes_of"
|
|
1663
|
+
evaluate_attributes_of_call(expression.arguments, env:)
|
|
1667
1664
|
else
|
|
1668
|
-
|
|
1669
|
-
end
|
|
1670
|
-
end
|
|
1671
|
-
when AST::Specialization
|
|
1672
|
-
if expression.callee.callee.is_a?(AST::Identifier) && expression.callee.callee.name == "attribute_arg"
|
|
1673
|
-
evaluate_attribute_arg_call(expression.arguments, env:)
|
|
1674
|
-
else
|
|
1675
|
-
callee_name = expression.callee.callee.is_a?(AST::Identifier) ? expression.callee.callee.name : nil
|
|
1676
|
-
if callee_name
|
|
1677
|
-
func = @ctx.functions[callee_name]
|
|
1665
|
+
func = @ctx.functions[expression.callee.name]
|
|
1678
1666
|
if func&.ast&.respond_to?(:const) && func.ast.const
|
|
1679
1667
|
evaluate_const_function_body_lower(func, expression.arguments)
|
|
1680
1668
|
else
|
|
1681
1669
|
evaluate_type_returning_call(expression, env:)
|
|
1682
1670
|
end
|
|
1683
|
-
|
|
1684
|
-
|
|
1671
|
+
end
|
|
1672
|
+
when AST::Specialization
|
|
1673
|
+
if expression.callee.callee.is_a?(AST::Identifier) && expression.callee.callee.name == "attribute_arg"
|
|
1674
|
+
evaluate_attribute_arg_call(expression.arguments, env:)
|
|
1675
|
+
else
|
|
1676
|
+
callee_name = expression.callee.callee.is_a?(AST::Identifier) ? expression.callee.callee.name : nil
|
|
1677
|
+
if callee_name
|
|
1678
|
+
func = @ctx.functions[callee_name]
|
|
1679
|
+
if func&.ast&.respond_to?(:const) && func.ast.const
|
|
1680
|
+
evaluate_const_function_body_lower(func, expression.arguments)
|
|
1681
|
+
else
|
|
1682
|
+
evaluate_type_returning_call(expression, env:)
|
|
1683
|
+
end
|
|
1684
|
+
else
|
|
1685
|
+
evaluate_type_returning_call(expression, env:)
|
|
1686
|
+
end
|
|
1685
1687
|
end
|
|
1686
1688
|
end
|
|
1687
1689
|
end
|
|
1688
|
-
end
|
|
1689
1690
|
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1691
|
+
def evaluate_type_returning_call(expression, env:)
|
|
1692
|
+
callee_name, type_args = extract_type_callee_info(expression)
|
|
1693
|
+
return nil unless callee_name
|
|
1694
|
+
|
|
1695
|
+
CompileTime::Reflection.core_evaluate_type_returning(
|
|
1696
|
+
callee_name, type_args,
|
|
1697
|
+
evaluate_value: ->(v) { compile_time_const_value(v, env:) },
|
|
1698
|
+
resolve_type_ref: ->(tr) { resolve_type_ref(tr) },
|
|
1699
|
+
pointer_to: ->(t) { pointer_to(t) },
|
|
1700
|
+
const_pointer_to: ->(t) { const_pointer_to(t) },
|
|
1701
|
+
top_level_functions: ->(name) { nil },
|
|
1702
|
+
evaluate_type_returning_function_body: nil,
|
|
1703
|
+
)
|
|
1704
|
+
end
|
|
1704
1705
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1706
|
+
def extract_type_callee_info(expression)
|
|
1707
|
+
if expression.is_a?(AST::Call) && expression.callee.is_a?(AST::Identifier)
|
|
1708
|
+
[expression.callee.name, nil]
|
|
1709
|
+
elsif expression.is_a?(AST::Specialization)
|
|
1710
|
+
if expression.callee.is_a?(AST::Identifier)
|
|
1711
|
+
[expression.callee.name, expression.arguments]
|
|
1712
|
+
elsif expression.callee.is_a?(AST::Specialization) && expression.callee.callee.is_a?(AST::Identifier)
|
|
1713
|
+
[expression.callee.callee.name, expression.callee.arguments]
|
|
1714
|
+
end
|
|
1713
1715
|
end
|
|
1714
1716
|
end
|
|
1715
|
-
end
|
|
1716
1717
|
|
|
1717
|
-
|
|
1718
|
-
|
|
1718
|
+
def evaluate_field_of_call(arguments, env:)
|
|
1719
|
+
return nil unless reflection_positional_arguments?(arguments, 2)
|
|
1719
1720
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1721
|
+
struct_handle = resolve_struct_handle_argument(arguments.first.value, env:)
|
|
1722
|
+
return nil unless struct_handle
|
|
1722
1723
|
|
|
1723
|
-
|
|
1724
|
-
|
|
1724
|
+
field_name = reflection_identifier_name(arguments[1].value)
|
|
1725
|
+
return nil unless field_name
|
|
1725
1726
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1727
|
+
CompileTime::Reflection.core_field_handle(struct_handle, field_name)
|
|
1728
|
+
end
|
|
1728
1729
|
|
|
1729
|
-
|
|
1730
|
-
|
|
1730
|
+
def evaluate_fields_of_call(arguments, env:)
|
|
1731
|
+
return nil unless reflection_positional_arguments?(arguments, 1)
|
|
1731
1732
|
|
|
1732
|
-
|
|
1733
|
-
|
|
1733
|
+
struct_handle = resolve_struct_handle_argument(arguments.first.value, env:)
|
|
1734
|
+
return nil unless struct_handle
|
|
1734
1735
|
|
|
1735
|
-
|
|
1736
|
-
|
|
1736
|
+
CompileTime::Reflection.core_field_handles(struct_handle)
|
|
1737
|
+
end
|
|
1737
1738
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1739
|
+
def evaluate_members_of_call(arguments, env:)
|
|
1740
|
+
return nil unless reflection_positional_arguments?(arguments, 1)
|
|
1740
1741
|
|
|
1741
|
-
|
|
1742
|
-
|
|
1742
|
+
type = resolve_type_expression(arguments.first.value)
|
|
1743
|
+
return nil unless type
|
|
1743
1744
|
|
|
1744
|
-
|
|
1745
|
+
return nil unless type.is_a?(Types::Enum) || type.is_a?(Types::Flags)
|
|
1745
1746
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1747
|
+
CompileTime::Reflection.core_member_handles(type)
|
|
1748
|
+
end
|
|
1748
1749
|
|
|
1749
|
-
|
|
1750
|
-
|
|
1750
|
+
def evaluate_attributes_of_call(arguments, env:)
|
|
1751
|
+
return nil unless reflection_positional_arguments?(arguments, 1) || reflection_positional_arguments?(arguments, 2)
|
|
1751
1752
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1753
|
+
target = evaluate_reflection_target_argument(arguments.first.value, env:)
|
|
1754
|
+
return nil unless target
|
|
1754
1755
|
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1756
|
+
if arguments.length == 2
|
|
1757
|
+
attribute_binding = resolve_attribute_name_argument(arguments[1].value)
|
|
1758
|
+
application = find_attribute_application(target, attribute_binding)
|
|
1759
|
+
return [] unless application
|
|
1759
1760
|
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
target,
|
|
1764
|
-
attribute_binding.params,
|
|
1765
|
-
application.argument_values,
|
|
1766
|
-
)]
|
|
1767
|
-
else
|
|
1768
|
-
resolved_attribute_applications_for_target(target).map do |application|
|
|
1769
|
-
Types::AttributeHandle.new(
|
|
1770
|
-
application.binding.name,
|
|
1771
|
-
application.binding.module_name,
|
|
1761
|
+
[Types::AttributeHandle.new(
|
|
1762
|
+
attribute_binding.name,
|
|
1763
|
+
attribute_binding.module_name,
|
|
1772
1764
|
target,
|
|
1773
|
-
|
|
1765
|
+
attribute_binding.params,
|
|
1774
1766
|
application.argument_values,
|
|
1775
|
-
)
|
|
1767
|
+
)]
|
|
1768
|
+
else
|
|
1769
|
+
resolved_attribute_applications_for_target(target).map do |application|
|
|
1770
|
+
Types::AttributeHandle.new(
|
|
1771
|
+
application.binding.name,
|
|
1772
|
+
application.binding.module_name,
|
|
1773
|
+
target,
|
|
1774
|
+
application.binding.params,
|
|
1775
|
+
application.argument_values,
|
|
1776
|
+
)
|
|
1777
|
+
end
|
|
1776
1778
|
end
|
|
1777
1779
|
end
|
|
1778
|
-
end
|
|
1779
|
-
|
|
1780
|
-
def evaluate_callable_of_call(arguments)
|
|
1781
|
-
return nil unless reflection_positional_arguments?(arguments, 1)
|
|
1782
1780
|
|
|
1783
|
-
|
|
1784
|
-
|
|
1781
|
+
def evaluate_callable_of_call(arguments)
|
|
1782
|
+
return nil unless reflection_positional_arguments?(arguments, 1)
|
|
1785
1783
|
|
|
1786
|
-
|
|
1787
|
-
|
|
1784
|
+
resolve_callable_handle_argument(arguments.first.value)
|
|
1785
|
+
end
|
|
1788
1786
|
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
return nil unless attribute_binding_supports_target?(binding, target)
|
|
1787
|
+
def evaluate_has_attribute_call(arguments, env:)
|
|
1788
|
+
return nil unless reflection_positional_arguments?(arguments, 2)
|
|
1792
1789
|
|
|
1793
|
-
|
|
1794
|
-
|
|
1790
|
+
target = evaluate_reflection_target_argument(arguments.first.value, env:)
|
|
1791
|
+
binding = resolve_attribute_name_argument(arguments[1].value)
|
|
1792
|
+
return nil unless attribute_binding_supports_target?(binding, target)
|
|
1795
1793
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1794
|
+
!find_attribute_application(target, binding).nil?
|
|
1795
|
+
end
|
|
1798
1796
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
return nil unless attribute_binding_supports_target?(binding, target)
|
|
1797
|
+
def evaluate_attribute_of_call(arguments, env:)
|
|
1798
|
+
return nil unless reflection_positional_arguments?(arguments, 2)
|
|
1802
1799
|
|
|
1803
|
-
|
|
1804
|
-
|
|
1800
|
+
target = evaluate_reflection_target_argument(arguments.first.value, env:)
|
|
1801
|
+
binding = resolve_attribute_name_argument(arguments[1].value)
|
|
1802
|
+
return nil unless attribute_binding_supports_target?(binding, target)
|
|
1805
1803
|
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
binding.module_name,
|
|
1809
|
-
target,
|
|
1810
|
-
binding.params,
|
|
1811
|
-
application.argument_values,
|
|
1812
|
-
)
|
|
1813
|
-
end
|
|
1804
|
+
application = find_attribute_application(target, binding)
|
|
1805
|
+
return nil unless application
|
|
1814
1806
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1807
|
+
Types::AttributeHandle.new(
|
|
1808
|
+
binding.name,
|
|
1809
|
+
binding.module_name,
|
|
1810
|
+
target,
|
|
1811
|
+
binding.params,
|
|
1812
|
+
application.argument_values,
|
|
1813
|
+
)
|
|
1814
|
+
end
|
|
1817
1815
|
|
|
1818
|
-
|
|
1819
|
-
|
|
1816
|
+
def evaluate_attribute_arg_call(arguments, env:)
|
|
1817
|
+
return nil unless reflection_positional_arguments?(arguments, 2)
|
|
1820
1818
|
|
|
1821
|
-
|
|
1822
|
-
|
|
1819
|
+
attribute_handle = compile_time_const_value(arguments.first.value, env:)
|
|
1820
|
+
return nil unless attribute_handle.is_a?(Types::AttributeHandle)
|
|
1823
1821
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1822
|
+
param_name = reflection_identifier_name(arguments[1].value)
|
|
1823
|
+
return nil unless param_name && attribute_handle.argument_values
|
|
1826
1824
|
|
|
1827
|
-
|
|
1828
|
-
|
|
1825
|
+
attribute_handle.argument_values[param_name]
|
|
1826
|
+
end
|
|
1829
1827
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
arg_expr = arguments[idx].value
|
|
1833
|
-
arg_value = compile_time_const_value(arg_expr, env: empty_env)
|
|
1834
|
-
return nil unless arg_value
|
|
1828
|
+
def evaluate_const_function_body_lower(func, arguments)
|
|
1829
|
+
return nil unless func.ast.params.length == arguments.length
|
|
1835
1830
|
|
|
1836
|
-
initial_vars
|
|
1837
|
-
|
|
1831
|
+
initial_vars = {}
|
|
1832
|
+
func.ast.params.each_with_index do |param, idx|
|
|
1833
|
+
arg_expr = arguments[idx].value
|
|
1834
|
+
arg_value = compile_time_const_value(arg_expr, env: empty_env)
|
|
1835
|
+
return nil unless arg_value
|
|
1838
1836
|
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
ctx.evaluate_block(func.ast.body, scopes: nil)
|
|
1842
|
-
rescue CompileTime::ReturnValue => e
|
|
1843
|
-
e.value
|
|
1844
|
-
end
|
|
1837
|
+
initial_vars[param.name] = arg_value
|
|
1838
|
+
end
|
|
1845
1839
|
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1840
|
+
evaluator = ConstFnLowerEvaluator.new(self)
|
|
1841
|
+
ctx = CompileTime::BlockContext.new(evaluator, initial_variables: initial_vars)
|
|
1842
|
+
ctx.evaluate_block(func.ast.body, scopes: nil)
|
|
1843
|
+
rescue CompileTime::ReturnValue => e
|
|
1844
|
+
e.value
|
|
1849
1845
|
end
|
|
1850
1846
|
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1847
|
+
class ConstFnLowerEvaluator
|
|
1848
|
+
def initialize(lowerer)
|
|
1849
|
+
@lowerer = lowerer
|
|
1850
|
+
end
|
|
1854
1851
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1852
|
+
def types
|
|
1853
|
+
@lowerer.instance_variable_get(:@ctx).types
|
|
1854
|
+
end
|
|
1858
1855
|
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1856
|
+
def evaluate_compile_time_const_value(expression, scopes: nil)
|
|
1857
|
+
@lowerer.compile_time_const_value(expression, env: @lowerer.empty_env)
|
|
1858
|
+
end
|
|
1859
|
+
|
|
1860
|
+
def top_level_function(name)
|
|
1861
|
+
@lowerer.instance_variable_get(:@ctx).functions&.[](name)
|
|
1862
|
+
end
|
|
1862
1863
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1864
|
+
def raise_sema_error(message)
|
|
1865
|
+
raise CompileTime::Error, message
|
|
1866
|
+
end
|
|
1865
1867
|
end
|
|
1866
|
-
end
|
|
1867
1868
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1869
|
+
def evaluate_reflection_target_argument(expression, env:)
|
|
1870
|
+
struct_handle = resolve_struct_handle_argument(expression, env:)
|
|
1871
|
+
return struct_handle if struct_handle
|
|
1871
1872
|
|
|
1872
|
-
|
|
1873
|
-
|
|
1873
|
+
value = compile_time_const_value(expression, env:)
|
|
1874
|
+
return value if value.is_a?(Types::FieldHandle) || value.is_a?(Types::CallableHandle)
|
|
1874
1875
|
|
|
1875
|
-
|
|
1876
|
-
|
|
1876
|
+
nil
|
|
1877
|
+
end
|
|
1877
1878
|
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1879
|
+
def reflection_positional_arguments?(arguments, expected_length)
|
|
1880
|
+
arguments.length == expected_length && arguments.none?(&:name)
|
|
1881
|
+
end
|
|
1881
1882
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1883
|
+
def resolve_struct_handle_argument(expression, env:)
|
|
1884
|
+
type = reflection_type_from_expression(expression, env:)
|
|
1885
|
+
return nil unless type
|
|
1885
1886
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1887
|
+
struct_handle_for_type(type)
|
|
1888
|
+
end
|
|
1888
1889
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1890
|
+
def reflection_type_from_expression(expression, env:)
|
|
1891
|
+
case expression
|
|
1892
|
+
when AST::Identifier
|
|
1893
|
+
return nil if env && lookup_value(expression.name, env)
|
|
1893
1894
|
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1895
|
+
current_type_params[expression.name] || @ctx.types[expression.name]
|
|
1896
|
+
when AST::MemberAccess
|
|
1897
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
1897
1898
|
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1899
|
+
if @ctx.imports.key?(expression.receiver.name)
|
|
1900
|
+
imported_module = @ctx.imports[expression.receiver.name]
|
|
1901
|
+
return nil if imported_module.private_type?(expression.member)
|
|
1902
|
+
return imported_module.types[expression.member]
|
|
1903
|
+
end
|
|
1903
1904
|
|
|
1904
|
-
|
|
1905
|
-
|
|
1905
|
+
parent_type = @ctx.types[expression.receiver.name]
|
|
1906
|
+
return parent_type.nested_types[expression.member] if parent_type.respond_to?(:nested_types) && parent_type.nested_types.key?(expression.member)
|
|
1906
1907
|
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1908
|
+
nil
|
|
1909
|
+
else
|
|
1910
|
+
nil
|
|
1911
|
+
end
|
|
1910
1912
|
end
|
|
1911
|
-
end
|
|
1912
1913
|
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1914
|
+
def struct_handle_for_type(type)
|
|
1915
|
+
base_type = type.is_a?(Types::StructInstance) ? type.definition : type
|
|
1916
|
+
return nil unless base_type.is_a?(Types::Struct) || base_type.is_a?(Types::GenericStructDefinition)
|
|
1917
|
+
return nil unless base_type.respond_to?(:module_name)
|
|
1917
1918
|
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1919
|
+
analysis = analysis_for_module(base_type.module_name)
|
|
1920
|
+
declaration = find_struct_decl_by_name(analysis.ast.declarations, base_type.name)
|
|
1921
|
+
return nil unless declaration
|
|
1921
1922
|
|
|
1922
|
-
|
|
1923
|
-
|
|
1923
|
+
Types::StructHandle.new(base_type, declaration)
|
|
1924
|
+
end
|
|
1924
1925
|
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1926
|
+
def find_struct_decl_by_name(declarations, name)
|
|
1927
|
+
declarations.each do |decl|
|
|
1928
|
+
next unless decl.is_a?(AST::StructDecl)
|
|
1929
|
+
return decl if decl.name == name
|
|
1930
|
+
if decl.nested_types&.any?
|
|
1931
|
+
found = find_struct_decl_by_name(decl.nested_types, name)
|
|
1932
|
+
return found if found
|
|
1933
|
+
end
|
|
1932
1934
|
end
|
|
1935
|
+
nil
|
|
1933
1936
|
end
|
|
1934
|
-
nil
|
|
1935
|
-
end
|
|
1936
1937
|
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1938
|
+
def resolve_callable_handle_argument(expression)
|
|
1939
|
+
case expression
|
|
1940
|
+
when AST::Identifier
|
|
1941
|
+
binding = @ctx.functions[expression.name]
|
|
1942
|
+
return nil unless binding&.ast
|
|
1942
1943
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1944
|
+
Types::CallableHandle.new(expression.name, binding.ast)
|
|
1945
|
+
when AST::MemberAccess
|
|
1946
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
1946
1947
|
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1948
|
+
imported_module = @ctx.imports[expression.receiver.name]
|
|
1949
|
+
return nil unless imported_module
|
|
1950
|
+
return nil if imported_module.private_function?(expression.member)
|
|
1950
1951
|
|
|
1951
|
-
|
|
1952
|
-
|
|
1952
|
+
binding = imported_module.functions[expression.member]
|
|
1953
|
+
return nil unless binding&.ast
|
|
1953
1954
|
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1955
|
+
Types::CallableHandle.new("#{expression.receiver.name}.#{expression.member}", binding.ast)
|
|
1956
|
+
else
|
|
1957
|
+
nil
|
|
1958
|
+
end
|
|
1957
1959
|
end
|
|
1958
|
-
end
|
|
1959
1960
|
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1961
|
+
def resolve_attribute_name_argument(expression)
|
|
1962
|
+
case expression
|
|
1963
|
+
when AST::Identifier
|
|
1964
|
+
@ctx.attributes[expression.name] || builtin_attribute_binding(expression.name)
|
|
1965
|
+
when AST::MemberAccess
|
|
1966
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
1966
1967
|
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1968
|
+
imported_module = @ctx.imports[expression.receiver.name]
|
|
1969
|
+
return nil unless imported_module
|
|
1970
|
+
return nil if imported_module.private_attribute?(expression.member)
|
|
1970
1971
|
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1972
|
+
imported_module.attributes[expression.member]
|
|
1973
|
+
else
|
|
1974
|
+
nil
|
|
1975
|
+
end
|
|
1974
1976
|
end
|
|
1975
|
-
end
|
|
1976
1977
|
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
def attribute_binding_supports_target?(binding, target)
|
|
1982
|
-
binding && target && binding.targets.include?(attribute_target_kind(target))
|
|
1983
|
-
end
|
|
1978
|
+
def reflection_identifier_name(expression)
|
|
1979
|
+
expression.is_a?(AST::Identifier) ? expression.name : nil
|
|
1980
|
+
end
|
|
1984
1981
|
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
when Types::StructHandle then :struct
|
|
1988
|
-
when Types::FieldHandle then :field
|
|
1989
|
-
when Types::CallableHandle then :callable
|
|
1982
|
+
def attribute_binding_supports_target?(binding, target)
|
|
1983
|
+
binding && target && binding.targets.include?(attribute_target_kind(target))
|
|
1990
1984
|
end
|
|
1991
|
-
end
|
|
1992
1985
|
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1986
|
+
def attribute_target_kind(target)
|
|
1987
|
+
case target
|
|
1988
|
+
when Types::StructHandle then :struct
|
|
1989
|
+
when Types::FieldHandle then :field
|
|
1990
|
+
when Types::CallableHandle then :callable
|
|
1991
|
+
end
|
|
1998
1992
|
end
|
|
1999
|
-
return [] unless target_id
|
|
2000
1993
|
|
|
2001
|
-
|
|
2002
|
-
|
|
1994
|
+
def resolved_attribute_applications_for_target(target)
|
|
1995
|
+
target_id = case target
|
|
1996
|
+
when Types::StructHandle then target.declaration.object_id
|
|
1997
|
+
when Types::FieldHandle then target.field_declaration.object_id
|
|
1998
|
+
when Types::CallableHandle then target.declaration.object_id
|
|
1999
|
+
end
|
|
2000
|
+
return [] unless target_id
|
|
2003
2001
|
|
|
2004
|
-
|
|
2005
|
-
applications = imported_module.attribute_applications[target_id]
|
|
2002
|
+
applications = @ctx.attribute_applications[target_id]
|
|
2006
2003
|
return applications if applications
|
|
2007
|
-
end
|
|
2008
2004
|
|
|
2009
|
-
|
|
2010
|
-
|
|
2005
|
+
@ctx.imports.each_value do |imported_module|
|
|
2006
|
+
applications = imported_module.attribute_applications[target_id]
|
|
2007
|
+
return applications if applications
|
|
2008
|
+
end
|
|
2011
2009
|
|
|
2012
|
-
|
|
2013
|
-
resolved_attribute_applications_for_target(target).find do |application|
|
|
2014
|
-
same_attribute_binding?(application.binding, binding)
|
|
2010
|
+
[]
|
|
2015
2011
|
end
|
|
2016
|
-
end
|
|
2017
|
-
|
|
2018
|
-
def same_attribute_binding?(left, right)
|
|
2019
|
-
left.name == right.name && left.module_name == right.module_name
|
|
2020
|
-
end
|
|
2021
|
-
|
|
2022
|
-
def builtin_attribute_binding(name)
|
|
2023
|
-
MilkTea.builtin_attribute_binding(name, @ctx.types)
|
|
2024
|
-
end
|
|
2025
|
-
|
|
2026
|
-
def specialize_function_binding(binding, arguments, env, receiver_type: nil)
|
|
2027
|
-
return binding if binding.type_params.empty?
|
|
2028
|
-
raise LoweringError.new("generic function #{binding.name} must be called", line: 0, column: 0, path: @ctx.current_analysis_path) unless arguments
|
|
2029
2012
|
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
def instantiate_function_binding_with_receiver(binding, explicit_type_arguments, receiver_type: nil)
|
|
2035
|
-
if binding.type_params.empty?
|
|
2036
|
-
raise LoweringError.new("function #{binding.name} is not generic and cannot be specialized", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2013
|
+
def find_attribute_application(target, binding)
|
|
2014
|
+
resolved_attribute_applications_for_target(target).find do |application|
|
|
2015
|
+
same_attribute_binding?(application.binding, binding)
|
|
2016
|
+
end
|
|
2037
2017
|
end
|
|
2038
2018
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
unless remaining_type_params.length == explicit_type_arguments.length
|
|
2042
|
-
raise LoweringError.new("function #{binding.name} expects #{remaining_type_params.length} type arguments, got #{explicit_type_arguments.length}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2019
|
+
def same_attribute_binding?(left, right)
|
|
2020
|
+
left.name == right.name && left.module_name == right.module_name
|
|
2043
2021
|
end
|
|
2044
2022
|
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
raise LoweringError.new("generic function #{binding.name} cannot be instantiated with ref types", line: 0, column: 0, path: @ctx.current_analysis_path) if contains_ref_type?(type_argument)
|
|
2048
|
-
|
|
2049
|
-
substitutions[name] = type_argument
|
|
2023
|
+
def builtin_attribute_binding(name)
|
|
2024
|
+
Bindings.builtin_attribute_binding(name, @ctx.types)
|
|
2050
2025
|
end
|
|
2051
2026
|
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
raise LoweringError.new("
|
|
2027
|
+
def specialize_function_binding(binding, arguments, env, receiver_type: nil)
|
|
2028
|
+
return binding if binding.type_params.empty?
|
|
2029
|
+
raise LoweringError.new("generic function #{binding.name} must be called", line: 0, column: 0, path: @ctx.current_analysis_path) unless arguments
|
|
2055
2030
|
|
|
2056
|
-
|
|
2031
|
+
type_arguments = infer_function_type_arguments(binding, arguments, env, receiver_type:)
|
|
2032
|
+
instantiate_function_binding(binding, type_arguments)
|
|
2057
2033
|
end
|
|
2058
2034
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2035
|
+
def instantiate_function_binding_with_receiver(binding, explicit_type_arguments, receiver_type: nil)
|
|
2036
|
+
if binding.type_params.empty?
|
|
2037
|
+
raise LoweringError.new("function #{binding.name} is not generic and cannot be specialized", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2038
|
+
end
|
|
2061
2039
|
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
unless binding.type_params.length == type_arguments.length
|
|
2068
|
-
raise LoweringError.new("function #{binding.name} expects #{binding.type_params.length} type arguments, got #{type_arguments.length}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2069
|
-
end
|
|
2070
|
-
|
|
2071
|
-
if type_arguments.any? { |type_argument| contains_ref_type?(type_argument) }
|
|
2072
|
-
raise LoweringError.new("generic function #{binding.name} cannot be instantiated with ref types", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2073
|
-
end
|
|
2074
|
-
|
|
2075
|
-
key = type_arguments.freeze
|
|
2076
|
-
return binding.instances.fetch(key) if binding.instances.key?(key)
|
|
2077
|
-
|
|
2078
|
-
substitutions = binding.type_params.zip(type_arguments).to_h
|
|
2079
|
-
validate_function_type_param_constraints!(binding, substitutions)
|
|
2080
|
-
instance = FunctionBinding.new(
|
|
2081
|
-
name: binding.name,
|
|
2082
|
-
type: substitute_type(binding.type, substitutions),
|
|
2083
|
-
body_params: binding.body_params.map { |param| substitute_value_binding(param, substitutions) },
|
|
2084
|
-
body_return_type: substitute_type(binding.body_return_type, substitutions),
|
|
2085
|
-
ast: binding.ast,
|
|
2086
|
-
external: binding.external,
|
|
2087
|
-
async: binding.async,
|
|
2088
|
-
type_params: [].freeze,
|
|
2089
|
-
type_param_constraints: {}.freeze,
|
|
2090
|
-
instances: {},
|
|
2091
|
-
type_arguments: key,
|
|
2092
|
-
owner: binding.owner,
|
|
2093
|
-
specialization_owner: nil,
|
|
2094
|
-
type_substitutions: substitutions.freeze,
|
|
2095
|
-
declared_receiver_type: binding.declared_receiver_type ? substitute_type(binding.declared_receiver_type, substitutions) : nil,
|
|
2096
|
-
)
|
|
2097
|
-
binding.instances[key] = instance
|
|
2098
|
-
end
|
|
2040
|
+
receiver_substitutions = infer_receiver_type_substitutions(binding, receiver_type)
|
|
2041
|
+
remaining_type_params = binding.type_params.reject { |name| receiver_substitutions.key?(name) }
|
|
2042
|
+
unless remaining_type_params.length == explicit_type_arguments.length
|
|
2043
|
+
raise LoweringError.new("function #{binding.name} expects #{remaining_type_params.length} type arguments, got #{explicit_type_arguments.length}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2044
|
+
end
|
|
2099
2045
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
raise LoweringError.new("cannot infer type argument #{name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless actual_type
|
|
2046
|
+
substitutions = receiver_substitutions.dup
|
|
2047
|
+
remaining_type_params.zip(explicit_type_arguments).each do |name, type_argument|
|
|
2048
|
+
raise LoweringError.new("generic function #{binding.name} cannot be instantiated with ref types", line: 0, column: 0, path: @ctx.current_analysis_path) if contains_ref_type?(type_argument)
|
|
2104
2049
|
|
|
2105
|
-
|
|
2106
|
-
|
|
2050
|
+
substitutions[name] = type_argument
|
|
2051
|
+
end
|
|
2052
|
+
|
|
2053
|
+
type_arguments = binding.type_params.map do |name|
|
|
2054
|
+
inferred = substitutions[name]
|
|
2055
|
+
raise LoweringError.new("cannot infer type argument #{name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless inferred
|
|
2107
2056
|
|
|
2108
|
-
|
|
2057
|
+
inferred
|
|
2109
2058
|
end
|
|
2059
|
+
|
|
2060
|
+
instantiate_function_binding(binding, type_arguments)
|
|
2110
2061
|
end
|
|
2111
|
-
end
|
|
2112
2062
|
|
|
2063
|
+
def instantiate_function_binding(binding, type_arguments)
|
|
2064
|
+
if binding.type_params.empty?
|
|
2065
|
+
raise LoweringError.new("function #{binding.name} is not generic and cannot be specialized", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2066
|
+
end
|
|
2113
2067
|
|
|
2114
|
-
|
|
2115
|
-
|
|
2068
|
+
unless binding.type_params.length == type_arguments.length
|
|
2069
|
+
raise LoweringError.new("function #{binding.name} expects #{binding.type_params.length} type arguments, got #{type_arguments.length}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2070
|
+
end
|
|
2116
2071
|
|
|
2117
|
-
|
|
2118
|
-
|
|
2072
|
+
if type_arguments.any? { |type_argument| contains_ref_type?(type_argument) }
|
|
2073
|
+
raise LoweringError.new("generic function #{binding.name} cannot be instantiated with ref types", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2074
|
+
end
|
|
2119
2075
|
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
return true if @ctx.implemented_interfaces.fetch(key, []).include?(interface)
|
|
2076
|
+
key = type_arguments.freeze
|
|
2077
|
+
return binding.instances.fetch(key) if binding.instances.key?(key)
|
|
2123
2078
|
|
|
2124
|
-
|
|
2125
|
-
|
|
2079
|
+
substitutions = binding.type_params.zip(type_arguments).to_h
|
|
2080
|
+
validate_function_type_param_constraints!(binding, substitutions)
|
|
2081
|
+
instance = Bindings::FunctionBinding.new(
|
|
2082
|
+
name: binding.name,
|
|
2083
|
+
type: substitute_type(binding.type, substitutions),
|
|
2084
|
+
body_params: binding.body_params.map { |param| substitute_value_binding(param, substitutions) },
|
|
2085
|
+
body_return_type: substitute_type(binding.body_return_type, substitutions),
|
|
2086
|
+
ast: binding.ast,
|
|
2087
|
+
external: binding.external,
|
|
2088
|
+
async: binding.async,
|
|
2089
|
+
type_params: [].freeze,
|
|
2090
|
+
type_param_constraints: {}.freeze,
|
|
2091
|
+
instances: {},
|
|
2092
|
+
type_arguments: key,
|
|
2093
|
+
owner: binding.owner,
|
|
2094
|
+
specialization_owner: nil,
|
|
2095
|
+
type_substitutions: substitutions.freeze,
|
|
2096
|
+
declared_receiver_type: binding.declared_receiver_type ? substitute_type(binding.declared_receiver_type, substitutions) : nil,
|
|
2097
|
+
)
|
|
2098
|
+
binding.instances[key] = instance
|
|
2126
2099
|
end
|
|
2127
2100
|
|
|
2128
|
-
|
|
2129
|
-
|
|
2101
|
+
def validate_function_type_param_constraints!(binding, substitutions)
|
|
2102
|
+
binding.type_param_constraints.each do |name, constraints|
|
|
2103
|
+
actual_type = substitutions[name]
|
|
2104
|
+
raise LoweringError.new("cannot infer type argument #{name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless actual_type
|
|
2130
2105
|
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
unless call_arity_matches?(binding.type, arguments.length)
|
|
2134
|
-
raise LoweringError.new(arity_error_message(binding.type, binding.name, arguments.length), line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2135
|
-
end
|
|
2106
|
+
constraints.interfaces.each do |interface|
|
|
2107
|
+
next if type_implements_interface?(actual_type, interface)
|
|
2136
2108
|
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
candidate_type = substitute_type(parameter.type, substitutions)
|
|
2141
|
-
expected_argument_type = if callable_type?(candidate_type)
|
|
2142
|
-
candidate_type
|
|
2143
|
-
elsif contains_type_var?(candidate_type)
|
|
2144
|
-
nil
|
|
2145
|
-
else
|
|
2146
|
-
candidate_type
|
|
2147
|
-
end
|
|
2148
|
-
actual_type = infer_expression_type(argument.value, env:, expected_type: expected_argument_type)
|
|
2149
|
-
collect_type_substitutions(parameter.type, actual_type, substitutions, binding.name)
|
|
2109
|
+
raise LoweringError.new("type #{actual_type} does not implement interface #{interface.name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2110
|
+
end
|
|
2111
|
+
end
|
|
2150
2112
|
end
|
|
2151
2113
|
|
|
2152
|
-
binding.type_params.map do |name|
|
|
2153
|
-
inferred = substitutions[name]
|
|
2154
|
-
raise LoweringError.new("cannot infer type argument #{name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless inferred
|
|
2155
2114
|
|
|
2156
|
-
|
|
2115
|
+
def interface_implementation_key(type)
|
|
2116
|
+
return type.definition if type.is_a?(Types::StructInstance)
|
|
2117
|
+
|
|
2118
|
+
type
|
|
2157
2119
|
end
|
|
2158
|
-
end
|
|
2159
2120
|
|
|
2121
|
+
def type_implements_interface?(type, interface)
|
|
2122
|
+
key = interface_implementation_key(type)
|
|
2123
|
+
return true if @ctx.implemented_interfaces.fetch(key, []).include?(interface)
|
|
2160
2124
|
|
|
2125
|
+
@ctx.imports.each_value do |module_binding|
|
|
2126
|
+
return true if module_binding.implemented_interfaces.fetch(key, []).include?(interface)
|
|
2127
|
+
end
|
|
2161
2128
|
|
|
2162
|
-
|
|
2163
|
-
if parts.length == 1
|
|
2164
|
-
type = analysis.types[parts.first]
|
|
2165
|
-
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2166
|
-
elsif parts.length == 2 && analysis.imports.key?(parts.first)
|
|
2167
|
-
type = analysis.imports.fetch(parts.first).types[parts.last]
|
|
2168
|
-
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2129
|
+
false
|
|
2169
2130
|
end
|
|
2170
2131
|
|
|
2171
|
-
nil
|
|
2172
|
-
|
|
2132
|
+
def infer_function_type_arguments(binding, arguments, env, receiver_type: nil)
|
|
2133
|
+
expected_params = binding.type.params
|
|
2134
|
+
unless call_arity_matches?(binding.type, arguments.length)
|
|
2135
|
+
raise LoweringError.new(arity_error_message(binding.type, binding.name, arguments.length), line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2136
|
+
end
|
|
2137
|
+
|
|
2138
|
+
substitutions = infer_receiver_type_substitutions(binding, receiver_type)
|
|
2139
|
+
expected_params.each_with_index do |parameter, index|
|
|
2140
|
+
argument = arguments.fetch(index)
|
|
2141
|
+
candidate_type = substitute_type(parameter.type, substitutions)
|
|
2142
|
+
expected_argument_type = if callable_type?(candidate_type)
|
|
2143
|
+
candidate_type
|
|
2144
|
+
elsif contains_type_var?(candidate_type)
|
|
2145
|
+
nil
|
|
2146
|
+
else
|
|
2147
|
+
candidate_type
|
|
2148
|
+
end
|
|
2149
|
+
actual_type = infer_expression_type(argument.value, env:, expected_type: expected_argument_type)
|
|
2150
|
+
collect_type_substitutions(parameter.type, actual_type, substitutions, binding.name)
|
|
2151
|
+
end
|
|
2173
2152
|
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
next unless value.is_a?(AST::TypeRef)
|
|
2178
|
-
next unless value.arguments.empty? && !value.nullable && value.name.parts.length == 1
|
|
2153
|
+
binding.type_params.map do |name|
|
|
2154
|
+
inferred = substitutions[name]
|
|
2155
|
+
raise LoweringError.new("cannot infer type argument #{name} for function #{binding.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless inferred
|
|
2179
2156
|
|
|
2180
|
-
|
|
2157
|
+
inferred
|
|
2158
|
+
end
|
|
2181
2159
|
end
|
|
2182
2160
|
|
|
2183
|
-
expected_names = generic_type.type_params
|
|
2184
|
-
unless names == expected_names
|
|
2185
|
-
raise LoweringError.new("extending target #{type_ref} must use the receiver type parameters directly", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2186
|
-
end
|
|
2187
2161
|
|
|
2188
|
-
expected_names
|
|
2189
|
-
end
|
|
2190
2162
|
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2163
|
+
def resolve_named_generic_type_for_analysis(analysis, parts)
|
|
2164
|
+
if parts.length == 1
|
|
2165
|
+
type = analysis.types[parts.first]
|
|
2166
|
+
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2167
|
+
elsif parts.length == 2 && analysis.imports.key?(parts.first)
|
|
2168
|
+
type = analysis.imports.fetch(parts.first).types[parts.last]
|
|
2169
|
+
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2170
|
+
end
|
|
2196
2171
|
|
|
2197
|
-
|
|
2172
|
+
nil
|
|
2198
2173
|
end
|
|
2199
2174
|
|
|
2200
|
-
|
|
2175
|
+
def validate_methods_receiver_type_arguments!(type_ref, generic_type)
|
|
2176
|
+
names = type_ref.arguments.map do |argument|
|
|
2177
|
+
value = argument.value
|
|
2178
|
+
next unless value.is_a?(AST::TypeRef)
|
|
2179
|
+
next unless value.arguments.empty? && !value.nullable && value.name.parts.length == 1
|
|
2201
2180
|
|
|
2202
|
-
|
|
2203
|
-
|
|
2181
|
+
value.name.parts.first
|
|
2182
|
+
end
|
|
2204
2183
|
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
case declared_receiver_type
|
|
2209
|
-
when Types::Nullable
|
|
2210
|
-
unless receiver_type.is_a?(Types::Nullable)
|
|
2211
|
-
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2184
|
+
expected_names = generic_type.type_params
|
|
2185
|
+
unless names == expected_names
|
|
2186
|
+
raise LoweringError.new("extending target #{type_ref} must use the receiver type parameters directly", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2212
2187
|
end
|
|
2213
2188
|
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
receiver_type.base,
|
|
2217
|
-
)
|
|
2218
|
-
when Types::StructInstance
|
|
2219
|
-
return {} unless declared_receiver_type.definition.is_a?(Types::GenericStructDefinition)
|
|
2189
|
+
expected_names
|
|
2190
|
+
end
|
|
2220
2191
|
|
|
2221
|
-
|
|
2222
|
-
|
|
2192
|
+
def methods_receiver_type_argument_names!(type_ref)
|
|
2193
|
+
names = type_ref.arguments.map do |argument|
|
|
2194
|
+
value = argument.value
|
|
2195
|
+
next unless value.is_a?(AST::TypeRef)
|
|
2196
|
+
next unless value.arguments.empty? && !value.nullable && value.name.parts.length == 1
|
|
2197
|
+
|
|
2198
|
+
value.name.parts.first
|
|
2223
2199
|
end
|
|
2224
2200
|
|
|
2225
|
-
|
|
2226
|
-
when Types::VariantInstance
|
|
2227
|
-
return {} unless declared_receiver_type.definition.is_a?(Types::GenericVariantDefinition)
|
|
2201
|
+
raise LoweringError.new("extending target #{type_ref} must use the receiver type parameters directly", line: 0, column: 0, path: @ctx.current_analysis_path) if names.any?(&:nil?)
|
|
2228
2202
|
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
end
|
|
2203
|
+
names
|
|
2204
|
+
end
|
|
2232
2205
|
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2206
|
+
def infer_receiver_type_substitutions(binding, receiver_type)
|
|
2207
|
+
declared_receiver_type = binding.declared_receiver_type
|
|
2208
|
+
return {} unless declared_receiver_type
|
|
2209
|
+
case declared_receiver_type
|
|
2210
|
+
when Types::Nullable
|
|
2211
|
+
unless receiver_type.is_a?(Types::Nullable)
|
|
2212
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2213
|
+
end
|
|
2214
|
+
|
|
2215
|
+
infer_receiver_type_substitutions(
|
|
2216
|
+
binding.with(declared_receiver_type: declared_receiver_type.base),
|
|
2217
|
+
receiver_type.base,
|
|
2218
|
+
)
|
|
2219
|
+
when Types::StructInstance
|
|
2220
|
+
return {} unless declared_receiver_type.definition.is_a?(Types::GenericStructDefinition)
|
|
2238
2221
|
|
|
2239
|
-
|
|
2240
|
-
if declared_argument.is_a?(Types::TypeVar)
|
|
2241
|
-
substitutions[declared_argument.name] = actual_argument
|
|
2242
|
-
elsif declared_argument != actual_argument
|
|
2222
|
+
unless receiver_type.is_a?(Types::StructInstance) && receiver_type.definition == declared_receiver_type.definition
|
|
2243
2223
|
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2244
2224
|
end
|
|
2245
|
-
end
|
|
2246
|
-
when Types::Span
|
|
2247
|
-
return {} unless receiver_type.is_a?(Types::Span)
|
|
2248
2225
|
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2253
|
-
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2254
|
-
end
|
|
2255
|
-
substitutions
|
|
2256
|
-
when Types::Task
|
|
2257
|
-
return {} unless receiver_type.is_a?(Types::Task)
|
|
2226
|
+
declared_receiver_type.definition.type_params.zip(receiver_type.arguments).to_h
|
|
2227
|
+
when Types::VariantInstance
|
|
2228
|
+
return {} unless declared_receiver_type.definition.is_a?(Types::GenericVariantDefinition)
|
|
2258
2229
|
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
2263
|
-
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2264
|
-
end
|
|
2265
|
-
substitutions
|
|
2266
|
-
when Types::SoA
|
|
2267
|
-
return {} unless receiver_type.is_a?(Types::SoA)
|
|
2230
|
+
unless receiver_type.is_a?(Types::VariantInstance) && receiver_type.definition == declared_receiver_type.definition
|
|
2231
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2232
|
+
end
|
|
2268
2233
|
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
end
|
|
2275
|
-
substitutions
|
|
2276
|
-
when Types::Simd
|
|
2277
|
-
return {} unless receiver_type.is_a?(Types::Simd)
|
|
2234
|
+
declared_receiver_type.definition.type_params.zip(receiver_type.arguments).to_h
|
|
2235
|
+
when Types::GenericInstance
|
|
2236
|
+
unless receiver_type.is_a?(Types::GenericInstance) && receiver_type.name == declared_receiver_type.name && receiver_type.arguments.length == declared_receiver_type.arguments.length
|
|
2237
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2238
|
+
end
|
|
2278
2239
|
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
end
|
|
2289
|
-
end
|
|
2240
|
+
declared_receiver_type.arguments.zip(receiver_type.arguments).each_with_object({}) do |(declared_argument, actual_argument), substitutions|
|
|
2241
|
+
if declared_argument.is_a?(Types::TypeVar)
|
|
2242
|
+
substitutions[declared_argument.name] = actual_argument
|
|
2243
|
+
elsif declared_argument != actual_argument
|
|
2244
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2245
|
+
end
|
|
2246
|
+
end
|
|
2247
|
+
when Types::Span
|
|
2248
|
+
return {} unless receiver_type.is_a?(Types::Span)
|
|
2290
2249
|
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2250
|
+
substitutions = {}
|
|
2251
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2252
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2253
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2254
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2255
|
+
end
|
|
2256
|
+
substitutions
|
|
2257
|
+
when Types::Task
|
|
2258
|
+
return {} unless receiver_type.is_a?(Types::Task)
|
|
2259
|
+
|
|
2260
|
+
substitutions = {}
|
|
2261
|
+
if declared_receiver_type.result_type.is_a?(Types::TypeVar)
|
|
2262
|
+
substitutions[declared_receiver_type.result_type.name] = receiver_type.result_type
|
|
2263
|
+
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
2264
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2265
|
+
end
|
|
2266
|
+
substitutions
|
|
2267
|
+
when Types::SoA
|
|
2268
|
+
return {} unless receiver_type.is_a?(Types::SoA)
|
|
2269
|
+
|
|
2270
|
+
substitutions = {}
|
|
2271
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2272
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2273
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2274
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2275
|
+
end
|
|
2276
|
+
substitutions
|
|
2277
|
+
when Types::Simd
|
|
2278
|
+
return {} unless receiver_type.is_a?(Types::Simd)
|
|
2279
|
+
|
|
2280
|
+
substitutions = {}
|
|
2281
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2282
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2283
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2284
|
+
raise LoweringError.new("cannot use method #{binding.name} with receiver #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2285
|
+
end
|
|
2286
|
+
substitutions
|
|
2287
|
+
else
|
|
2288
|
+
{}
|
|
2307
2289
|
end
|
|
2290
|
+
end
|
|
2308
2291
|
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2292
|
+
def collect_type_substitutions(pattern_type, actual_type, substitutions, function_name)
|
|
2293
|
+
case pattern_type
|
|
2294
|
+
when Types::TypeVar
|
|
2295
|
+
existing = substitutions[pattern_type.name]
|
|
2296
|
+
if existing && existing != actual_type
|
|
2297
|
+
raise LoweringError.new("conflicting type argument #{pattern_type.name} for function #{function_name}: got #{existing} and #{actual_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2298
|
+
end
|
|
2313
2299
|
|
|
2314
|
-
|
|
2315
|
-
|
|
2300
|
+
substitutions[pattern_type.name] ||= actual_type
|
|
2301
|
+
when Types::Nullable
|
|
2302
|
+
candidate = actual_type.is_a?(Types::Nullable) ? actual_type.base : actual_type
|
|
2303
|
+
collect_type_substitutions(pattern_type.base, candidate, substitutions, function_name)
|
|
2304
|
+
when Types::GenericInstance
|
|
2305
|
+
if ref_type?(pattern_type) && !ref_type?(actual_type)
|
|
2306
|
+
collect_type_substitutions(referenced_type(pattern_type), actual_type, substitutions, function_name)
|
|
2307
|
+
return
|
|
2308
|
+
end
|
|
2316
2309
|
|
|
2317
|
-
|
|
2318
|
-
|
|
2310
|
+
if own_type?(actual_type) && (mutable_pointer_type?(pattern_type) || const_pointer_type?(pattern_type))
|
|
2311
|
+
collect_type_substitutions(pointee_type(pattern_type), owned_referent_type(actual_type), substitutions, function_name)
|
|
2312
|
+
return
|
|
2313
|
+
end
|
|
2319
2314
|
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
when Types::Span
|
|
2323
|
-
return unless actual_type.is_a?(Types::Span)
|
|
2315
|
+
return unless actual_type.is_a?(Types::GenericInstance)
|
|
2316
|
+
return unless actual_type.name == pattern_type.name && actual_type.arguments.length == pattern_type.arguments.length
|
|
2324
2317
|
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
return unless actual_type.is_a?(Types::Task)
|
|
2318
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
2319
|
+
next if expected_argument.is_a?(Types::LiteralTypeArg)
|
|
2328
2320
|
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2321
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
2322
|
+
end
|
|
2323
|
+
when Types::Span
|
|
2324
|
+
return unless actual_type.is_a?(Types::Span)
|
|
2325
|
+
|
|
2326
|
+
collect_type_substitutions(pattern_type.element_type, actual_type.element_type, substitutions, function_name)
|
|
2327
|
+
when Types::Task
|
|
2328
|
+
return unless actual_type.is_a?(Types::Task)
|
|
2329
|
+
|
|
2330
|
+
collect_type_substitutions(pattern_type.result_type, actual_type.result_type, substitutions, function_name)
|
|
2331
|
+
when Types::Proc
|
|
2332
|
+
if task_root_proc_type?(pattern_type) && actual_type.is_a?(Types::Task)
|
|
2333
|
+
collect_type_substitutions(pattern_type.return_type, actual_type, substitutions, function_name)
|
|
2334
|
+
return
|
|
2335
|
+
end
|
|
2335
2336
|
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2337
|
+
actual_params = case actual_type
|
|
2338
|
+
when Types::Proc
|
|
2339
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
2339
2340
|
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2341
|
+
actual_type.params
|
|
2342
|
+
when Types::Function
|
|
2343
|
+
return if actual_type.receiver_type || actual_type.variadic
|
|
2344
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
2345
|
+
return unless actual_type.params.zip(pattern_type.params).all? { |actual_param, expected_param| actual_param.mutable == expected_param.mutable }
|
|
2345
2346
|
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2347
|
+
actual_type.params
|
|
2348
|
+
else
|
|
2349
|
+
return
|
|
2350
|
+
end
|
|
2350
2351
|
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2352
|
+
pattern_type.params.zip(actual_params).each do |expected_param, actual_param|
|
|
2353
|
+
collect_type_substitutions(expected_param.type, actual_param.type, substitutions, function_name)
|
|
2354
|
+
end
|
|
2355
|
+
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
2356
|
+
when Types::StructInstance
|
|
2357
|
+
return unless actual_type.is_a?(Types::StructInstance)
|
|
2358
|
+
return unless actual_type.definition == pattern_type.definition && actual_type.arguments.length == pattern_type.arguments.length
|
|
2358
2359
|
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2360
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
2361
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
2362
|
+
end
|
|
2363
|
+
when Types::VariantInstance
|
|
2364
|
+
return unless actual_type.is_a?(Types::VariantInstance)
|
|
2365
|
+
return unless actual_type.definition == pattern_type.definition && actual_type.arguments.length == pattern_type.arguments.length
|
|
2365
2366
|
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2367
|
+
pattern_type.arguments.zip(actual_type.arguments).each do |expected_argument, actual_argument|
|
|
2368
|
+
collect_type_substitutions(expected_argument, actual_argument, substitutions, function_name)
|
|
2369
|
+
end
|
|
2370
|
+
when Types::Function
|
|
2371
|
+
return unless actual_type.is_a?(Types::Function)
|
|
2372
|
+
return unless actual_type.params.length == pattern_type.params.length
|
|
2372
2373
|
|
|
2373
|
-
|
|
2374
|
-
|
|
2374
|
+
pattern_type.params.zip(actual_type.params).each do |expected_param, actual_param|
|
|
2375
|
+
collect_type_substitutions(expected_param.type, actual_param.type, substitutions, function_name)
|
|
2376
|
+
end
|
|
2377
|
+
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
2375
2378
|
end
|
|
2376
|
-
collect_type_substitutions(pattern_type.return_type, actual_type.return_type, substitutions, function_name)
|
|
2377
2379
|
end
|
|
2378
|
-
end
|
|
2379
2380
|
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2381
|
+
def substitute_value_binding(binding, substitutions)
|
|
2382
|
+
Bindings::ValueBinding.new(
|
|
2383
|
+
id: binding.id,
|
|
2384
|
+
name: binding.name,
|
|
2385
|
+
storage_type: substitute_type(binding.storage_type, substitutions),
|
|
2386
|
+
flow_type: binding.flow_type ? substitute_type(binding.flow_type, substitutions) : nil,
|
|
2387
|
+
mutable: binding.mutable,
|
|
2388
|
+
kind: binding.kind,
|
|
2389
|
+
const_value: binding.const_value,
|
|
2390
|
+
)
|
|
2391
|
+
end
|
|
2391
2392
|
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2393
|
+
def substitute_type(type, substitutions)
|
|
2394
|
+
Types::SubstituteTypeVisitor.new(substitutions).apply(type)
|
|
2395
|
+
end
|
|
2395
2396
|
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2397
|
+
def analysis_for_module(module_name)
|
|
2398
|
+
@program.analyses_by_module_name.fetch(module_name)
|
|
2399
|
+
end
|
|
2399
2400
|
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2401
|
+
def each_raw_module_analysis(&block)
|
|
2402
|
+
return @program.analyses_by_module_name.each_value.select { |a| a.module_kind == :raw_module }.each unless block
|
|
2403
|
+
@program.analyses_by_module_name.each_value { |a| block.call(a) if a.module_kind == :raw_module }
|
|
2404
|
+
end
|
|
2404
2405
|
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2406
|
+
def each_non_raw_module_analysis(&block)
|
|
2407
|
+
return @program.analyses_by_module_name.each_value.reject { |a| a.module_kind == :raw_module }.each unless block
|
|
2408
|
+
@program.analyses_by_module_name.each_value { |a| block.call(a) unless a.module_kind == :raw_module }
|
|
2409
|
+
end
|
|
2409
2410
|
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2411
|
+
def types_for_module(module_name)
|
|
2412
|
+
@program.analyses_by_module_name.fetch(module_name).types
|
|
2413
|
+
end
|
|
2413
2414
|
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2415
|
+
def imports_for_module(module_name)
|
|
2416
|
+
@program.analyses_by_module_name.fetch(module_name).imports
|
|
2417
|
+
end
|
|
2417
2418
|
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2419
|
+
def const_declaration_for_module(module_name, name)
|
|
2420
|
+
analysis = @program.analyses_by_module_name.fetch(module_name)
|
|
2421
|
+
declaration = analysis.ast.declarations.find { |decl| decl.is_a?(AST::ConstDecl) && decl.name == name }
|
|
2422
|
+
raise LoweringError.new("unknown constant #{analysis.module_name}.#{name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless declaration
|
|
2422
2423
|
|
|
2423
|
-
|
|
2424
|
-
|
|
2424
|
+
declaration
|
|
2425
|
+
end
|
|
2425
2426
|
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2427
|
+
def resolve_type_ref_for_analysis(type_ref, analysis, type_params: current_type_params)
|
|
2428
|
+
saved = @ctx.save
|
|
2429
|
+
@ctx.install(analysis)
|
|
2430
|
+
@ctx.module_prefix = module_c_prefix(@ctx.module_name)
|
|
2431
|
+
resolve_type_ref(type_ref, type_params:)
|
|
2432
|
+
ensure
|
|
2433
|
+
@ctx.restore(saved)
|
|
2434
|
+
end
|
|
2434
2435
|
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2436
|
+
def current_type_params
|
|
2437
|
+
@ctx.current_type_substitutions || {}
|
|
2438
|
+
end
|
|
2438
2439
|
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2440
|
+
def resolve_type_ref(type_ref, type_params: current_type_params)
|
|
2441
|
+
if type_ref.is_a?(AST::FunctionType)
|
|
2442
|
+
params = type_ref.params.map do |param|
|
|
2443
|
+
Types::Registry.parameter(param.name, resolve_type_ref(param.type, type_params:))
|
|
2444
|
+
end
|
|
2445
|
+
return Types::Registry.function(nil, params:, return_type: resolve_type_ref(type_ref.return_type, type_params:))
|
|
2443
2446
|
end
|
|
2444
|
-
return Types::Registry.function(nil, params:, return_type: resolve_type_ref(type_ref.return_type, type_params:))
|
|
2445
|
-
end
|
|
2446
2447
|
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2448
|
+
if type_ref.is_a?(AST::ProcType)
|
|
2449
|
+
params = type_ref.params.map do |param|
|
|
2450
|
+
Types::Registry.parameter(param.name, resolve_type_ref(param.type, type_params:))
|
|
2451
|
+
end
|
|
2452
|
+
return Types::Registry.proc(params:, return_type: resolve_type_ref(type_ref.return_type, type_params:))
|
|
2450
2453
|
end
|
|
2451
|
-
return Types::Registry.proc(params:, return_type: resolve_type_ref(type_ref.return_type, type_params:))
|
|
2452
|
-
end
|
|
2453
2454
|
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2455
|
+
if type_ref.is_a?(AST::DynType)
|
|
2456
|
+
interface = resolve_interface_ref(type_ref.interface)
|
|
2457
|
+
raise LoweringError.new("generic interface requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path) if interface.respond_to?(:instantiate)
|
|
2458
|
+
type_arguments = interface.respond_to?(:type_arguments) ? (interface.type_arguments || []) : []
|
|
2459
|
+
return Types::Dyn.new(interface, type_arguments)
|
|
2460
|
+
end
|
|
2460
2461
|
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2462
|
+
if type_ref.is_a?(AST::TupleType)
|
|
2463
|
+
names = []
|
|
2464
|
+
element_types = []
|
|
2465
|
+
type_ref.element_types.each do |et|
|
|
2466
|
+
if et.is_a?(AST::Argument)
|
|
2467
|
+
names << et.name
|
|
2468
|
+
element_types << resolve_type_ref(et.value, type_params:)
|
|
2469
|
+
else
|
|
2470
|
+
names << nil
|
|
2471
|
+
element_types << resolve_type_ref(et, type_params:)
|
|
2472
|
+
end
|
|
2471
2473
|
end
|
|
2474
|
+
has_named = names.any?
|
|
2475
|
+
return Types::Registry.tuple(element_types, field_names: has_named ? names : nil)
|
|
2472
2476
|
end
|
|
2473
|
-
has_named = names.any?
|
|
2474
|
-
return Types::Registry.tuple(element_types, field_names: has_named ? names : nil)
|
|
2475
|
-
end
|
|
2476
2477
|
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2478
|
+
parts = type_ref.name.parts
|
|
2479
|
+
base = if type_ref.arguments.any?
|
|
2480
|
+
name = parts.join(".")
|
|
2481
|
+
args = type_ref.arguments.map { |argument| resolve_type_argument(argument.value, type_params:) }
|
|
2482
|
+
if name != "ref" && args.any? { |argument| contains_ref_type?(argument) && !stored_ref_supported_type?(argument) }
|
|
2483
|
+
raise LoweringError.new("ref types cannot be nested inside #{name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2484
|
+
end
|
|
2485
|
+
if name == "Task"
|
|
2486
|
+
validate_generic_type!(name, args)
|
|
2487
|
+
Types::Registry.task(args.fetch(0))
|
|
2488
|
+
elsif (generic_type = resolve_named_generic_type(parts))
|
|
2489
|
+
generic_type.instantiate(args)
|
|
2490
|
+
elsif name == "span"
|
|
2491
|
+
Types::Registry.span(args.fetch(0))
|
|
2492
|
+
elsif name == "SoA"
|
|
2493
|
+
validate_generic_type!(name, args)
|
|
2494
|
+
Types::Registry.soa(args.fetch(0), count: args.fetch(1).value)
|
|
2495
|
+
elsif name == "simd"
|
|
2496
|
+
validate_generic_type!(name, args)
|
|
2497
|
+
Types::Registry.simd(args.fetch(0), lane_count: args.fetch(1).value)
|
|
2498
|
+
else
|
|
2499
|
+
validate_generic_type!(name, args)
|
|
2500
|
+
args = [type_ref.lifetime] + args if name == "ref" && type_ref.lifetime
|
|
2501
|
+
Types::Registry.generic_instance(name, args)
|
|
2502
|
+
end
|
|
2503
|
+
elsif parts.length == 1 && type_params.key?(parts.first)
|
|
2504
|
+
type_params.fetch(parts.first)
|
|
2505
|
+
elsif parts.length == 1
|
|
2506
|
+
type = @ctx.types[parts.first]
|
|
2507
|
+
raise LoweringError.new("unknown type #{parts.first}", line: 0, column: 0, path: @ctx.current_analysis_path) unless type
|
|
2508
|
+
raise LoweringError.new("generic type #{parts.first} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path) if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2509
|
+
|
|
2510
|
+
type
|
|
2511
|
+
elsif parts.length >= 2
|
|
2512
|
+
type = resolve_nested_type_ref(parts)
|
|
2513
|
+
|
|
2514
|
+
unless type
|
|
2515
|
+
if @ctx.imports.key?(parts.first)
|
|
2516
|
+
imported_module = @ctx.imports.fetch(parts.first)
|
|
2517
|
+
if imported_module.private_type?(parts.last)
|
|
2518
|
+
raise LoweringError.new("#{parts.first}.#{parts.last} is private to module #{imported_module.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2501
2519
|
end
|
|
2502
|
-
elsif parts.length == 1 && type_params.key?(parts.first)
|
|
2503
|
-
type_params.fetch(parts.first)
|
|
2504
|
-
elsif parts.length == 1
|
|
2505
|
-
type = @ctx.types[parts.first]
|
|
2506
|
-
raise LoweringError.new("unknown type #{parts.first}", line: 0, column: 0, path: @ctx.current_analysis_path) unless type
|
|
2507
|
-
raise LoweringError.new("generic type #{parts.first} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path) if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2508
|
-
|
|
2509
|
-
type
|
|
2510
|
-
elsif parts.length >= 2
|
|
2511
|
-
type = resolve_nested_type_ref(parts)
|
|
2512
2520
|
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2521
|
+
type = imported_module.types[parts.last]
|
|
2522
|
+
raise LoweringError.new("unknown type #{type_ref.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless type
|
|
2523
|
+
raise LoweringError.new("generic type #{type_ref.name} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path) if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2524
|
+
elsif @type_resolution_env && (field_type = resolve_field_handle_type_ref(parts))
|
|
2525
|
+
type = field_type
|
|
2526
|
+
else
|
|
2527
|
+
raise LoweringError.new("unknown type #{type_ref.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2518
2528
|
end
|
|
2519
|
-
|
|
2520
|
-
type = imported_module.types[parts.last]
|
|
2521
|
-
raise LoweringError.new("unknown type #{type_ref.name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless type
|
|
2522
|
-
raise LoweringError.new("generic type #{type_ref.name} requires type arguments", line: 0, column: 0, path: @ctx.current_analysis_path) if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2523
|
-
elsif @type_resolution_env && (field_type = resolve_field_handle_type_ref(parts))
|
|
2524
|
-
type = field_type
|
|
2525
|
-
else
|
|
2526
|
-
raise LoweringError.new("unknown type #{type_ref.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2527
2529
|
end
|
|
2528
|
-
end
|
|
2529
2530
|
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2531
|
+
type
|
|
2532
|
+
else
|
|
2533
|
+
raise LoweringError.new("unknown type #{type_ref.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
2534
|
+
end
|
|
2534
2535
|
|
|
2535
|
-
|
|
2536
|
+
raise LoweringError.new("ref types are non-null and cannot be nullable", line: 0, column: 0, path: @ctx.current_analysis_path) if type_ref.nullable && ref_type?(base)
|
|
2536
2537
|
|
|
2537
|
-
|
|
2538
|
-
|
|
2538
|
+
type_ref.nullable ? Types::Registry.nullable(base) : base
|
|
2539
|
+
end
|
|
2539
2540
|
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2541
|
+
def resolve_nested_type_ref(parts)
|
|
2542
|
+
current = @ctx.types[parts.first]
|
|
2543
|
+
return nil unless current.is_a?(Types::Struct) || current.is_a?(Types::GenericStructDefinition)
|
|
2543
2544
|
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2545
|
+
parts[1..].each do |part|
|
|
2546
|
+
nested = current.respond_to?(:nested_types) ? current.nested_types[part] : nil
|
|
2547
|
+
return nil unless nested
|
|
2548
|
+
current = nested
|
|
2549
|
+
end
|
|
2550
|
+
current
|
|
2548
2551
|
end
|
|
2549
|
-
current
|
|
2550
|
-
end
|
|
2551
2552
|
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2556
|
-
elsif parts.length >= 2
|
|
2557
|
-
type = resolve_nested_type_ref(parts)
|
|
2558
|
-
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2559
|
-
if @ctx.imports.key?(parts.first)
|
|
2560
|
-
type = @ctx.imports.fetch(parts.first).types[parts.last]
|
|
2553
|
+
def resolve_named_generic_type(parts)
|
|
2554
|
+
if parts.length == 1
|
|
2555
|
+
type = @ctx.types[parts.first]
|
|
2561
2556
|
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2557
|
+
elsif parts.length >= 2
|
|
2558
|
+
type = resolve_nested_type_ref(parts)
|
|
2559
|
+
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2560
|
+
if @ctx.imports.key?(parts.first)
|
|
2561
|
+
type = @ctx.imports.fetch(parts.first).types[parts.last]
|
|
2562
|
+
return type if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
2563
|
+
end
|
|
2562
2564
|
end
|
|
2563
|
-
end
|
|
2564
2565
|
|
|
2565
|
-
|
|
2566
|
-
|
|
2566
|
+
nil
|
|
2567
|
+
end
|
|
2567
2568
|
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2569
|
+
# Resolves a bare dotted reflection type ref `field.type` (where `field` is
|
|
2570
|
+
# a compile-time `field_handle` bound in the active inline-for env) to the
|
|
2571
|
+
# field's concrete type. Mirrors the sema-side `resolve_compile_time_type_ref`.
|
|
2572
|
+
def resolve_field_handle_type_ref(parts)
|
|
2573
|
+
return nil unless parts.length == 2 && parts.last == "type"
|
|
2573
2574
|
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2575
|
+
binding = lookup_value(parts.first, @type_resolution_env)
|
|
2576
|
+
handle = binding && binding[:const_value]
|
|
2577
|
+
return nil unless handle.is_a?(Types::FieldHandle)
|
|
2577
2578
|
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2579
|
+
# Use the struct's already-resolved field type (module-independent) rather
|
|
2580
|
+
# than re-resolving the field's declared TypeRef, which would look up a
|
|
2581
|
+
# user struct name in this (std) module's scope and fail.
|
|
2582
|
+
handle.struct_handle.struct_type.field(handle.field_name)
|
|
2583
|
+
end
|
|
2583
2584
|
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2585
|
+
def infer_field_handle_member_type(expression)
|
|
2586
|
+
case expression.member
|
|
2587
|
+
when "name" then @ctx.types["str"]
|
|
2588
|
+
when "type"
|
|
2589
|
+
handle = compile_time_const_value(expression.receiver, env: nil)
|
|
2590
|
+
return @error_type unless handle.is_a?(Types::FieldHandle)
|
|
2590
2591
|
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2592
|
+
resolve_type_ref(handle.field_declaration.type)
|
|
2593
|
+
else
|
|
2594
|
+
@error_type
|
|
2595
|
+
end
|
|
2594
2596
|
end
|
|
2595
|
-
end
|
|
2596
2597
|
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2598
|
+
def infer_member_handle_member_type(expression)
|
|
2599
|
+
case expression.member
|
|
2600
|
+
when "name" then @ctx.types["str"]
|
|
2601
|
+
when "value" then @ctx.types["int"]
|
|
2602
|
+
else @error_type
|
|
2603
|
+
end
|
|
2602
2604
|
end
|
|
2603
|
-
end
|
|
2604
2605
|
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2606
|
+
def resolve_interface_ref(interface_ref)
|
|
2607
|
+
parts = interface_ref.parts
|
|
2608
|
+
interface = if parts.length == 1
|
|
2609
|
+
@ctx.interfaces[parts.first]
|
|
2610
|
+
elsif parts.length == 2 && @ctx.imports.key?(parts.first)
|
|
2611
|
+
@ctx.imports.fetch(parts.first).interfaces[parts.last]
|
|
2612
|
+
end
|
|
2613
|
+
raise LoweringError.new("unknown interface #{interface_ref}", line: 0, column: 0, path: @ctx.current_analysis_path) unless interface
|
|
2614
|
+
|
|
2615
|
+
if interface_ref.type_arguments.any?
|
|
2616
|
+
raise LoweringError.new("interface #{interface.name} is not generic", line: 0, column: 0, path: @ctx.current_analysis_path) unless interface.respond_to?(:instantiate)
|
|
2617
|
+
type_args = interface_ref.type_arguments.map { |arg| resolve_type_ref(arg) }
|
|
2618
|
+
interface.instantiate(type_args)
|
|
2619
|
+
else
|
|
2620
|
+
interface
|
|
2621
|
+
end
|
|
2620
2622
|
end
|
|
2621
2623
|
end
|
|
2622
2624
|
end
|