mt-lang 0.2.0

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