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,1545 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CBackend
5
+ module TypeCollectors
6
+ private
7
+
8
+ def collect_checked_array_index_types(nullable_only: false)
9
+ array_types = []
10
+ emitted_functions.each do |function|
11
+ collect_checked_array_index_types_from_statements(function.body, array_types, nullable_only:)
12
+ end
13
+ array_types.uniq
14
+ end
15
+
16
+ def collect_checked_span_index_types(nullable_only: false)
17
+ span_types = []
18
+ emitted_functions.each do |function|
19
+ collect_checked_span_index_types_from_statements(function.body, span_types, nullable_only:)
20
+ end
21
+ span_types.uniq
22
+ end
23
+
24
+ def collect_checked_array_index_types_from_statements(statements, array_types, nullable_only: false)
25
+ statements.each do |statement|
26
+ case statement
27
+ when IR::LocalDecl
28
+ collect_checked_array_index_types_from_expression(statement.value, array_types, nullable_only:)
29
+ when IR::Assignment
30
+ collect_checked_array_index_types_from_expression(statement.target, array_types, nullable_only:)
31
+ collect_checked_array_index_types_from_expression(statement.value, array_types, nullable_only:)
32
+ when IR::BlockStmt
33
+ collect_checked_array_index_types_from_statements(statement.body, array_types, nullable_only:)
34
+ when IR::WhileStmt
35
+ collect_checked_array_index_types_from_expression(statement.condition, array_types, nullable_only:)
36
+ collect_checked_array_index_types_from_statements(statement.body, array_types, nullable_only:)
37
+ when IR::ForStmt
38
+ collect_checked_array_index_types_from_statements([statement.init], array_types, nullable_only:)
39
+ collect_checked_array_index_types_from_expression(statement.condition, array_types, nullable_only:)
40
+ collect_checked_array_index_types_from_statements(statement.body, array_types, nullable_only:)
41
+ collect_checked_array_index_types_from_statements([statement.post], array_types, nullable_only:)
42
+ when IR::IfStmt
43
+ collect_checked_array_index_types_from_expression(statement.condition, array_types, nullable_only:)
44
+ collect_checked_array_index_types_from_statements(statement.then_body, array_types, nullable_only:)
45
+ collect_checked_array_index_types_from_statements(statement.else_body, array_types, nullable_only:) if statement.else_body
46
+ when IR::SwitchStmt
47
+ collect_checked_array_index_types_from_expression(statement.expression, array_types, nullable_only:)
48
+ statement.cases.each do |switch_case|
49
+ collect_checked_array_index_types_from_statements(switch_case.body, array_types, nullable_only:)
50
+ end
51
+ when IR::StaticAssert
52
+ collect_checked_array_index_types_from_expression(statement.condition, array_types, nullable_only:)
53
+ collect_checked_array_index_types_from_expression(statement.message, array_types, nullable_only:)
54
+ when IR::ReturnStmt
55
+ collect_checked_array_index_types_from_expression(statement.value, array_types, nullable_only:) if statement.value
56
+ when IR::ExpressionStmt
57
+ collect_checked_array_index_types_from_expression(statement.expression, array_types, nullable_only:)
58
+ end
59
+ end
60
+ end
61
+
62
+ def collect_checked_array_index_types_from_expression(expression, array_types, nullable_only: false)
63
+ case expression
64
+ when IR::Member
65
+ collect_checked_array_index_types_from_expression(expression.receiver, array_types, nullable_only:)
66
+ when IR::Index
67
+ collect_checked_array_index_types_from_expression(expression.receiver, array_types, nullable_only:)
68
+ collect_checked_array_index_types_from_expression(expression.index, array_types, nullable_only:)
69
+ when IR::CheckedIndex
70
+ array_types << expression.receiver_type unless nullable_only
71
+ collect_checked_array_index_types_from_expression(expression.receiver, array_types, nullable_only:)
72
+ collect_checked_array_index_types_from_expression(expression.index, array_types, nullable_only:)
73
+ when IR::NullableIndex
74
+ array_types << expression.receiver_type
75
+ collect_checked_array_index_types_from_expression(expression.receiver, array_types, nullable_only:)
76
+ collect_checked_array_index_types_from_expression(expression.index, array_types, nullable_only:)
77
+ when IR::Call
78
+ collect_checked_array_index_types_from_expression(expression.callee, array_types, nullable_only:) unless expression.callee.is_a?(String)
79
+ expression.arguments.each { |argument| collect_checked_array_index_types_from_expression(argument, array_types, nullable_only:) }
80
+ when IR::Unary
81
+ collect_checked_array_index_types_from_expression(expression.operand, array_types, nullable_only:)
82
+ when IR::Binary
83
+ collect_checked_array_index_types_from_expression(expression.left, array_types, nullable_only:)
84
+ collect_checked_array_index_types_from_expression(expression.right, array_types, nullable_only:)
85
+ when IR::Conditional
86
+ collect_checked_array_index_types_from_expression(expression.condition, array_types, nullable_only:)
87
+ collect_checked_array_index_types_from_expression(expression.then_expression, array_types, nullable_only:)
88
+ collect_checked_array_index_types_from_expression(expression.else_expression, array_types, nullable_only:)
89
+ when IR::ReinterpretExpr
90
+ collect_checked_array_index_types_from_expression(expression.expression, array_types, nullable_only:)
91
+ when IR::AddressOf
92
+ collect_checked_array_index_types_from_expression(expression.expression, array_types, nullable_only:)
93
+ when IR::Cast
94
+ collect_checked_array_index_types_from_expression(expression.expression, array_types, nullable_only:)
95
+ when IR::AggregateLiteral
96
+ expression.fields.each { |field| collect_checked_array_index_types_from_expression(field.value, array_types, nullable_only:) }
97
+ when IR::ArrayLiteral
98
+ expression.elements.each { |element| collect_checked_array_index_types_from_expression(element, array_types, nullable_only:) }
99
+ when IR::VariantLiteral
100
+ expression.fields.each { |field| collect_checked_array_index_types_from_expression(field.value, array_types, nullable_only:) }
101
+ end
102
+ end
103
+
104
+ def collect_checked_span_index_types_from_statements(statements, span_types, nullable_only: false)
105
+ statements.each do |statement|
106
+ case statement
107
+ when IR::LocalDecl
108
+ collect_checked_span_index_types_from_expression(statement.value, span_types, nullable_only:)
109
+ when IR::Assignment
110
+ collect_checked_span_index_types_from_expression(statement.target, span_types, nullable_only:)
111
+ collect_checked_span_index_types_from_expression(statement.value, span_types, nullable_only:)
112
+ when IR::BlockStmt
113
+ collect_checked_span_index_types_from_statements(statement.body, span_types, nullable_only:)
114
+ when IR::WhileStmt
115
+ collect_checked_span_index_types_from_expression(statement.condition, span_types, nullable_only:)
116
+ collect_checked_span_index_types_from_statements(statement.body, span_types, nullable_only:)
117
+ when IR::ForStmt
118
+ collect_checked_span_index_types_from_statements([statement.init], span_types, nullable_only:)
119
+ collect_checked_span_index_types_from_expression(statement.condition, span_types, nullable_only:)
120
+ collect_checked_span_index_types_from_statements(statement.body, span_types, nullable_only:)
121
+ collect_checked_span_index_types_from_statements([statement.post], span_types, nullable_only:)
122
+ when IR::IfStmt
123
+ collect_checked_span_index_types_from_expression(statement.condition, span_types, nullable_only:)
124
+ collect_checked_span_index_types_from_statements(statement.then_body, span_types, nullable_only:)
125
+ collect_checked_span_index_types_from_statements(statement.else_body, span_types, nullable_only:) if statement.else_body
126
+ when IR::SwitchStmt
127
+ collect_checked_span_index_types_from_expression(statement.expression, span_types, nullable_only:)
128
+ statement.cases.each do |switch_case|
129
+ collect_checked_span_index_types_from_statements(switch_case.body, span_types, nullable_only:)
130
+ end
131
+ when IR::StaticAssert
132
+ collect_checked_span_index_types_from_expression(statement.condition, span_types, nullable_only:)
133
+ collect_checked_span_index_types_from_expression(statement.message, span_types, nullable_only:)
134
+ when IR::ReturnStmt
135
+ collect_checked_span_index_types_from_expression(statement.value, span_types, nullable_only:) if statement.value
136
+ when IR::ExpressionStmt
137
+ collect_checked_span_index_types_from_expression(statement.expression, span_types, nullable_only:)
138
+ end
139
+ end
140
+ end
141
+
142
+ def collect_checked_span_index_types_from_expression(expression, span_types, nullable_only: false)
143
+ case expression
144
+ when IR::Member
145
+ collect_checked_span_index_types_from_expression(expression.receiver, span_types, nullable_only:)
146
+ when IR::Index, IR::CheckedIndex, IR::NullableIndex
147
+ collect_checked_span_index_types_from_expression(expression.receiver, span_types, nullable_only:)
148
+ collect_checked_span_index_types_from_expression(expression.index, span_types, nullable_only:)
149
+ when IR::CheckedSpanIndex
150
+ span_types << expression.receiver_type unless nullable_only
151
+ collect_checked_span_index_types_from_expression(expression.receiver, span_types, nullable_only:)
152
+ collect_checked_span_index_types_from_expression(expression.index, span_types, nullable_only:)
153
+ when IR::NullableSpanIndex
154
+ span_types << expression.receiver_type
155
+ collect_checked_span_index_types_from_expression(expression.receiver, span_types, nullable_only:)
156
+ collect_checked_span_index_types_from_expression(expression.index, span_types, nullable_only:)
157
+ when IR::Call
158
+ collect_checked_span_index_types_from_expression(expression.callee, span_types, nullable_only:) unless expression.callee.is_a?(String)
159
+ expression.arguments.each { |argument| collect_checked_span_index_types_from_expression(argument, span_types, nullable_only:) }
160
+ when IR::Unary
161
+ collect_checked_span_index_types_from_expression(expression.operand, span_types, nullable_only:)
162
+ when IR::Binary
163
+ collect_checked_span_index_types_from_expression(expression.left, span_types, nullable_only:)
164
+ collect_checked_span_index_types_from_expression(expression.right, span_types, nullable_only:)
165
+ when IR::Conditional
166
+ collect_checked_span_index_types_from_expression(expression.condition, span_types, nullable_only:)
167
+ collect_checked_span_index_types_from_expression(expression.then_expression, span_types, nullable_only:)
168
+ collect_checked_span_index_types_from_expression(expression.else_expression, span_types, nullable_only:)
169
+ when IR::ReinterpretExpr
170
+ collect_checked_span_index_types_from_expression(expression.expression, span_types, nullable_only:)
171
+ when IR::AddressOf
172
+ collect_checked_span_index_types_from_expression(expression.expression, span_types, nullable_only:)
173
+ when IR::Cast
174
+ collect_checked_span_index_types_from_expression(expression.expression, span_types, nullable_only:)
175
+ when IR::AggregateLiteral
176
+ expression.fields.each { |field| collect_checked_span_index_types_from_expression(field.value, span_types, nullable_only:) }
177
+ when IR::ArrayLiteral
178
+ expression.elements.each { |element| collect_checked_span_index_types_from_expression(element, span_types, nullable_only:) }
179
+ when IR::VariantLiteral
180
+ expression.fields.each { |field| collect_checked_span_index_types_from_expression(field.value, span_types, nullable_only:) }
181
+ end
182
+ end
183
+
184
+ def collect_span_types
185
+ span_types = []
186
+ visited = {}
187
+
188
+ all_emitted_top_level_values.each do |value|
189
+ collect_span_type(value.type, span_types, visited)
190
+ end
191
+
192
+ @program.structs.each do |struct_decl|
193
+ struct_decl.fields.each do |field|
194
+ collect_span_type(field.type, span_types, visited)
195
+ end
196
+ end
197
+
198
+ @program.unions.each do |union_decl|
199
+ union_decl.fields.each do |field|
200
+ collect_span_type(field.type, span_types, visited)
201
+ end
202
+ end
203
+
204
+ each_variant_arm_field_type do |field_type|
205
+ collect_span_type(field_type, span_types, visited)
206
+ end
207
+
208
+ emitted_functions.each do |function|
209
+ collect_span_type(function.return_type, span_types, visited)
210
+ function.params.each do |param|
211
+ collect_span_type(param.type, span_types, visited)
212
+ end
213
+ collect_span_types_from_statements(function.body, span_types, visited)
214
+ end
215
+
216
+ @program.static_asserts.each do |statement|
217
+ collect_span_types_from_expression(statement.condition, span_types, visited)
218
+ collect_span_types_from_expression(statement.message, span_types, visited)
219
+ end
220
+
221
+ span_types.uniq
222
+ end
223
+
224
+ def collect_soa_types
225
+ soa_types = []
226
+ visited = {}
227
+
228
+ emitted_functions.each do |function|
229
+ collect_soa_type(function.return_type, soa_types, visited)
230
+ function.params.each do |param|
231
+ collect_soa_type(param.type, soa_types, visited)
232
+ end
233
+ collect_soa_from_statements(function.body, soa_types, visited)
234
+ end
235
+
236
+ @program.structs.each do |struct_decl|
237
+ struct_decl.fields.each do |field|
238
+ collect_soa_type(field.type, soa_types, visited)
239
+ end
240
+ end
241
+
242
+ soa_types.uniq
243
+ end
244
+
245
+ def collect_soa_from_statements(statements, soa_types, visited)
246
+ statements.each do |stmt|
247
+ case stmt
248
+ when IR::LocalDecl
249
+ collect_soa_type(stmt.type, soa_types, visited)
250
+ when IR::BlockStmt
251
+ collect_soa_from_statements(stmt.body, soa_types, visited)
252
+ when IR::IfStmt
253
+ collect_soa_from_statements(stmt.then_body || [], soa_types, visited)
254
+ collect_soa_from_statements(stmt.else_body || [], soa_types, visited)
255
+ when IR::WhileStmt
256
+ collect_soa_from_statements(stmt.body || [], soa_types, visited)
257
+ when IR::ForStmt
258
+ collect_soa_from_statements(stmt.body || [], soa_types, visited)
259
+ end
260
+ end
261
+ end
262
+
263
+ def collect_soa_type(type, soa_types, visited)
264
+ return unless type
265
+ return if visited[type]
266
+
267
+ if type.is_a?(Types::SoA)
268
+ soa_types << type
269
+ visited[type] = true
270
+ end
271
+ end
272
+
273
+ def collect_generic_struct_decls
274
+ collect_generic_struct_types.map do |type|
275
+ fields = type.fields.map { |field_name, field_type| IR::Field.new(name: field_name, type: field_type) }
276
+ if type.respond_to?(:events)
277
+ type.events.each_value do |event_type|
278
+ fields << IR::Field.new(name: event_type.hidden_field_name, type: event_type)
279
+ end
280
+ end
281
+ IR::StructDecl.new(
282
+ name: type.to_s,
283
+ linkage_name: named_type_c_name(type),
284
+ fields:,
285
+ packed: type.packed,
286
+ alignment: type.alignment,
287
+ )
288
+ end
289
+ end
290
+
291
+ def collect_task_decls
292
+ collect_task_types.map do |type|
293
+ IR::StructDecl.new(
294
+ name: type.to_s,
295
+ linkage_name: task_type_name(type),
296
+ fields: type.fields.map { |field_name, field_type| IR::Field.new(name: field_name, type: field_type) },
297
+ packed: false,
298
+ alignment: nil,
299
+ )
300
+ end
301
+ end
302
+
303
+ def collect_proc_decls
304
+ collect_proc_types.map do |type|
305
+ IR::StructDecl.new(
306
+ name: type.to_s,
307
+ linkage_name: proc_type_name(type),
308
+ fields: proc_field_types(type).map { |field_name, field_type| IR::Field.new(name: field_name, type: field_type) },
309
+ packed: false,
310
+ alignment: nil,
311
+ )
312
+ end
313
+ end
314
+
315
+ def proc_field_types(type)
316
+ void_ptr = Types::Registry.generic_instance("ptr", [Types::Registry.primitive("void")])
317
+
318
+ {
319
+ "env" => void_ptr,
320
+ "invoke" => Types::Registry.function(nil, params: [Types::Registry.parameter("env", void_ptr)] + type.params, return_type: type.return_type),
321
+ "release" => Types::Registry.function(nil, params: [Types::Registry.parameter("env", void_ptr)], return_type: Types::Registry.primitive("void")),
322
+ "retain" => Types::Registry.function(nil, params: [Types::Registry.parameter("env", void_ptr)], return_type: Types::Registry.primitive("void")),
323
+ }
324
+ end
325
+
326
+ def collect_str_buffer_decls
327
+ collect_str_buffer_types.map do |type|
328
+ IR::StructDecl.new(
329
+ name: type.to_s,
330
+ linkage_name: str_buffer_type_name(type),
331
+ fields: [
332
+ IR::Field.new(name: "data", type: Types::Registry.generic_instance("array", [Types::Registry.primitive("char"), Types::LiteralTypeArg.new(str_buffer_storage_capacity(type))])),
333
+ IR::Field.new(name: "len", type: Types::Registry.primitive("ptr_uint")),
334
+ IR::Field.new(name: "dirty", type: Types::Registry.primitive("bool")),
335
+ ],
336
+ packed: false,
337
+ alignment: nil,
338
+ )
339
+ end
340
+ end
341
+
342
+ def collect_generic_variant_decls
343
+ collect_generic_variant_types.map do |type|
344
+ outer_c = named_type_c_name(type)
345
+ arms = type.arm_names.map do |arm_name|
346
+ fields = type.arm(arm_name)
347
+ IR::VariantArm.new(
348
+ name: arm_name,
349
+ linkage_name: "#{outer_c}_#{arm_name}",
350
+ fields: fields.map { |field_name, field_type| IR::Field.new(name: field_name, type: field_type) },
351
+ )
352
+ end
353
+ IR::VariantDecl.new(name: type.to_s, linkage_name: outer_c, arms:)
354
+ end
355
+ end
356
+
357
+ def collect_task_types
358
+ task_types = []
359
+ visited = {}
360
+
361
+ all_emitted_top_level_values.each do |value|
362
+ collect_task_type(value.type, task_types, visited)
363
+ end
364
+
365
+ @program.structs.each do |struct_decl|
366
+ struct_decl.fields.each do |field|
367
+ collect_task_type(field.type, task_types, visited)
368
+ end
369
+ end
370
+
371
+ @program.unions.each do |union_decl|
372
+ union_decl.fields.each do |field|
373
+ collect_task_type(field.type, task_types, visited)
374
+ end
375
+ end
376
+
377
+ each_variant_arm_field_type do |field_type|
378
+ collect_task_type(field_type, task_types, visited)
379
+ end
380
+
381
+ emitted_functions.each do |function|
382
+ collect_task_type(function.return_type, task_types, visited)
383
+ function.params.each do |param|
384
+ collect_task_type(param.type, task_types, visited)
385
+ end
386
+ collect_task_types_from_statements(function.body, task_types, visited)
387
+ end
388
+
389
+ @program.static_asserts.each do |statement|
390
+ collect_task_types_from_expression(statement.condition, task_types, visited)
391
+ collect_task_types_from_expression(statement.message, task_types, visited)
392
+ end
393
+
394
+ task_types
395
+ end
396
+
397
+ def collect_proc_types
398
+ proc_types = []
399
+ visited = {}
400
+
401
+ all_emitted_top_level_values.each do |value|
402
+ collect_proc_type(value.type, proc_types, visited)
403
+ end
404
+
405
+ @program.structs.each do |struct_decl|
406
+ struct_decl.fields.each do |field|
407
+ collect_proc_type(field.type, proc_types, visited)
408
+ end
409
+ end
410
+
411
+ @program.unions.each do |union_decl|
412
+ union_decl.fields.each do |field|
413
+ collect_proc_type(field.type, proc_types, visited)
414
+ end
415
+ end
416
+
417
+ each_variant_arm_field_type do |field_type|
418
+ collect_proc_type(field_type, proc_types, visited)
419
+ end
420
+
421
+ emitted_functions.each do |function|
422
+ collect_proc_type(function.return_type, proc_types, visited)
423
+ function.params.each do |param|
424
+ collect_proc_type(param.type, proc_types, visited)
425
+ end
426
+ collect_proc_types_from_statements(function.body, proc_types, visited)
427
+ end
428
+
429
+ @program.static_asserts.each do |statement|
430
+ collect_proc_types_from_expression(statement.condition, proc_types, visited)
431
+ collect_proc_types_from_expression(statement.message, proc_types, visited)
432
+ end
433
+
434
+ proc_types
435
+ end
436
+
437
+ def collect_proc_types_from_statements(statements, proc_types, visited)
438
+ statements.each do |statement|
439
+ case statement
440
+ when IR::LocalDecl
441
+ collect_proc_type(statement.type, proc_types, visited)
442
+ collect_proc_types_from_expression(statement.value, proc_types, visited)
443
+ when IR::Assignment
444
+ collect_proc_types_from_expression(statement.target, proc_types, visited)
445
+ collect_proc_types_from_expression(statement.value, proc_types, visited)
446
+ when IR::BlockStmt
447
+ collect_proc_types_from_statements(statement.body, proc_types, visited)
448
+ when IR::WhileStmt
449
+ collect_proc_types_from_expression(statement.condition, proc_types, visited)
450
+ collect_proc_types_from_statements(statement.body, proc_types, visited)
451
+ when IR::ForStmt
452
+ collect_proc_types_from_statements([statement.init], proc_types, visited)
453
+ collect_proc_types_from_expression(statement.condition, proc_types, visited)
454
+ collect_proc_types_from_statements(statement.body, proc_types, visited)
455
+ collect_proc_types_from_statements([statement.post], proc_types, visited)
456
+ when IR::IfStmt
457
+ collect_proc_types_from_expression(statement.condition, proc_types, visited)
458
+ collect_proc_types_from_statements(statement.then_body, proc_types, visited)
459
+ collect_proc_types_from_statements(statement.else_body, proc_types, visited) if statement.else_body
460
+ when IR::SwitchStmt
461
+ collect_proc_types_from_expression(statement.expression, proc_types, visited)
462
+ statement.cases.each do |switch_case|
463
+ collect_proc_types_from_statements(switch_case.body, proc_types, visited)
464
+ end
465
+ when IR::StaticAssert
466
+ collect_proc_types_from_expression(statement.condition, proc_types, visited)
467
+ collect_proc_types_from_expression(statement.message, proc_types, visited)
468
+ when IR::ReturnStmt
469
+ collect_proc_types_from_expression(statement.value, proc_types, visited) if statement.value
470
+ when IR::ExpressionStmt
471
+ collect_proc_types_from_expression(statement.expression, proc_types, visited)
472
+ end
473
+ end
474
+ end
475
+
476
+ def collect_proc_types_from_expression(expression, proc_types, visited)
477
+ case expression
478
+ when IR::Member
479
+ collect_proc_types_from_expression(expression.receiver, proc_types, visited)
480
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
481
+ collect_proc_types_from_expression(expression.receiver, proc_types, visited)
482
+ collect_proc_types_from_expression(expression.index, proc_types, visited)
483
+ when IR::Call
484
+ collect_proc_type(expression.type, proc_types, visited)
485
+ collect_proc_types_from_expression(expression.callee, proc_types, visited) unless expression.callee.is_a?(String)
486
+ expression.arguments.each { |argument| collect_proc_types_from_expression(argument, proc_types, visited) }
487
+ when IR::Unary
488
+ collect_proc_types_from_expression(expression.operand, proc_types, visited)
489
+ when IR::Binary
490
+ collect_proc_types_from_expression(expression.left, proc_types, visited)
491
+ collect_proc_types_from_expression(expression.right, proc_types, visited)
492
+ when IR::Conditional
493
+ collect_proc_types_from_expression(expression.condition, proc_types, visited)
494
+ collect_proc_types_from_expression(expression.then_expression, proc_types, visited)
495
+ collect_proc_types_from_expression(expression.else_expression, proc_types, visited)
496
+ when IR::ReinterpretExpr
497
+ collect_proc_type(expression.target_type, proc_types, visited)
498
+ collect_proc_type(expression.source_type, proc_types, visited)
499
+ collect_proc_types_from_expression(expression.expression, proc_types, visited)
500
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
501
+ collect_proc_type(expression.target_type, proc_types, visited)
502
+ when IR::AddressOf, IR::Cast
503
+ collect_proc_types_from_expression(expression.expression, proc_types, visited)
504
+ when IR::AggregateLiteral
505
+ collect_proc_type(expression.type, proc_types, visited)
506
+ expression.fields.each { |field| collect_proc_types_from_expression(field.value, proc_types, visited) }
507
+ when IR::ArrayLiteral
508
+ expression.elements.each { |element| collect_proc_types_from_expression(element, proc_types, visited) }
509
+ when IR::VariantLiteral
510
+ collect_proc_type(expression.type, proc_types, visited)
511
+ expression.fields.each { |field| collect_proc_types_from_expression(field.value, proc_types, visited) }
512
+ end
513
+ end
514
+
515
+ def collect_proc_type(type, proc_types, visited)
516
+ return unless type
517
+ return if visited[type]
518
+
519
+ visited[type] = true
520
+
521
+ case type
522
+ when Types::Nullable
523
+ collect_proc_type(type.base, proc_types, visited)
524
+ when Types::Task
525
+ collect_proc_type(type.result_type, proc_types, visited)
526
+ when Types::Proc
527
+ proc_types << type
528
+ type.params.each do |param|
529
+ collect_proc_type(param.type, proc_types, visited)
530
+ end
531
+ collect_proc_type(type.return_type, proc_types, visited)
532
+ when Types::Span
533
+ collect_proc_type(type.element_type, proc_types, visited)
534
+ when Types::StructInstance
535
+ type.arguments.each do |argument|
536
+ collect_proc_type(argument, proc_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
537
+ end
538
+ type.fields.each_value do |field_type|
539
+ collect_proc_type(field_type, proc_types, visited)
540
+ end
541
+ when Types::GenericInstance
542
+ type.arguments.each do |argument|
543
+ collect_proc_type(argument, proc_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
544
+ end
545
+ when Types::Function
546
+ type.params.each do |param|
547
+ collect_proc_type(param.type, proc_types, visited)
548
+ end
549
+ collect_proc_type(type.return_type, proc_types, visited)
550
+ when Types::Struct, Types::Union
551
+ type.fields.each_value do |field_type|
552
+ collect_proc_type(field_type, proc_types, visited)
553
+ end
554
+ when Types::Variant
555
+ type.arm_names.each do |arm_name|
556
+ type.arm(arm_name).each_value do |field_type|
557
+ collect_proc_type(field_type, proc_types, visited)
558
+ end
559
+ end
560
+ end
561
+ end
562
+
563
+ def collect_task_types_from_statements(statements, task_types, visited)
564
+ statements.each do |statement|
565
+ case statement
566
+ when IR::LocalDecl
567
+ collect_task_type(statement.type, task_types, visited)
568
+ collect_task_types_from_expression(statement.value, task_types, visited)
569
+ when IR::Assignment
570
+ collect_task_types_from_expression(statement.target, task_types, visited)
571
+ collect_task_types_from_expression(statement.value, task_types, visited)
572
+ when IR::BlockStmt
573
+ collect_task_types_from_statements(statement.body, task_types, visited)
574
+ when IR::WhileStmt
575
+ collect_task_types_from_expression(statement.condition, task_types, visited)
576
+ collect_task_types_from_statements(statement.body, task_types, visited)
577
+ when IR::ForStmt
578
+ collect_task_types_from_statements([statement.init], task_types, visited)
579
+ collect_task_types_from_expression(statement.condition, task_types, visited)
580
+ collect_task_types_from_statements(statement.body, task_types, visited)
581
+ collect_task_types_from_statements([statement.post], task_types, visited)
582
+ when IR::IfStmt
583
+ collect_task_types_from_expression(statement.condition, task_types, visited)
584
+ collect_task_types_from_statements(statement.then_body, task_types, visited)
585
+ collect_task_types_from_statements(statement.else_body, task_types, visited) if statement.else_body
586
+ when IR::SwitchStmt
587
+ collect_task_types_from_expression(statement.expression, task_types, visited)
588
+ statement.cases.each do |switch_case|
589
+ collect_task_types_from_statements(switch_case.body, task_types, visited)
590
+ end
591
+ when IR::StaticAssert
592
+ collect_task_types_from_expression(statement.condition, task_types, visited)
593
+ collect_task_types_from_expression(statement.message, task_types, visited)
594
+ when IR::ReturnStmt
595
+ collect_task_types_from_expression(statement.value, task_types, visited) if statement.value
596
+ when IR::ExpressionStmt
597
+ collect_task_types_from_expression(statement.expression, task_types, visited)
598
+ end
599
+ end
600
+ end
601
+
602
+ def collect_task_types_from_expression(expression, task_types, visited)
603
+ case expression
604
+ when IR::Member
605
+ collect_task_types_from_expression(expression.receiver, task_types, visited)
606
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
607
+ collect_task_types_from_expression(expression.receiver, task_types, visited)
608
+ collect_task_types_from_expression(expression.index, task_types, visited)
609
+ when IR::Call
610
+ collect_task_type(expression.type, task_types, visited)
611
+ collect_task_types_from_expression(expression.callee, task_types, visited) unless expression.callee.is_a?(String)
612
+ expression.arguments.each { |argument| collect_task_types_from_expression(argument, task_types, visited) }
613
+ when IR::Unary
614
+ collect_task_types_from_expression(expression.operand, task_types, visited)
615
+ when IR::Binary
616
+ collect_task_types_from_expression(expression.left, task_types, visited)
617
+ collect_task_types_from_expression(expression.right, task_types, visited)
618
+ when IR::Conditional
619
+ collect_task_types_from_expression(expression.condition, task_types, visited)
620
+ collect_task_types_from_expression(expression.then_expression, task_types, visited)
621
+ collect_task_types_from_expression(expression.else_expression, task_types, visited)
622
+ when IR::ReinterpretExpr
623
+ collect_task_type(expression.target_type, task_types, visited)
624
+ collect_task_type(expression.source_type, task_types, visited)
625
+ collect_task_types_from_expression(expression.expression, task_types, visited)
626
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
627
+ collect_task_type(expression.target_type, task_types, visited)
628
+ when IR::AddressOf, IR::Cast
629
+ collect_task_types_from_expression(expression.expression, task_types, visited)
630
+ when IR::AggregateLiteral
631
+ collect_task_type(expression.type, task_types, visited)
632
+ expression.fields.each { |field| collect_task_types_from_expression(field.value, task_types, visited) }
633
+ when IR::ArrayLiteral
634
+ expression.elements.each { |element| collect_task_types_from_expression(element, task_types, visited) }
635
+ when IR::VariantLiteral
636
+ collect_task_type(expression.type, task_types, visited)
637
+ expression.fields.each { |field| collect_task_types_from_expression(field.value, task_types, visited) }
638
+ end
639
+ end
640
+
641
+ def collect_task_type(type, task_types, visited)
642
+ return unless type
643
+ return if visited[type]
644
+
645
+ visited[type] = true
646
+
647
+ case type
648
+ when Types::Nullable
649
+ collect_task_type(type.base, task_types, visited)
650
+ when Types::Task
651
+ task_types << type
652
+ collect_task_type(type.result_type, task_types, visited)
653
+ when Types::Span
654
+ collect_task_type(type.element_type, task_types, visited)
655
+ when Types::StructInstance
656
+ type.arguments.each do |argument|
657
+ collect_task_type(argument, task_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
658
+ end
659
+ type.fields.each_value do |field_type|
660
+ collect_task_type(field_type, task_types, visited)
661
+ end
662
+ when Types::GenericInstance
663
+ type.arguments.each do |argument|
664
+ collect_task_type(argument, task_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
665
+ end
666
+ when Types::Function
667
+ type.params.each do |param|
668
+ collect_task_type(param.type, task_types, visited)
669
+ end
670
+ collect_task_type(type.return_type, task_types, visited)
671
+ when Types::Struct, Types::Union
672
+ type.fields.each_value do |field_type|
673
+ collect_task_type(field_type, task_types, visited)
674
+ end
675
+ when Types::Variant
676
+ type.arm_names.each do |arm_name|
677
+ type.arm(arm_name).each_value do |field_type|
678
+ collect_task_type(field_type, task_types, visited)
679
+ end
680
+ end
681
+ end
682
+ end
683
+
684
+ def collect_generic_variant_types
685
+ generic_variant_types = []
686
+ visited = {}
687
+
688
+ all_emitted_top_level_values.each do |value|
689
+ collect_generic_variant_type(value.type, generic_variant_types, visited)
690
+ end
691
+
692
+ @program.structs.each do |struct_decl|
693
+ struct_decl.fields.each do |field|
694
+ collect_generic_variant_type(field.type, generic_variant_types, visited)
695
+ end
696
+ end
697
+
698
+ @program.unions.each do |union_decl|
699
+ union_decl.fields.each do |field|
700
+ collect_generic_variant_type(field.type, generic_variant_types, visited)
701
+ end
702
+ end
703
+
704
+ each_variant_arm_field_type do |field_type|
705
+ collect_generic_variant_type(field_type, generic_variant_types, visited)
706
+ end
707
+
708
+ emitted_functions.each do |function|
709
+ collect_generic_variant_type(function.return_type, generic_variant_types, visited)
710
+ function.params.each do |param|
711
+ collect_generic_variant_type(param.type, generic_variant_types, visited)
712
+ end
713
+ collect_generic_variant_types_from_statements(function.body, generic_variant_types, visited)
714
+ end
715
+
716
+ @program.static_asserts.each do |statement|
717
+ collect_generic_variant_types_from_expression(statement.condition, generic_variant_types, visited)
718
+ collect_generic_variant_types_from_expression(statement.message, generic_variant_types, visited)
719
+ end
720
+
721
+ generic_variant_types
722
+ end
723
+
724
+ def collect_generic_variant_types_from_statements(statements, generic_variant_types, visited)
725
+ statements.each do |statement|
726
+ case statement
727
+ when IR::LocalDecl
728
+ collect_generic_variant_type(statement.type, generic_variant_types, visited)
729
+ collect_generic_variant_types_from_expression(statement.value, generic_variant_types, visited)
730
+ when IR::Assignment
731
+ collect_generic_variant_types_from_expression(statement.target, generic_variant_types, visited)
732
+ collect_generic_variant_types_from_expression(statement.value, generic_variant_types, visited)
733
+ when IR::BlockStmt
734
+ collect_generic_variant_types_from_statements(statement.body, generic_variant_types, visited)
735
+ when IR::WhileStmt
736
+ collect_generic_variant_types_from_expression(statement.condition, generic_variant_types, visited)
737
+ collect_generic_variant_types_from_statements(statement.body, generic_variant_types, visited)
738
+ when IR::ForStmt
739
+ collect_generic_variant_types_from_statements([statement.init], generic_variant_types, visited)
740
+ collect_generic_variant_types_from_expression(statement.condition, generic_variant_types, visited)
741
+ collect_generic_variant_types_from_statements(statement.body, generic_variant_types, visited)
742
+ collect_generic_variant_types_from_statements([statement.post], generic_variant_types, visited)
743
+ when IR::IfStmt
744
+ collect_generic_variant_types_from_expression(statement.condition, generic_variant_types, visited)
745
+ collect_generic_variant_types_from_statements(statement.then_body, generic_variant_types, visited)
746
+ collect_generic_variant_types_from_statements(statement.else_body, generic_variant_types, visited) if statement.else_body
747
+ when IR::SwitchStmt
748
+ collect_generic_variant_types_from_expression(statement.expression, generic_variant_types, visited)
749
+ statement.cases.each do |switch_case|
750
+ collect_generic_variant_types_from_statements(switch_case.body, generic_variant_types, visited)
751
+ end
752
+ when IR::StaticAssert
753
+ collect_generic_variant_types_from_expression(statement.condition, generic_variant_types, visited)
754
+ collect_generic_variant_types_from_expression(statement.message, generic_variant_types, visited)
755
+ when IR::ReturnStmt
756
+ collect_generic_variant_types_from_expression(statement.value, generic_variant_types, visited) if statement.value
757
+ when IR::ExpressionStmt
758
+ collect_generic_variant_types_from_expression(statement.expression, generic_variant_types, visited)
759
+ end
760
+ end
761
+ end
762
+
763
+ def collect_generic_variant_types_from_expression(expression, generic_variant_types, visited)
764
+ case expression
765
+ when IR::Member
766
+ collect_generic_variant_types_from_expression(expression.receiver, generic_variant_types, visited)
767
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
768
+ collect_generic_variant_types_from_expression(expression.receiver, generic_variant_types, visited)
769
+ collect_generic_variant_types_from_expression(expression.index, generic_variant_types, visited)
770
+ when IR::Call
771
+ collect_generic_variant_type(expression.type, generic_variant_types, visited)
772
+ collect_generic_variant_types_from_expression(expression.callee, generic_variant_types, visited) unless expression.callee.is_a?(String)
773
+ expression.arguments.each { |argument| collect_generic_variant_types_from_expression(argument, generic_variant_types, visited) }
774
+ when IR::Unary
775
+ collect_generic_variant_types_from_expression(expression.operand, generic_variant_types, visited)
776
+ when IR::Binary
777
+ collect_generic_variant_types_from_expression(expression.left, generic_variant_types, visited)
778
+ collect_generic_variant_types_from_expression(expression.right, generic_variant_types, visited)
779
+ when IR::Conditional
780
+ collect_generic_variant_types_from_expression(expression.condition, generic_variant_types, visited)
781
+ collect_generic_variant_types_from_expression(expression.then_expression, generic_variant_types, visited)
782
+ collect_generic_variant_types_from_expression(expression.else_expression, generic_variant_types, visited)
783
+ when IR::ReinterpretExpr
784
+ collect_generic_variant_type(expression.target_type, generic_variant_types, visited)
785
+ collect_generic_variant_type(expression.source_type, generic_variant_types, visited)
786
+ collect_generic_variant_types_from_expression(expression.expression, generic_variant_types, visited)
787
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
788
+ collect_generic_variant_type(expression.target_type, generic_variant_types, visited)
789
+ when IR::AddressOf, IR::Cast
790
+ collect_generic_variant_types_from_expression(expression.expression, generic_variant_types, visited)
791
+ when IR::AggregateLiteral
792
+ collect_generic_variant_type(expression.type, generic_variant_types, visited)
793
+ expression.fields.each { |field| collect_generic_variant_types_from_expression(field.value, generic_variant_types, visited) }
794
+ when IR::ArrayLiteral
795
+ expression.elements.each { |element| collect_generic_variant_types_from_expression(element, generic_variant_types, visited) }
796
+ when IR::VariantLiteral
797
+ collect_generic_variant_type(expression.type, generic_variant_types, visited)
798
+ expression.fields.each { |field| collect_generic_variant_types_from_expression(field.value, generic_variant_types, visited) }
799
+ end
800
+ end
801
+
802
+ def collect_generic_variant_type(type, generic_variant_types, visited)
803
+ return unless type
804
+ return if visited[type]
805
+
806
+ visited[type] = true
807
+
808
+ case type
809
+ when Types::Nullable
810
+ collect_generic_variant_type(type.base, generic_variant_types, visited)
811
+ when Types::Task
812
+ collect_generic_variant_type(type.result_type, generic_variant_types, visited)
813
+ when Types::Span
814
+ collect_generic_variant_type(type.element_type, generic_variant_types, visited)
815
+ when Types::VariantInstance
816
+ type.arguments.each do |argument|
817
+ collect_generic_variant_type(argument, generic_variant_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
818
+ end
819
+ type.arm_names.each do |arm_name|
820
+ type.arm(arm_name).each_value do |field_type|
821
+ collect_generic_variant_type(field_type, generic_variant_types, visited)
822
+ end
823
+ end
824
+ generic_variant_types << type
825
+ when Types::StructInstance
826
+ type.arguments.each do |argument|
827
+ collect_generic_variant_type(argument, generic_variant_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
828
+ end
829
+ type.fields.each_value do |field_type|
830
+ collect_generic_variant_type(field_type, generic_variant_types, visited)
831
+ end
832
+ when Types::GenericInstance
833
+ type.arguments.each do |argument|
834
+ collect_generic_variant_type(argument, generic_variant_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
835
+ end
836
+ when Types::Function, Types::Proc
837
+ type.params.each do |param|
838
+ collect_generic_variant_type(param.type, generic_variant_types, visited)
839
+ end
840
+ collect_generic_variant_type(type.return_type, generic_variant_types, visited)
841
+ when Types::Struct, Types::Union
842
+ type.fields.each_value do |field_type|
843
+ collect_generic_variant_type(field_type, generic_variant_types, visited)
844
+ end
845
+ when Types::Variant
846
+ type.arm_names.each do |arm_name|
847
+ type.arm(arm_name).each_value do |field_type|
848
+ collect_generic_variant_type(field_type, generic_variant_types, visited)
849
+ end
850
+ end
851
+ end
852
+ end
853
+
854
+ def collect_generic_struct_types
855
+ generic_struct_types = []
856
+ visited = {}
857
+
858
+ all_emitted_top_level_values.each do |value|
859
+ collect_generic_struct_type(value.type, generic_struct_types, visited)
860
+ end
861
+
862
+ @program.structs.each do |struct_decl|
863
+ struct_decl.fields.each do |field|
864
+ collect_generic_struct_type(field.type, generic_struct_types, visited)
865
+ end
866
+ end
867
+
868
+ @program.unions.each do |union_decl|
869
+ union_decl.fields.each do |field|
870
+ collect_generic_struct_type(field.type, generic_struct_types, visited)
871
+ end
872
+ end
873
+
874
+ each_variant_arm_field_type do |field_type|
875
+ collect_generic_struct_type(field_type, generic_struct_types, visited)
876
+ end
877
+
878
+ emitted_functions.each do |function|
879
+ collect_generic_struct_type(function.return_type, generic_struct_types, visited)
880
+ function.params.each do |param|
881
+ collect_generic_struct_type(param.type, generic_struct_types, visited)
882
+ end
883
+ collect_generic_struct_types_from_statements(function.body, generic_struct_types, visited)
884
+ end
885
+
886
+ @program.static_asserts.each do |statement|
887
+ collect_generic_struct_types_from_expression(statement.condition, generic_struct_types, visited)
888
+ collect_generic_struct_types_from_expression(statement.message, generic_struct_types, visited)
889
+ end
890
+
891
+ generic_struct_types
892
+ end
893
+
894
+ def collect_str_buffer_types
895
+ str_buffer_types = []
896
+ visited = {}
897
+
898
+ all_emitted_top_level_values.each do |value|
899
+ collect_str_buffer_type(value.type, str_buffer_types, visited)
900
+ end
901
+
902
+ @program.structs.each do |struct_decl|
903
+ struct_decl.fields.each do |field|
904
+ collect_str_buffer_type(field.type, str_buffer_types, visited)
905
+ end
906
+ end
907
+
908
+ @program.unions.each do |union_decl|
909
+ union_decl.fields.each do |field|
910
+ collect_str_buffer_type(field.type, str_buffer_types, visited)
911
+ end
912
+ end
913
+
914
+ each_variant_arm_field_type do |field_type|
915
+ collect_str_buffer_type(field_type, str_buffer_types, visited)
916
+ end
917
+
918
+ emitted_functions.each do |function|
919
+ collect_str_buffer_type(function.return_type, str_buffer_types, visited)
920
+ function.params.each do |param|
921
+ collect_str_buffer_type(param.type, str_buffer_types, visited)
922
+ end
923
+ collect_str_buffer_types_from_statements(function.body, str_buffer_types, visited)
924
+ end
925
+
926
+ @program.static_asserts.each do |statement|
927
+ collect_str_buffer_types_from_expression(statement.condition, str_buffer_types, visited)
928
+ collect_str_buffer_types_from_expression(statement.message, str_buffer_types, visited)
929
+ end
930
+
931
+ str_buffer_types
932
+ end
933
+
934
+ def collect_str_buffer_types_from_statements(statements, str_buffer_types, visited)
935
+ statements.each do |statement|
936
+ case statement
937
+ when IR::LocalDecl
938
+ collect_str_buffer_type(statement.type, str_buffer_types, visited)
939
+ collect_str_buffer_types_from_expression(statement.value, str_buffer_types, visited)
940
+ when IR::Assignment
941
+ collect_str_buffer_types_from_expression(statement.target, str_buffer_types, visited)
942
+ collect_str_buffer_types_from_expression(statement.value, str_buffer_types, visited)
943
+ when IR::BlockStmt
944
+ collect_str_buffer_types_from_statements(statement.body, str_buffer_types, visited)
945
+ when IR::WhileStmt
946
+ collect_str_buffer_types_from_expression(statement.condition, str_buffer_types, visited)
947
+ collect_str_buffer_types_from_statements(statement.body, str_buffer_types, visited)
948
+ when IR::ForStmt
949
+ collect_str_buffer_types_from_statements([statement.init], str_buffer_types, visited)
950
+ collect_str_buffer_types_from_expression(statement.condition, str_buffer_types, visited)
951
+ collect_str_buffer_types_from_statements(statement.body, str_buffer_types, visited)
952
+ collect_str_buffer_types_from_statements([statement.post], str_buffer_types, visited)
953
+ when IR::IfStmt
954
+ collect_str_buffer_types_from_expression(statement.condition, str_buffer_types, visited)
955
+ collect_str_buffer_types_from_statements(statement.then_body, str_buffer_types, visited)
956
+ collect_str_buffer_types_from_statements(statement.else_body, str_buffer_types, visited) if statement.else_body
957
+ when IR::SwitchStmt
958
+ collect_str_buffer_types_from_expression(statement.expression, str_buffer_types, visited)
959
+ statement.cases.each do |switch_case|
960
+ collect_str_buffer_types_from_statements(switch_case.body, str_buffer_types, visited)
961
+ end
962
+ when IR::StaticAssert
963
+ collect_str_buffer_types_from_expression(statement.condition, str_buffer_types, visited)
964
+ collect_str_buffer_types_from_expression(statement.message, str_buffer_types, visited)
965
+ when IR::ReturnStmt
966
+ collect_str_buffer_types_from_expression(statement.value, str_buffer_types, visited) if statement.value
967
+ when IR::ExpressionStmt
968
+ collect_str_buffer_types_from_expression(statement.expression, str_buffer_types, visited)
969
+ end
970
+ end
971
+ end
972
+
973
+ def collect_str_buffer_types_from_expression(expression, str_buffer_types, visited)
974
+ case expression
975
+ when IR::Member
976
+ collect_str_buffer_types_from_expression(expression.receiver, str_buffer_types, visited)
977
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
978
+ collect_str_buffer_types_from_expression(expression.receiver, str_buffer_types, visited)
979
+ collect_str_buffer_types_from_expression(expression.index, str_buffer_types, visited)
980
+ when IR::Call
981
+ collect_str_buffer_type(expression.type, str_buffer_types, visited)
982
+ collect_str_buffer_types_from_expression(expression.callee, str_buffer_types, visited) unless expression.callee.is_a?(String)
983
+ expression.arguments.each { |argument| collect_str_buffer_types_from_expression(argument, str_buffer_types, visited) }
984
+ when IR::Unary
985
+ collect_str_buffer_types_from_expression(expression.operand, str_buffer_types, visited)
986
+ when IR::Binary
987
+ collect_str_buffer_types_from_expression(expression.left, str_buffer_types, visited)
988
+ collect_str_buffer_types_from_expression(expression.right, str_buffer_types, visited)
989
+ when IR::Conditional
990
+ collect_str_buffer_types_from_expression(expression.condition, str_buffer_types, visited)
991
+ collect_str_buffer_types_from_expression(expression.then_expression, str_buffer_types, visited)
992
+ collect_str_buffer_types_from_expression(expression.else_expression, str_buffer_types, visited)
993
+ when IR::ReinterpretExpr
994
+ collect_str_buffer_type(expression.target_type, str_buffer_types, visited)
995
+ collect_str_buffer_type(expression.source_type, str_buffer_types, visited)
996
+ collect_str_buffer_types_from_expression(expression.expression, str_buffer_types, visited)
997
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
998
+ collect_str_buffer_type(expression.target_type, str_buffer_types, visited)
999
+ when IR::AddressOf, IR::Cast
1000
+ collect_str_buffer_types_from_expression(expression.expression, str_buffer_types, visited)
1001
+ when IR::AggregateLiteral
1002
+ collect_str_buffer_type(expression.type, str_buffer_types, visited)
1003
+ expression.fields.each { |field| collect_str_buffer_types_from_expression(field.value, str_buffer_types, visited) }
1004
+ when IR::ArrayLiteral
1005
+ expression.elements.each { |element| collect_str_buffer_types_from_expression(element, str_buffer_types, visited) }
1006
+ when IR::VariantLiteral
1007
+ collect_str_buffer_type(expression.type, str_buffer_types, visited)
1008
+ expression.fields.each { |field| collect_str_buffer_types_from_expression(field.value, str_buffer_types, visited) }
1009
+ end
1010
+ end
1011
+
1012
+ def collect_str_buffer_type(type, str_buffer_types, visited)
1013
+ return unless type
1014
+ return if visited[type]
1015
+
1016
+ visited[type] = true
1017
+
1018
+ case type
1019
+ when Types::Nullable
1020
+ collect_str_buffer_type(type.base, str_buffer_types, visited)
1021
+ when Types::Span
1022
+ collect_str_buffer_type(type.element_type, str_buffer_types, visited)
1023
+ when Types::StructInstance
1024
+ type.arguments.each do |argument|
1025
+ collect_str_buffer_type(argument, str_buffer_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
1026
+ end
1027
+ type.fields.each_value do |field_type|
1028
+ collect_str_buffer_type(field_type, str_buffer_types, visited)
1029
+ end
1030
+ when Types::GenericInstance
1031
+ str_buffer_types << type if str_buffer_type?(type)
1032
+ type.arguments.each do |argument|
1033
+ collect_str_buffer_type(argument, str_buffer_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
1034
+ end
1035
+ when Types::Function
1036
+ type.params.each do |param|
1037
+ collect_str_buffer_type(param.type, str_buffer_types, visited)
1038
+ end
1039
+ collect_str_buffer_type(type.return_type, str_buffer_types, visited)
1040
+ when Types::Struct, Types::Union
1041
+ type.fields.each_value do |field_type|
1042
+ collect_str_buffer_type(field_type, str_buffer_types, visited)
1043
+ end
1044
+ when Types::Variant
1045
+ type.arm_names.each do |arm_name|
1046
+ type.arm(arm_name).each_value do |field_type|
1047
+ collect_str_buffer_type(field_type, str_buffer_types, visited)
1048
+ end
1049
+ end
1050
+ end
1051
+ end
1052
+
1053
+ def collect_generic_struct_types_from_statements(statements, generic_struct_types, visited)
1054
+ statements.each do |statement|
1055
+ case statement
1056
+ when IR::LocalDecl
1057
+ collect_generic_struct_type(statement.type, generic_struct_types, visited)
1058
+ collect_generic_struct_types_from_expression(statement.value, generic_struct_types, visited)
1059
+ when IR::Assignment
1060
+ collect_generic_struct_types_from_expression(statement.target, generic_struct_types, visited)
1061
+ collect_generic_struct_types_from_expression(statement.value, generic_struct_types, visited)
1062
+ when IR::BlockStmt
1063
+ collect_generic_struct_types_from_statements(statement.body, generic_struct_types, visited)
1064
+ when IR::WhileStmt
1065
+ collect_generic_struct_types_from_expression(statement.condition, generic_struct_types, visited)
1066
+ collect_generic_struct_types_from_statements(statement.body, generic_struct_types, visited)
1067
+ when IR::ForStmt
1068
+ collect_generic_struct_types_from_statements([statement.init], generic_struct_types, visited)
1069
+ collect_generic_struct_types_from_expression(statement.condition, generic_struct_types, visited)
1070
+ collect_generic_struct_types_from_statements(statement.body, generic_struct_types, visited)
1071
+ collect_generic_struct_types_from_statements([statement.post], generic_struct_types, visited)
1072
+ when IR::IfStmt
1073
+ collect_generic_struct_types_from_expression(statement.condition, generic_struct_types, visited)
1074
+ collect_generic_struct_types_from_statements(statement.then_body, generic_struct_types, visited)
1075
+ collect_generic_struct_types_from_statements(statement.else_body, generic_struct_types, visited) if statement.else_body
1076
+ when IR::SwitchStmt
1077
+ collect_generic_struct_types_from_expression(statement.expression, generic_struct_types, visited)
1078
+ statement.cases.each do |switch_case|
1079
+ collect_generic_struct_types_from_statements(switch_case.body, generic_struct_types, visited)
1080
+ end
1081
+ when IR::StaticAssert
1082
+ collect_generic_struct_types_from_expression(statement.condition, generic_struct_types, visited)
1083
+ collect_generic_struct_types_from_expression(statement.message, generic_struct_types, visited)
1084
+ when IR::ReturnStmt
1085
+ collect_generic_struct_types_from_expression(statement.value, generic_struct_types, visited) if statement.value
1086
+ when IR::ExpressionStmt
1087
+ collect_generic_struct_types_from_expression(statement.expression, generic_struct_types, visited)
1088
+ end
1089
+ end
1090
+ end
1091
+
1092
+ def collect_generic_struct_types_from_expression(expression, generic_struct_types, visited)
1093
+ case expression
1094
+ when IR::Member
1095
+ collect_generic_struct_types_from_expression(expression.receiver, generic_struct_types, visited)
1096
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
1097
+ collect_generic_struct_types_from_expression(expression.receiver, generic_struct_types, visited)
1098
+ collect_generic_struct_types_from_expression(expression.index, generic_struct_types, visited)
1099
+ when IR::Call
1100
+ collect_generic_struct_type(expression.type, generic_struct_types, visited)
1101
+ collect_generic_struct_types_from_expression(expression.callee, generic_struct_types, visited) unless expression.callee.is_a?(String)
1102
+ expression.arguments.each { |argument| collect_generic_struct_types_from_expression(argument, generic_struct_types, visited) }
1103
+ when IR::Unary
1104
+ collect_generic_struct_types_from_expression(expression.operand, generic_struct_types, visited)
1105
+ when IR::Binary
1106
+ collect_generic_struct_types_from_expression(expression.left, generic_struct_types, visited)
1107
+ collect_generic_struct_types_from_expression(expression.right, generic_struct_types, visited)
1108
+ when IR::Conditional
1109
+ collect_generic_struct_types_from_expression(expression.condition, generic_struct_types, visited)
1110
+ collect_generic_struct_types_from_expression(expression.then_expression, generic_struct_types, visited)
1111
+ collect_generic_struct_types_from_expression(expression.else_expression, generic_struct_types, visited)
1112
+ when IR::ReinterpretExpr
1113
+ collect_generic_struct_type(expression.target_type, generic_struct_types, visited)
1114
+ collect_generic_struct_type(expression.source_type, generic_struct_types, visited)
1115
+ collect_generic_struct_types_from_expression(expression.expression, generic_struct_types, visited)
1116
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
1117
+ collect_generic_struct_type(expression.target_type, generic_struct_types, visited)
1118
+ when IR::AddressOf
1119
+ collect_generic_struct_types_from_expression(expression.expression, generic_struct_types, visited)
1120
+ when IR::Cast
1121
+ collect_generic_struct_types_from_expression(expression.expression, generic_struct_types, visited)
1122
+ when IR::AggregateLiteral
1123
+ collect_generic_struct_type(expression.type, generic_struct_types, visited)
1124
+ expression.fields.each { |field| collect_generic_struct_types_from_expression(field.value, generic_struct_types, visited) }
1125
+ when IR::ArrayLiteral
1126
+ expression.elements.each { |element| collect_generic_struct_types_from_expression(element, generic_struct_types, visited) }
1127
+ when IR::VariantLiteral
1128
+ collect_generic_struct_type(expression.type, generic_struct_types, visited)
1129
+ expression.fields.each { |field| collect_generic_struct_types_from_expression(field.value, generic_struct_types, visited) }
1130
+ end
1131
+ end
1132
+
1133
+ def collect_generic_struct_type(type, generic_struct_types, visited)
1134
+ return unless type
1135
+ return if visited[type]
1136
+
1137
+ visited[type] = true
1138
+
1139
+ case type
1140
+ when Types::Nullable
1141
+ collect_generic_struct_type(type.base, generic_struct_types, visited)
1142
+ when Types::Span
1143
+ collect_generic_struct_type(type.element_type, generic_struct_types, visited)
1144
+ when Types::StructInstance
1145
+ generic_struct_types << type
1146
+ type.arguments.each do |argument|
1147
+ collect_generic_struct_type(argument, generic_struct_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
1148
+ end
1149
+ type.fields.each_value do |field_type|
1150
+ collect_generic_struct_type(field_type, generic_struct_types, visited)
1151
+ end
1152
+ when Types::GenericInstance
1153
+ type.arguments.each do |argument|
1154
+ collect_generic_struct_type(argument, generic_struct_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
1155
+ end
1156
+ when Types::Function
1157
+ type.params.each do |param|
1158
+ collect_generic_struct_type(param.type, generic_struct_types, visited)
1159
+ end
1160
+ collect_generic_struct_type(type.return_type, generic_struct_types, visited)
1161
+ when Types::Struct, Types::Union
1162
+ type.fields.each_value do |field_type|
1163
+ collect_generic_struct_type(field_type, generic_struct_types, visited)
1164
+ end
1165
+ when Types::Variant
1166
+ type.arm_names.each do |arm_name|
1167
+ type.arm(arm_name).each_value do |field_type|
1168
+ collect_generic_struct_type(field_type, generic_struct_types, visited)
1169
+ end
1170
+ end
1171
+ end
1172
+ end
1173
+
1174
+ def collect_span_types_from_statements(statements, span_types, visited)
1175
+ statements.each do |statement|
1176
+ case statement
1177
+ when IR::LocalDecl
1178
+ collect_span_type(statement.type, span_types, visited)
1179
+ collect_span_types_from_expression(statement.value, span_types, visited)
1180
+ when IR::Assignment
1181
+ collect_span_types_from_expression(statement.target, span_types, visited)
1182
+ collect_span_types_from_expression(statement.value, span_types, visited)
1183
+ when IR::BlockStmt
1184
+ collect_span_types_from_statements(statement.body, span_types, visited)
1185
+ when IR::WhileStmt
1186
+ collect_span_types_from_expression(statement.condition, span_types, visited)
1187
+ collect_span_types_from_statements(statement.body, span_types, visited)
1188
+ when IR::ForStmt
1189
+ collect_span_types_from_statements([statement.init], span_types, visited)
1190
+ collect_span_types_from_expression(statement.condition, span_types, visited)
1191
+ collect_span_types_from_statements(statement.body, span_types, visited)
1192
+ collect_span_types_from_statements([statement.post], span_types, visited)
1193
+ when IR::IfStmt
1194
+ collect_span_types_from_expression(statement.condition, span_types, visited)
1195
+ collect_span_types_from_statements(statement.then_body, span_types, visited)
1196
+ collect_span_types_from_statements(statement.else_body, span_types, visited) if statement.else_body
1197
+ when IR::SwitchStmt
1198
+ collect_span_types_from_expression(statement.expression, span_types, visited)
1199
+ statement.cases.each do |switch_case|
1200
+ collect_span_types_from_statements(switch_case.body, span_types, visited)
1201
+ end
1202
+ when IR::StaticAssert
1203
+ collect_span_types_from_expression(statement.condition, span_types, visited)
1204
+ collect_span_types_from_expression(statement.message, span_types, visited)
1205
+ when IR::ReturnStmt
1206
+ collect_span_types_from_expression(statement.value, span_types, visited) if statement.value
1207
+ when IR::ExpressionStmt
1208
+ collect_span_types_from_expression(statement.expression, span_types, visited)
1209
+ end
1210
+ end
1211
+ end
1212
+
1213
+ def collect_span_types_from_expression(expression, span_types, visited)
1214
+ case expression
1215
+ when IR::Member
1216
+ collect_span_types_from_expression(expression.receiver, span_types, visited)
1217
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
1218
+ collect_span_types_from_expression(expression.receiver, span_types, visited)
1219
+ collect_span_types_from_expression(expression.index, span_types, visited)
1220
+ when IR::Call
1221
+ collect_span_type(expression.type, span_types, visited)
1222
+ collect_span_types_from_expression(expression.callee, span_types, visited) unless expression.callee.is_a?(String)
1223
+ expression.arguments.each { |argument| collect_span_types_from_expression(argument, span_types, visited) }
1224
+ when IR::Unary
1225
+ collect_span_types_from_expression(expression.operand, span_types, visited)
1226
+ when IR::Binary
1227
+ collect_span_types_from_expression(expression.left, span_types, visited)
1228
+ collect_span_types_from_expression(expression.right, span_types, visited)
1229
+ when IR::Conditional
1230
+ collect_span_types_from_expression(expression.condition, span_types, visited)
1231
+ collect_span_types_from_expression(expression.then_expression, span_types, visited)
1232
+ collect_span_types_from_expression(expression.else_expression, span_types, visited)
1233
+ when IR::ReinterpretExpr
1234
+ collect_span_type(expression.target_type, span_types, visited)
1235
+ collect_span_type(expression.source_type, span_types, visited)
1236
+ collect_span_types_from_expression(expression.expression, span_types, visited)
1237
+ when IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
1238
+ collect_span_type(expression.target_type, span_types, visited)
1239
+ when IR::AddressOf
1240
+ collect_span_types_from_expression(expression.expression, span_types, visited)
1241
+ when IR::Cast
1242
+ collect_span_types_from_expression(expression.expression, span_types, visited)
1243
+ when IR::AggregateLiteral
1244
+ collect_span_type(expression.type, span_types, visited)
1245
+ expression.fields.each { |field| collect_span_types_from_expression(field.value, span_types, visited) }
1246
+ when IR::ArrayLiteral
1247
+ expression.elements.each { |element| collect_span_types_from_expression(element, span_types, visited) }
1248
+ when IR::VariantLiteral
1249
+ collect_span_type(expression.type, span_types, visited)
1250
+ expression.fields.each { |field| collect_span_types_from_expression(field.value, span_types, visited) }
1251
+ end
1252
+ end
1253
+
1254
+ def collect_span_type(type, span_types, visited)
1255
+ return unless type
1256
+ return if visited[type]
1257
+
1258
+ visited[type] = true
1259
+
1260
+ case type
1261
+ when Types::Nullable
1262
+ collect_span_type(type.base, span_types, visited)
1263
+ when Types::Span
1264
+ span_types << type
1265
+ collect_span_type(type.element_type, span_types, visited)
1266
+ when Types::GenericInstance
1267
+ type.arguments.each do |argument|
1268
+ collect_span_type(argument, span_types, visited) unless argument.is_a?(Types::LiteralTypeArg)
1269
+ end
1270
+ when Types::Function
1271
+ type.params.each do |param|
1272
+ collect_span_type(param.type, span_types, visited)
1273
+ end
1274
+ collect_span_type(type.return_type, span_types, visited)
1275
+ when Types::Struct, Types::Union
1276
+ type.fields.each_value do |field_type|
1277
+ collect_span_type(field_type, span_types, visited)
1278
+ end
1279
+ when Types::Variant
1280
+ type.arm_names.each do |arm_name|
1281
+ type.arm(arm_name).each_value do |field_type|
1282
+ collect_span_type(field_type, span_types, visited)
1283
+ end
1284
+ end
1285
+ end
1286
+ end
1287
+
1288
+ def collect_dyn_decls
1289
+ void_ptr = Types::Registry.generic_instance("ptr", [Types::Registry.primitive("void")])
1290
+ collect_dyn_types.map do |type|
1291
+ IR::StructDecl.new(
1292
+ name: type.to_s,
1293
+ linkage_name: dyn_type_name(type),
1294
+ fields: [
1295
+ IR::Field.new(name: "data", type: void_ptr),
1296
+ IR::Field.new(name: "vtable", type: void_ptr),
1297
+ ],
1298
+ packed: false,
1299
+ alignment: nil,
1300
+ )
1301
+ end
1302
+ end
1303
+
1304
+ def collect_dyn_types
1305
+ dyn_types = []
1306
+ seen = []
1307
+
1308
+ collect_type = lambda do |type|
1309
+ return unless type
1310
+ case type
1311
+ when Types::Dyn
1312
+ name = type.interface_binding.name
1313
+ unless seen.include?(name)
1314
+ seen << name
1315
+ dyn_types << type
1316
+ end
1317
+ when Types::Nullable
1318
+ collect_type.call(type.base)
1319
+ when Types::GenericInstance
1320
+ type.arguments.each { |arg| collect_type.call(arg) unless arg.is_a?(Types::LiteralTypeArg) }
1321
+ when Types::Span
1322
+ collect_type.call(type.element_type)
1323
+ when Types::Task
1324
+ collect_type.call(type.result_type)
1325
+ when Types::Function
1326
+ type.params.each { |p| collect_type.call(p.type) }
1327
+ collect_type.call(type.return_type)
1328
+ when Types::Proc
1329
+ type.params.each { |p| collect_type.call(p.type) }
1330
+ collect_type.call(type.return_type)
1331
+ when Types::StructInstance
1332
+ type.arguments.each { |arg| collect_type.call(arg) }
1333
+ when Types::VariantInstance
1334
+ type.arguments.each { |arg| collect_type.call(arg) }
1335
+ end
1336
+ end
1337
+
1338
+ collect_in_stmt = lambda do |stmt|
1339
+ case stmt
1340
+ when IR::LocalDecl
1341
+ collect_type.call(stmt.type)
1342
+ when IR::BlockStmt
1343
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1344
+ when IR::IfStmt
1345
+ stmt.then_body.each { |s| collect_in_stmt.call(s) }
1346
+ stmt.else_body&.each { |s| collect_in_stmt.call(s) }
1347
+ when IR::WhileStmt
1348
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1349
+ when IR::ForStmt
1350
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1351
+ when IR::SwitchStmt
1352
+ stmt.cases.each { |c| c.body.each { |s| collect_in_stmt.call(s) } }
1353
+ end
1354
+ end
1355
+
1356
+ if @program
1357
+ @program.constants.each { |c| collect_type.call(c.type) }
1358
+ @program.globals.each { |g| collect_type.call(g.type) }
1359
+ @program.structs.each { |s| s.fields.each { |f| collect_type.call(f.type) } }
1360
+ @program.unions.each { |u| u.fields.each { |f| collect_type.call(f.type) } }
1361
+ @program.functions.each do |f|
1362
+ collect_type.call(f.return_type)
1363
+ f.params.each { |p| collect_type.call(p.type) }
1364
+ body = f.body
1365
+ if body.is_a?(IR::BlockStmt)
1366
+ body.body.each { |s| collect_in_stmt.call(s) }
1367
+ elsif body.is_a?(Array)
1368
+ body.each { |s| collect_in_stmt.call(s) }
1369
+ end
1370
+ end
1371
+ end
1372
+
1373
+ dyn_types
1374
+ end
1375
+
1376
+ def collect_nullable_opt_decls
1377
+ collect_nullable_opt_types.map do |type|
1378
+ IR::StructDecl.new(
1379
+ name: type.to_s,
1380
+ linkage_name: nullable_opt_type_name(type),
1381
+ fields: [
1382
+ IR::Field.new(name: "has_value", type: Types::Registry.primitive("bool")),
1383
+ IR::Field.new(name: "value", type: type.base),
1384
+ ],
1385
+ packed: false,
1386
+ alignment: nil,
1387
+ )
1388
+ end
1389
+ end
1390
+
1391
+ def collect_nullable_opt_types
1392
+ opt_types = []
1393
+ seen = {}
1394
+
1395
+ collect_type = lambda do |type|
1396
+ return unless type
1397
+
1398
+ case type
1399
+ when Types::Nullable
1400
+ unless c_backend_pointer_like_type?(type.base)
1401
+ name = nullable_opt_type_name(type)
1402
+ unless seen[name]
1403
+ seen[name] = true
1404
+ opt_types << type
1405
+ end
1406
+ end
1407
+ collect_type.call(type.base)
1408
+ when Types::GenericInstance
1409
+ type.arguments.each { |arg| collect_type.call(arg) unless arg.is_a?(Types::LiteralTypeArg) }
1410
+ when Types::Span
1411
+ collect_type.call(type.element_type)
1412
+ when Types::Task
1413
+ collect_type.call(type.result_type)
1414
+ when Types::Function, Types::Proc
1415
+ type.params.each { |p| collect_type.call(p.type) }
1416
+ collect_type.call(type.return_type)
1417
+ when Types::StructInstance, Types::VariantInstance
1418
+ type.arguments.each { |arg| collect_type.call(arg) }
1419
+ end
1420
+ end
1421
+
1422
+ collect_in_stmt = lambda do |stmt|
1423
+ case stmt
1424
+ when IR::LocalDecl
1425
+ collect_type.call(stmt.type)
1426
+ when IR::BlockStmt
1427
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1428
+ when IR::IfStmt
1429
+ stmt.then_body.each { |s| collect_in_stmt.call(s) }
1430
+ stmt.else_body&.each { |s| collect_in_stmt.call(s) }
1431
+ when IR::WhileStmt
1432
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1433
+ when IR::ForStmt
1434
+ stmt.body.each { |s| collect_in_stmt.call(s) }
1435
+ when IR::SwitchStmt
1436
+ stmt.cases.each { |c| c.body.each { |s| collect_in_stmt.call(s) } }
1437
+ end
1438
+ end
1439
+
1440
+ emitted_aggregate_structs.each { |decl| decl.fields.each { |f| collect_type.call(f.type) } }
1441
+ emitted_aggregate_unions.each { |decl| decl.fields.each { |f| collect_type.call(f.type) } }
1442
+ emitted_aggregate_variants.each do |decl|
1443
+ decl.arms.each { |arm| arm.fields.each { |f| collect_type.call(f.type) } }
1444
+ end
1445
+ emitted_constants.each { |c| collect_type.call(c.type) }
1446
+ emitted_globals.each { |g| collect_type.call(g.type) }
1447
+ emitted_functions.each do |f|
1448
+ collect_type.call(f.return_type)
1449
+ f.params.each { |p| collect_type.call(p.type) }
1450
+ f.body.each { |s| collect_in_stmt.call(s) }
1451
+ end
1452
+
1453
+ opt_types
1454
+ end
1455
+
1456
+ def collect_str_literals
1457
+ literals = {}
1458
+ emitted_functions.each do |func|
1459
+ collect_str_literals_from_statements(func.body, literals)
1460
+ end
1461
+ emitted_globals.each do |global|
1462
+ collect_str_literals_from_expression(global.value, literals)
1463
+ end
1464
+ emitted_constants.each do |constant|
1465
+ collect_str_literals_from_expression(constant.value, literals)
1466
+ end
1467
+ literals.keys.sort_by { |k| [k.bytesize, k] }
1468
+ end
1469
+
1470
+ def collect_str_literals_from_statements(statements, literals)
1471
+ statements.each do |stmt|
1472
+ case stmt
1473
+ when IR::LocalDecl
1474
+ collect_str_literals_from_expression(stmt.value, literals) if stmt.value
1475
+ when IR::Assignment
1476
+ collect_str_literals_from_expression(stmt.target, literals)
1477
+ collect_str_literals_from_expression(stmt.value, literals)
1478
+ when IR::BlockStmt
1479
+ collect_str_literals_from_statements(stmt.body, literals)
1480
+ when IR::WhileStmt
1481
+ collect_str_literals_from_expression(stmt.condition, literals)
1482
+ collect_str_literals_from_statements(stmt.body, literals)
1483
+ when IR::ForStmt
1484
+ collect_str_literals_from_statements([stmt.init], literals)
1485
+ collect_str_literals_from_expression(stmt.condition, literals)
1486
+ collect_str_literals_from_statements(stmt.body, literals)
1487
+ collect_str_literals_from_statements([stmt.post], literals)
1488
+ when IR::IfStmt
1489
+ collect_str_literals_from_expression(stmt.condition, literals)
1490
+ collect_str_literals_from_statements(stmt.then_body, literals)
1491
+ collect_str_literals_from_statements(stmt.else_body, literals) if stmt.else_body
1492
+ when IR::SwitchStmt
1493
+ collect_str_literals_from_expression(stmt.expression, literals)
1494
+ stmt.cases.each { |c| collect_str_literals_from_statements(c.body, literals) }
1495
+ when IR::ReturnStmt
1496
+ collect_str_literals_from_expression(stmt.value, literals) if stmt.value
1497
+ when IR::ExpressionStmt
1498
+ collect_str_literals_from_expression(stmt.expression, literals)
1499
+ when IR::StaticAssert
1500
+ collect_str_literals_from_expression(stmt.condition, literals)
1501
+ collect_str_literals_from_expression(stmt.message, literals)
1502
+ end
1503
+ end
1504
+ end
1505
+
1506
+ def collect_str_literals_from_expression(expr, literals)
1507
+ return unless expr
1508
+
1509
+ case expr
1510
+ when IR::StringLiteral
1511
+ literals[expr.value] = true if expr.type.is_a?(Types::StringView)
1512
+ when IR::Member
1513
+ collect_str_literals_from_expression(expr.receiver, literals)
1514
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
1515
+ collect_str_literals_from_expression(expr.receiver, literals)
1516
+ collect_str_literals_from_expression(expr.index, literals)
1517
+ when IR::Call
1518
+ collect_str_literals_from_expression(expr.callee, literals) unless expr.callee.is_a?(String)
1519
+ expr.arguments.each { |arg| collect_str_literals_from_expression(arg, literals) }
1520
+ when IR::Unary
1521
+ collect_str_literals_from_expression(expr.operand, literals)
1522
+ when IR::Binary
1523
+ collect_str_literals_from_expression(expr.left, literals)
1524
+ collect_str_literals_from_expression(expr.right, literals)
1525
+ when IR::Conditional
1526
+ collect_str_literals_from_expression(expr.condition, literals)
1527
+ collect_str_literals_from_expression(expr.then_expression, literals)
1528
+ collect_str_literals_from_expression(expr.else_expression, literals)
1529
+ when IR::ReinterpretExpr
1530
+ collect_str_literals_from_expression(expr.expression, literals)
1531
+ when IR::AddressOf
1532
+ collect_str_literals_from_expression(expr.expression, literals)
1533
+ when IR::Cast
1534
+ collect_str_literals_from_expression(expr.expression, literals)
1535
+ when IR::AggregateLiteral
1536
+ expr.fields.each { |f| collect_str_literals_from_expression(f.value, literals) }
1537
+ when IR::ArrayLiteral
1538
+ expr.elements.each { |e| collect_str_literals_from_expression(e, literals) }
1539
+ when IR::VariantLiteral
1540
+ expr.fields.each { |f| collect_str_literals_from_expression(f.value, literals) }
1541
+ end
1542
+ end
1543
+ end
1544
+ end
1545
+ end