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