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,483 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CBackend
5
+ module FeatureDetection
6
+ private
7
+
8
+ def uses_fmt_builder?
9
+ return @uses_fmt_builder if defined?(@uses_fmt_builder)
10
+
11
+ @uses_fmt_builder = emitted_functions.any? do |function|
12
+ function_uses_named_call?(function, %w[mt_fmt_begin])
13
+ end
14
+ end
15
+
16
+ def uses_string_view?
17
+ return @uses_string_view if defined?(@uses_string_view)
18
+ @uses_string_view = begin
19
+ uses_fatal_helper? || uses_format_helpers? || uses_str_buffer_helpers? ||
20
+ uses_entrypoint_argv_helpers? || uses_str_equality_helper? ||
21
+ uses_foreign_temp_cstr_helpers? ||
22
+ emitted_functions.any? do |function|
23
+ type_contains_string_view?(function.return_type) ||
24
+ function.params.any? { |param| type_contains_string_view?(param.type) }
25
+ end ||
26
+ emitted_aggregate_structs.any? { |s| s.fields.any? { |f| type_contains_string_view?(f.type) } } ||
27
+ emitted_aggregate_unions.any? { |u| u.fields.any? { |f| type_contains_string_view?(f.type) } } ||
28
+ emitted_aggregate_variants.any? { |v| v.arms.any? { |a| a.fields.any? { |f| type_contains_string_view?(f.type) } } } ||
29
+ emitted_constants.any? { |c| type_contains_string_view?(c.type) } ||
30
+ emitted_globals.any? { |g| type_contains_string_view?(g.type) } ||
31
+ !collect_str_literals.empty?
32
+ end
33
+ end
34
+
35
+ def type_contains_string_view?(type)
36
+ return false unless type
37
+ return true if type.is_a?(Types::StringView)
38
+ case type
39
+ when Types::Nullable
40
+ type_contains_string_view?(type.base)
41
+ when Types::Span
42
+ type_contains_string_view?(type.element_type)
43
+ when Types::GenericInstance
44
+ type.arguments.any? { |a| type_contains_string_view?(a) }
45
+ else
46
+ false
47
+ end
48
+ end
49
+
50
+ def uses_vector_math_types?
51
+ return @uses_vector_math_types if defined?(@uses_vector_math_types)
52
+ @uses_vector_math_types = begin
53
+ emitted_functions.any? do |function|
54
+ type_contains_vector_math?(function.return_type) ||
55
+ function.params.any? { |param| type_contains_vector_math?(param.type) } ||
56
+ function.body.any? { |stmt| statement_uses_vector_math?(stmt) }
57
+ end ||
58
+ emitted_aggregate_structs.any? { |s| s.fields.any? { |f| type_contains_vector_math?(f.type) } } ||
59
+ emitted_aggregate_unions.any? { |u| u.fields.any? { |f| type_contains_vector_math?(f.type) } } ||
60
+ emitted_aggregate_variants.any? { |v| v.arms.any? { |a| a.fields.any? { |f| type_contains_vector_math?(f.type) } } } ||
61
+ emitted_constants.any? { |c| type_contains_vector_math?(c.type) } ||
62
+ emitted_globals.any? { |g| type_contains_vector_math?(g.type) }
63
+ end
64
+ @uses_vector_math_types
65
+ end
66
+
67
+ def statement_uses_vector_math?(stmt)
68
+ case stmt
69
+ when IR::LocalDecl
70
+ type_contains_vector_math?(stmt.type)
71
+ when IR::Assignment
72
+ type_contains_vector_math?(stmt.target.type) || expression_uses_vector_math?(stmt.value)
73
+ when IR::ExpressionStmt
74
+ expression_uses_vector_math?(stmt.expression)
75
+ when IR::ReturnStmt
76
+ stmt.value && expression_uses_vector_math?(stmt.value)
77
+ when IR::BlockStmt
78
+ stmt.body.any? { |s| statement_uses_vector_math?(s) }
79
+ when IR::WhileStmt
80
+ stmt.body.any? { |s| statement_uses_vector_math?(s) }
81
+ when IR::ForStmt
82
+ stmt.body.any? { |s| statement_uses_vector_math?(s) }
83
+ when IR::IfStmt
84
+ stmt.then_body.any? { |s| statement_uses_vector_math?(s) } ||
85
+ (stmt.else_body && stmt.else_body.any? { |s| statement_uses_vector_math?(s) })
86
+ when IR::SwitchStmt
87
+ stmt.cases.any? { |c| c.body.any? { |s| statement_uses_vector_math?(s) } }
88
+ else
89
+ false
90
+ end
91
+ end
92
+
93
+ def expression_uses_vector_math?(expr)
94
+ return false unless expr
95
+ return true if expr.respond_to?(:type) && type_contains_vector_math?(expr.type)
96
+ case expr
97
+ when IR::Assignment
98
+ expression_uses_vector_math?(expr.target) || expression_uses_vector_math?(expr.value)
99
+ when IR::AggregateLiteral
100
+ expr.fields.any? { |f| expression_uses_vector_math?(f.value) }
101
+ when IR::Binary
102
+ expression_uses_vector_math?(expr.left) || expression_uses_vector_math?(expr.right)
103
+ when IR::Unary
104
+ expression_uses_vector_math?(expr.operand)
105
+ when IR::Call
106
+ expr.arguments.any? { |a| expression_uses_vector_math?(a) }
107
+ when IR::Member
108
+ expression_uses_vector_math?(expr.receiver)
109
+ when IR::Index
110
+ expression_uses_vector_math?(expr.receiver)
111
+ when IR::Conditional
112
+ expression_uses_vector_math?(expr.then_expression) || expression_uses_vector_math?(expr.else_expression)
113
+ else
114
+ false
115
+ end
116
+ end
117
+
118
+ def type_contains_vector_math?(type)
119
+ return false unless type
120
+ return true if type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
121
+ case type
122
+ when Types::Nullable
123
+ type_contains_vector_math?(type.base)
124
+ when Types::Span
125
+ type_contains_vector_math?(type.element_type)
126
+ when Types::GenericInstance
127
+ type.arguments.any? { |a| type_contains_vector_math?(a) }
128
+ else
129
+ false
130
+ end
131
+ end
132
+
133
+ def uses_fatal_helper?
134
+ uses_mt_fatal_helper? || uses_mt_fatal_str_helper?
135
+ end
136
+
137
+ def uses_mt_fatal_helper?
138
+ return true if @debug_guards
139
+
140
+ collect_checked_array_index_types.any? || collect_checked_span_index_types.any? ||
141
+ uses_format_helpers? ||
142
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_fatal mt_str_buffer_len mt_str_buffer_as_cstr mt_str_buffer_assign mt_str_buffer_append mt_foreign_str_to_cstr_temp mt_foreign_strs_to_cstrs_temp]) }
143
+ end
144
+
145
+ def uses_mt_fatal_str_helper?
146
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_fatal_str]) }
147
+ end
148
+
149
+ def uses_foreign_temp_cstr_helpers?
150
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_foreign_str_to_cstr_temp mt_free_foreign_cstr_temp mt_foreign_strs_to_cstrs_temp mt_free_foreign_cstrs_temp]) }
151
+ end
152
+
153
+ def uses_entrypoint_argv_helpers?
154
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_entry_argv_to_span_str mt_free_entry_argv_strs]) }
155
+ end
156
+
157
+ def uses_text_buffer_helpers?
158
+ uses_str_buffer_helpers?
159
+ end
160
+
161
+ def uses_str_buffer_helpers?
162
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_str_buffer_len mt_str_buffer_as_cstr mt_str_buffer_clear mt_str_buffer_assign mt_str_buffer_append mt_str_buffer_prepare_write]) }
163
+ end
164
+
165
+ def uses_async_memory_helpers?
166
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_async_alloc mt_async_free]) }
167
+ end
168
+
169
+ def uses_parallel_for_helper?
170
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_parallel_for]) }
171
+ end
172
+
173
+ def uses_spawn_all_helper?
174
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_spawn_all]) }
175
+ end
176
+
177
+ def uses_detach_helper?
178
+ emitted_functions.any? { |function| function_uses_named_call?(function, %w[mt_detach_run mt_detach_join]) }
179
+ end
180
+
181
+ def format_helper_callees
182
+ %w[
183
+ mt_format_str_make
184
+ mt_format_str_release
185
+ mt_format_cstr_len
186
+ mt_format_bool_len
187
+ mt_format_ptr_uint_len
188
+ mt_format_ulong_len
189
+ mt_format_uint_len
190
+ mt_format_long_len
191
+ mt_format_int_len
192
+ mt_format_ulong_hex_len
193
+ mt_format_long_hex_len
194
+ mt_format_float_len
195
+ mt_format_double_len
196
+ mt_format_double_precision_len
197
+ mt_format_ulong_oct_len
198
+ mt_format_long_oct_len
199
+ mt_format_ulong_bin_len
200
+ mt_format_long_bin_len
201
+ mt_format_append_str
202
+ mt_format_append_cstr
203
+ mt_format_append_bool
204
+ mt_format_append_ptr_uint
205
+ mt_format_append_ulong
206
+ mt_format_append_uint
207
+ mt_format_append_long
208
+ mt_format_append_int
209
+ mt_format_append_ulong_hex
210
+ mt_format_append_ulong_hex_upper
211
+ mt_format_append_long_hex
212
+ mt_format_append_long_hex_upper
213
+ mt_format_append_float
214
+ mt_format_append_double
215
+ mt_format_append_double_precision
216
+ mt_format_append_ulong_oct
217
+ mt_format_append_long_oct
218
+ mt_format_append_ulong_bin
219
+ mt_format_append_long_bin
220
+ ]
221
+ end
222
+
223
+ def used_format_helpers
224
+ @used_format_helpers ||= begin
225
+ helpers = {}
226
+
227
+ emitted_functions.each do |function|
228
+ format_helper_callees.each do |callee|
229
+ helpers[callee] = true if function_uses_named_call?(function, [callee])
230
+ end
231
+ end
232
+
233
+ loop do
234
+ changed = false
235
+
236
+ helpers.keys.each do |helper|
237
+ format_helper_dependencies(helper).each do |dependency|
238
+ next if helpers[dependency]
239
+
240
+ helpers[dependency] = true
241
+ changed = true
242
+ end
243
+ end
244
+
245
+ break unless changed
246
+ end
247
+
248
+ helpers
249
+ end
250
+ end
251
+
252
+ def format_helper_dependencies(helper)
253
+ case helper
254
+ when 'mt_format_append_str'
255
+ %w[mt_format_append_bytes mt_format_check_capacity]
256
+ when 'mt_format_append_cstr'
257
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_cstr_len]
258
+ when 'mt_format_append_bool'
259
+ %w[mt_format_append_bytes mt_format_check_capacity]
260
+ when 'mt_format_append_ptr_uint'
261
+ %w[mt_format_check_capacity mt_format_ptr_uint_len]
262
+ when 'mt_format_append_ulong'
263
+ %w[mt_format_check_capacity mt_format_ulong_len]
264
+ when 'mt_format_append_uint'
265
+ %w[mt_format_append_ptr_uint mt_format_check_capacity mt_format_ptr_uint_len]
266
+ when 'mt_format_append_long'
267
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ulong mt_format_ulong_len]
268
+ when 'mt_format_append_int'
269
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ptr_uint mt_format_ptr_uint_len]
270
+ when 'mt_format_append_ulong_hex'
271
+ %w[mt_format_check_capacity mt_format_ulong_hex_len]
272
+ when 'mt_format_append_ulong_hex_upper'
273
+ %w[mt_format_check_capacity mt_format_ulong_hex_len]
274
+ when 'mt_format_append_long_hex'
275
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ulong_hex mt_format_ulong_hex_len]
276
+ when 'mt_format_append_long_hex_upper'
277
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ulong_hex_upper mt_format_ulong_hex_len]
278
+ when 'mt_format_append_ulong_oct'
279
+ %w[mt_format_check_capacity mt_format_ulong_oct_len]
280
+ when 'mt_format_append_long_oct'
281
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ulong_oct mt_format_ulong_oct_len]
282
+ when 'mt_format_append_ulong_bin'
283
+ %w[mt_format_check_capacity mt_format_ulong_bin_len]
284
+ when 'mt_format_append_long_bin'
285
+ %w[mt_format_append_bytes mt_format_check_capacity mt_format_append_ulong_bin mt_format_ulong_bin_len]
286
+ when 'mt_format_append_float'
287
+ %w[mt_format_check_capacity mt_format_float_len]
288
+ when 'mt_format_append_double'
289
+ %w[mt_format_check_capacity mt_format_double_len]
290
+ when 'mt_format_append_double_precision'
291
+ %w[mt_format_check_capacity mt_format_double_precision_len]
292
+ when 'mt_format_int_len'
293
+ %w[mt_format_ptr_uint_len]
294
+ when 'mt_format_long_len'
295
+ %w[mt_format_ulong_len]
296
+ when 'mt_format_long_hex_len'
297
+ %w[mt_format_ulong_hex_len]
298
+ when 'mt_format_long_oct_len'
299
+ %w[mt_format_ulong_oct_len]
300
+ when 'mt_format_long_bin_len'
301
+ %w[mt_format_ulong_bin_len]
302
+ else
303
+ []
304
+ end
305
+ end
306
+
307
+ def uses_format_helpers?
308
+ !used_format_helpers.empty?
309
+ end
310
+
311
+ def uses_str_equality_helper?
312
+ emitted_functions.any? { |function| function_uses_str_equality?(function) }
313
+ end
314
+
315
+ def uses_variant_equality_helper?
316
+ emitted_functions.any? { |function| function_uses_variant_equality?(function) }
317
+ end
318
+
319
+ def function_uses_variant_equality?(function)
320
+ function.body.any? { |statement| statement_uses_variant_equality?(statement) }
321
+ end
322
+
323
+ def statement_uses_variant_equality?(statement)
324
+ case statement
325
+ when IR::LocalDecl
326
+ expression_uses_variant_equality?(statement.value)
327
+ when IR::ExpressionStmt
328
+ expression_uses_variant_equality?(statement.expression)
329
+ when IR::ReturnStmt
330
+ statement.value && expression_uses_variant_equality?(statement.value)
331
+ when IR::Assignment
332
+ expression_uses_variant_equality?(statement.value)
333
+ when IR::IfStmt
334
+ expression_uses_variant_equality?(statement.condition)
335
+ when IR::WhileStmt
336
+ expression_uses_variant_equality?(statement.condition)
337
+ else
338
+ false
339
+ end
340
+ end
341
+
342
+ def expression_uses_variant_equality?(expression)
343
+ return false unless expression
344
+
345
+ case expression
346
+ when IR::Binary
347
+ EQUALITY_OPERATORS.include?(expression.operator) &&
348
+ (expression.left.type.is_a?(Types::Variant) || expression.left.type.is_a?(Types::VariantArmPayload))
349
+ when IR::Call
350
+ expression.arguments.any? { |arg| expression_uses_variant_equality?(arg) }
351
+ else
352
+ false
353
+ end
354
+ end
355
+
356
+ def function_uses_named_call?(function, callees)
357
+ function.body.any? { |statement| statement_uses_named_call?(statement, callees) }
358
+ end
359
+
360
+ def function_uses_str_equality?(function)
361
+ function.body.any? { |statement| statement_uses_str_equality?(statement) }
362
+ end
363
+
364
+ def statement_uses_named_call?(statement, callees)
365
+ case statement
366
+ when IR::LocalDecl
367
+ expression_uses_named_call?(statement.value, callees)
368
+ when IR::Assignment
369
+ expression_uses_named_call?(statement.target, callees) || expression_uses_named_call?(statement.value, callees)
370
+ when IR::BlockStmt
371
+ statement.body.any? { |inner| statement_uses_named_call?(inner, callees) }
372
+ when IR::WhileStmt
373
+ expression_uses_named_call?(statement.condition, callees) || statement.body.any? { |inner| statement_uses_named_call?(inner, callees) }
374
+ when IR::ForStmt
375
+ statement_uses_named_call?(statement.init, callees) ||
376
+ expression_uses_named_call?(statement.condition, callees) ||
377
+ statement.body.any? { |inner| statement_uses_named_call?(inner, callees) } ||
378
+ statement_uses_named_call?(statement.post, callees)
379
+ when IR::IfStmt
380
+ expression_uses_named_call?(statement.condition, callees) ||
381
+ statement.then_body.any? { |inner| statement_uses_named_call?(inner, callees) } ||
382
+ (statement.else_body && statement.else_body.any? { |inner| statement_uses_named_call?(inner, callees) })
383
+ when IR::SwitchStmt
384
+ expression_uses_named_call?(statement.expression, callees) || statement.cases.any? { |switch_case| switch_case.body.any? { |inner| statement_uses_named_call?(inner, callees) } }
385
+ when IR::StaticAssert
386
+ expression_uses_named_call?(statement.condition, callees) || expression_uses_named_call?(statement.message, callees)
387
+ when IR::ReturnStmt
388
+ statement.value && expression_uses_named_call?(statement.value, callees)
389
+ when IR::ExpressionStmt
390
+ expression_uses_named_call?(statement.expression, callees)
391
+ end
392
+ end
393
+
394
+ def statement_uses_str_equality?(statement)
395
+ case statement
396
+ when IR::LocalDecl
397
+ expression_uses_str_equality?(statement.value)
398
+ when IR::Assignment
399
+ expression_uses_str_equality?(statement.target) || expression_uses_str_equality?(statement.value)
400
+ when IR::BlockStmt
401
+ statement.body.any? { |inner| statement_uses_str_equality?(inner) }
402
+ when IR::WhileStmt
403
+ expression_uses_str_equality?(statement.condition) || statement.body.any? { |inner| statement_uses_str_equality?(inner) }
404
+ when IR::ForStmt
405
+ statement_uses_str_equality?(statement.init) ||
406
+ expression_uses_str_equality?(statement.condition) ||
407
+ statement.body.any? { |inner| statement_uses_str_equality?(inner) } ||
408
+ statement_uses_str_equality?(statement.post)
409
+ when IR::IfStmt
410
+ expression_uses_str_equality?(statement.condition) ||
411
+ statement.then_body.any? { |inner| statement_uses_str_equality?(inner) } ||
412
+ (statement.else_body && statement.else_body.any? { |inner| statement_uses_str_equality?(inner) })
413
+ when IR::SwitchStmt
414
+ expression_uses_str_equality?(statement.expression) || statement.cases.any? { |switch_case| switch_case.body.any? { |inner| statement_uses_str_equality?(inner) } }
415
+ when IR::StaticAssert
416
+ expression_uses_str_equality?(statement.condition) || expression_uses_str_equality?(statement.message)
417
+ when IR::ReturnStmt
418
+ statement.value && expression_uses_str_equality?(statement.value)
419
+ when IR::ExpressionStmt
420
+ expression_uses_str_equality?(statement.expression)
421
+ else
422
+ false
423
+ end
424
+ end
425
+
426
+ def expression_uses_named_call?(expression, callees)
427
+ case expression
428
+ when IR::Call
429
+ callees.include?(expression.callee) ||
430
+ (!expression.callee.is_a?(String) && expression_uses_named_call?(expression.callee, callees)) ||
431
+ expression.arguments.any? { |argument| expression_uses_named_call?(argument, callees) }
432
+ when IR::Member
433
+ expression_uses_named_call?(expression.receiver, callees)
434
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
435
+ expression_uses_named_call?(expression.receiver, callees) || expression_uses_named_call?(expression.index, callees)
436
+ when IR::Unary
437
+ expression_uses_named_call?(expression.operand, callees)
438
+ when IR::Binary
439
+ expression_uses_named_call?(expression.left, callees) || expression_uses_named_call?(expression.right, callees)
440
+ when IR::Conditional
441
+ expression_uses_named_call?(expression.condition, callees) || expression_uses_named_call?(expression.then_expression, callees) || expression_uses_named_call?(expression.else_expression, callees)
442
+ when IR::ReinterpretExpr, IR::Cast, IR::AddressOf
443
+ expression_uses_named_call?(expression.expression, callees)
444
+ when IR::AggregateLiteral
445
+ expression.fields.any? { |field| expression_uses_named_call?(field.value, callees) }
446
+ when IR::ArrayLiteral
447
+ expression.elements.any? { |element| expression_uses_named_call?(element, callees) }
448
+ when IR::VariantLiteral
449
+ expression.fields.any? { |field| expression_uses_named_call?(field.value, callees) }
450
+ else
451
+ false
452
+ end
453
+ end
454
+
455
+ def expression_uses_str_equality?(expression)
456
+ case expression
457
+ when IR::Binary
458
+ str_equality_expression?(expression) || expression_uses_str_equality?(expression.left) || expression_uses_str_equality?(expression.right)
459
+ when IR::Call
460
+ (!expression.callee.is_a?(String) && expression_uses_str_equality?(expression.callee)) || expression.arguments.any? { |argument| expression_uses_str_equality?(argument) }
461
+ when IR::Member
462
+ expression_uses_str_equality?(expression.receiver)
463
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
464
+ expression_uses_str_equality?(expression.receiver) || expression_uses_str_equality?(expression.index)
465
+ when IR::Unary
466
+ expression_uses_str_equality?(expression.operand)
467
+ when IR::Conditional
468
+ expression_uses_str_equality?(expression.condition) || expression_uses_str_equality?(expression.then_expression) || expression_uses_str_equality?(expression.else_expression)
469
+ when IR::ReinterpretExpr, IR::Cast, IR::AddressOf
470
+ expression_uses_str_equality?(expression.expression)
471
+ when IR::AggregateLiteral
472
+ expression.fields.any? { |field| expression_uses_str_equality?(field.value) }
473
+ when IR::ArrayLiteral
474
+ expression.elements.any? { |element| expression_uses_str_equality?(element) }
475
+ when IR::VariantLiteral
476
+ expression.fields.any? { |field| expression_uses_str_equality?(field.value) }
477
+ else
478
+ false
479
+ end
480
+ end
481
+ end
482
+ end
483
+ end