mt-lang 0.3.8 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/lib/milk_tea/base.rb +1 -2
  3. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
  4. data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
  5. data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
  6. data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
  7. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
  8. data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
  9. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
  10. data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
  11. data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
  12. data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
  13. data/lib/milk_tea/bindings/steamworks.rb +12 -16
  14. data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
  15. data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
  16. data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
  17. data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
  18. data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
  19. data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
  20. data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
  21. data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
  22. data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
  23. data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
  24. data/lib/milk_tea/core/ast.rb +103 -45
  25. data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
  26. data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
  27. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
  28. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
  29. data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
  30. data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
  31. data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
  32. data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
  33. data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
  34. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
  35. data/lib/milk_tea/core/c_backend/statements.rb +528 -530
  36. data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
  37. data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
  38. data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
  39. data/lib/milk_tea/core/c_backend.rb +17 -9
  40. data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
  41. data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
  42. data/lib/milk_tea/core/compile_time.rb +32 -38
  43. data/lib/milk_tea/core/control_flow/builder.rb +3 -5
  44. data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
  45. data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
  46. data/lib/milk_tea/core/ir.rb +10 -10
  47. data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
  48. data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
  49. data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
  50. data/lib/milk_tea/core/lexer/indentation.rb +0 -2
  51. data/lib/milk_tea/core/lexer/numbers.rb +0 -2
  52. data/lib/milk_tea/core/lexer/recovery.rb +0 -2
  53. data/lib/milk_tea/core/lexer/strings.rb +0 -2
  54. data/lib/milk_tea/core/lexer/symbols.rb +0 -2
  55. data/lib/milk_tea/core/lexer/trivia.rb +0 -2
  56. data/lib/milk_tea/core/lexer.rb +0 -2
  57. data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
  58. data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
  59. data/lib/milk_tea/core/lowering/async/normalization.rb +0 -2
  60. data/lib/milk_tea/core/lowering/async.rb +627 -630
  61. data/lib/milk_tea/core/lowering/block.rb +413 -416
  62. data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
  63. data/lib/milk_tea/core/lowering/declarations.rb +180 -183
  64. data/lib/milk_tea/core/lowering/dyn.rb +48 -50
  65. data/lib/milk_tea/core/lowering/events.rb +983 -985
  66. data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
  67. data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
  68. data/lib/milk_tea/core/lowering/functions.rb +185 -188
  69. data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
  70. data/lib/milk_tea/core/lowering/proc.rb +363 -366
  71. data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
  72. data/lib/milk_tea/core/lowering/scans.rb +179 -181
  73. data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
  74. data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
  75. data/lib/milk_tea/core/lowering.rb +5 -7
  76. data/lib/milk_tea/core/module_binder.rb +0 -2
  77. data/lib/milk_tea/core/module_loader/errors.rb +4 -2
  78. data/lib/milk_tea/core/module_loader.rb +113 -20
  79. data/lib/milk_tea/core/module_path_resolver.rb +0 -2
  80. data/lib/milk_tea/core/module_roots.rb +6 -8
  81. data/lib/milk_tea/core/parser/attributes.rb +0 -2
  82. data/lib/milk_tea/core/parser/blocks.rb +0 -2
  83. data/lib/milk_tea/core/parser/declarations.rb +0 -2
  84. data/lib/milk_tea/core/parser/expressions.rb +31 -14
  85. data/lib/milk_tea/core/parser/recovery.rb +0 -2
  86. data/lib/milk_tea/core/parser/statements.rb +0 -2
  87. data/lib/milk_tea/core/parser/types.rb +8 -10
  88. data/lib/milk_tea/core/parser.rb +1 -3
  89. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
  90. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
  91. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
  92. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
  93. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
  94. data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
  95. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
  96. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
  97. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
  98. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +12 -15
  99. data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
  100. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
  101. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
  102. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
  103. data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
  104. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
  105. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
  106. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +102 -105
  107. data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
  108. data/lib/milk_tea/core/types/layout.rb +21 -22
  109. data/lib/milk_tea/core/types/predicates.rb +0 -2
  110. data/lib/milk_tea/core/types/registry.rb +16 -18
  111. data/lib/milk_tea/core/types/visitor.rb +0 -4
  112. data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
  113. data/lib/milk_tea/dap/protocol.rb +1 -1
  114. data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
  115. data/lib/milk_tea/dap/server/debug_map.rb +0 -2
  116. data/lib/milk_tea/dap/server/handlers.rb +0 -2
  117. data/lib/milk_tea/dap/server/launch.rb +0 -2
  118. data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
  119. data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
  120. data/lib/milk_tea/dap/server/utilities.rb +0 -2
  121. data/lib/milk_tea/dap/server/wire.rb +0 -2
  122. data/lib/milk_tea/dap/server.rb +0 -2
  123. data/lib/milk_tea/lsp/diagnostics.rb +16 -16
  124. data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
  125. data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
  126. data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
  127. data/lib/milk_tea/lsp/server/completion.rb +873 -875
  128. data/lib/milk_tea/lsp/server/configuration.rb +129 -131
  129. data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
  130. data/lib/milk_tea/lsp/server/definition.rb +564 -565
  131. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
  132. data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
  133. data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
  134. data/lib/milk_tea/lsp/server/formatting.rb +478 -480
  135. data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
  136. data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
  137. data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
  138. data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
  139. data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
  140. data/lib/milk_tea/lsp/server/progress.rb +0 -2
  141. data/lib/milk_tea/lsp/server/references.rb +316 -318
  142. data/lib/milk_tea/lsp/server/rename.rb +445 -447
  143. data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
  144. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1318 -1320
  145. data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
  146. data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
  147. data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
  148. data/lib/milk_tea/lsp/server/utilities.rb +397 -399
  149. data/lib/milk_tea/lsp/server.rb +0 -3
  150. data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
  151. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
  152. data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
  153. data/lib/milk_tea/packages/atomic_write.rb +4 -5
  154. data/lib/milk_tea/packages/dependency_solver.rb +15 -15
  155. data/lib/milk_tea/packages/lock.rb +4 -4
  156. data/lib/milk_tea/packages/manager_cli.rb +1 -1
  157. data/lib/milk_tea/packages/manifest.rb +3 -3
  158. data/lib/milk_tea/packages/registry_store.rb +4 -6
  159. data/lib/milk_tea/packages/services.rb +16 -16
  160. data/lib/milk_tea/packages/source_cache.rb +4 -6
  161. data/lib/milk_tea/packages/source_resolver.rb +44 -44
  162. data/lib/milk_tea/packages/version.rb +8 -8
  163. data/lib/milk_tea/tooling/build.rb +3 -7
  164. data/lib/milk_tea/tooling/build_cache.rb +0 -2
  165. data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
  166. data/lib/milk_tea/tooling/debug_map.rb +8 -10
  167. data/lib/milk_tea/tooling/docs_app.rb +0 -2
  168. data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
  169. data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
  170. data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
  171. data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
  172. data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
  173. data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
  174. data/lib/milk_tea/tooling/linter/rules.rb +87 -89
  175. data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
  176. data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
  177. data/lib/milk_tea/tooling/linter/visitors.rb +162 -50
  178. data/lib/milk_tea/tooling/linter.rb +0 -2
  179. data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
  180. data/lib/milk_tea/tooling/run.rb +0 -2
  181. data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
  182. data/std/cli.mt +13 -32
  183. data/std/color.mt +28 -28
  184. data/std/encoding.mt +4 -4
  185. data/std/graph.mt +1 -2
  186. data/std/hash.mt +14 -14
  187. data/std/http/server.mt +3 -3
  188. data/std/input.mt +1 -1
  189. data/std/json.mt +1 -1
  190. data/std/linear_algebra.mt +6 -6
  191. data/std/net/mux.mt +1 -1
  192. data/std/noise.mt +23 -23
  193. data/std/parse.mt +2 -2
  194. data/std/process.mt +3 -4
  195. data/std/sparse_set.mt +1 -1
  196. data/std/steering.mt +5 -5
  197. data/std/str.mt +1 -1
  198. data/std/tween.mt +4 -4
  199. data/std/utility.mt +3 -3
  200. metadata +2 -2
@@ -3,224 +3,238 @@
3
3
  module MilkTea
4
4
  class CBackend
5
5
  module Reinterpret
6
- private
7
-
8
-
9
- def collect_reinterpret_helpers
10
- helpers = []
11
- seen = {}
12
-
13
- emitted_functions.each do |function|
14
- collect_reinterpret_helpers_from_statements(function.body, helpers, seen)
15
- end
16
-
17
- helpers
18
- end
19
-
20
- def collect_reinterpret_helpers_from_statements(statements, helpers, seen)
21
- statements.each do |statement|
22
- case statement
23
- when IR::LocalDecl
24
- collect_reinterpret_helpers_from_expression(statement.value, helpers, seen)
25
- when IR::Assignment
26
- collect_reinterpret_helpers_from_expression(statement.target, helpers, seen)
27
- collect_reinterpret_helpers_from_expression(statement.value, helpers, seen)
28
- when IR::BlockStmt
29
- collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
30
- when IR::WhileStmt
31
- collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
32
- collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
33
- when IR::ForStmt
34
- collect_reinterpret_helpers_from_statements([statement.init], helpers, seen)
35
- collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
36
- collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
37
- collect_reinterpret_helpers_from_statements([statement.post], helpers, seen)
38
- when IR::IfStmt
39
- collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
40
- collect_reinterpret_helpers_from_statements(statement.then_body, helpers, seen)
41
- collect_reinterpret_helpers_from_statements(statement.else_body, helpers, seen) if statement.else_body
42
- when IR::SwitchStmt
43
- collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen)
44
- statement.cases.each do |switch_case|
45
- collect_reinterpret_helpers_from_statements(switch_case.body, helpers, seen)
46
- end
47
- when IR::StaticAssert
48
- collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
49
- collect_reinterpret_helpers_from_expression(statement.message, helpers, seen)
50
- when IR::ReturnStmt
51
- collect_reinterpret_helpers_from_expression(statement.value, helpers, seen) if statement.value
52
- when IR::ExpressionStmt
53
- collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen)
54
- end
6
+ def collect_reinterpret_helpers
7
+ helpers = []
8
+ seen = {}
9
+
10
+ emitted_functions.each do |function|
11
+ collect_reinterpret_helpers_from_statements(function.body, helpers, seen)
12
+ end
13
+
14
+ helpers
15
+ end
16
+
17
+ def collect_reinterpret_helpers_from_statements(statements, helpers, seen)
18
+ statements.each do |statement|
19
+ case statement
20
+ when IR::LocalDecl
21
+ collect_reinterpret_helpers_from_expression(statement.value, helpers, seen)
22
+ when IR::Assignment
23
+ collect_reinterpret_helpers_from_expression(statement.target, helpers, seen)
24
+ collect_reinterpret_helpers_from_expression(statement.value, helpers, seen)
25
+ when IR::BlockStmt
26
+ collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
27
+ when IR::WhileStmt
28
+ collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
29
+ collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
30
+ when IR::ForStmt
31
+ collect_reinterpret_helpers_from_statements([statement.init], helpers, seen)
32
+ collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
33
+ collect_reinterpret_helpers_from_statements(statement.body, helpers, seen)
34
+ collect_reinterpret_helpers_from_statements([statement.post], helpers, seen)
35
+ when IR::IfStmt
36
+ collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
37
+ collect_reinterpret_helpers_from_statements(statement.then_body, helpers, seen)
38
+ collect_reinterpret_helpers_from_statements(statement.else_body, helpers, seen) if statement.else_body
39
+ when IR::SwitchStmt
40
+ collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen)
41
+ statement.cases.each do |switch_case|
42
+ collect_reinterpret_helpers_from_statements(switch_case.body, helpers, seen)
55
43
  end
56
- end
57
-
58
- def collect_reinterpret_helpers_from_expression(expression, helpers, seen)
59
- case expression
60
- when IR::Member
61
- collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen)
62
- when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
63
- collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen)
64
- collect_reinterpret_helpers_from_expression(expression.index, helpers, seen)
65
- when IR::Call
66
- collect_reinterpret_helpers_from_expression(expression.callee, helpers, seen) unless expression.callee.is_a?(String)
67
- expression.arguments.each { |argument| collect_reinterpret_helpers_from_expression(argument, helpers, seen) }
68
- when IR::Unary
69
- collect_reinterpret_helpers_from_expression(expression.operand, helpers, seen)
70
- when IR::Binary
71
- collect_reinterpret_helpers_from_expression(expression.left, helpers, seen)
72
- collect_reinterpret_helpers_from_expression(expression.right, helpers, seen)
73
- when IR::Conditional
74
- collect_reinterpret_helpers_from_expression(expression.condition, helpers, seen)
75
- collect_reinterpret_helpers_from_expression(expression.then_expression, helpers, seen)
76
- collect_reinterpret_helpers_from_expression(expression.else_expression, helpers, seen)
77
- when IR::ReinterpretExpr
78
- return if no_op_reinterpret?(expression.target_type, expression.source_type)
79
-
80
- key = [expression.target_type, expression.source_type]
81
- unless seen[key]
82
- helpers << expression
83
- seen[key] = true
84
- end
85
- collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
86
- when IR::AddressOf
87
- collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
88
- when IR::Cast
89
- collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
90
- when IR::AggregateLiteral
91
- expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) }
92
- when IR::ArrayLiteral
93
- expression.elements.each { |element| collect_reinterpret_helpers_from_expression(element, helpers, seen) }
94
- when IR::VariantLiteral
95
- expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) }
96
- when IR::ZeroInit, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::Name, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
97
- nil
98
- end
99
- end
100
-
101
- def emit_reinterpret_helper(expression)
102
- helper_name = reinterpret_helper_name(expression.target_type, expression.source_type)
103
- params = c_declaration(expression.source_type, 'value')
104
- [
105
- "static inline #{c_function_declaration(expression.target_type, helper_name, params)} {",
106
- "#{INDENT}_Static_assert(sizeof(#{layout_type_expression(expression.target_type)}) == sizeof(#{layout_type_expression(expression.source_type)}), \"reinterpret requires equal sizes\");",
107
- "#{INDENT}#{c_declaration(expression.target_type, 'result')};",
108
- "#{INDENT}memcpy(&result, &value, sizeof(result));",
109
- "#{INDENT}return result;",
110
- "}",
111
- ]
112
- end
113
-
114
- def reinterpret_helper_name(target_type, source_type)
115
- "mt_reinterpret_#{sanitize_identifier(target_type.to_s)}_from_#{sanitize_identifier(source_type.to_s)}"
116
- end
117
-
118
- def no_op_cast?(expression)
119
- return false if expression.expression.type.is_a?(Types::Null)
120
-
121
- c_type(expression.target_type) == c_type(expression.expression.type)
122
- rescue StandardError
123
- false
124
- end
125
-
126
- def no_op_reinterpret?(target_type, source_type)
127
- c_type(target_type) == c_type(source_type)
128
- rescue StandardError
129
- false
130
- end
131
-
132
- def checked_array_index_helper_name(type)
133
- return "mt_checked_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type))
134
-
135
- "mt_checked_index_#{sanitize_identifier(type.to_s)}"
136
- end
137
-
138
- def checked_span_index_helper_name(type)
139
- return "mt_checked_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type)
140
-
141
- "mt_checked_span_index_#{sanitize_identifier(type.to_s)}"
142
- end
143
-
144
- def nullable_array_index_helper_name(type)
145
- return "mt_nullable_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type))
146
-
147
- "mt_nullable_index_#{sanitize_identifier(type.to_s)}"
148
- end
149
-
150
- def nullable_span_index_helper_name(type)
151
- return "mt_nullable_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type)
152
-
153
- "mt_nullable_span_index_#{sanitize_identifier(type.to_s)}"
154
- end
155
-
156
- def callable_container_element_type?(type)
157
- type.is_a?(Types::Function) || type.is_a?(Types::Proc)
158
- end
159
-
160
- def wrap_member_receiver(expression)
161
- case expression
162
- when IR::Unary
163
- if expression.operator == "*"
164
- wrap_pointer_member_receiver(expression.operand)
165
- else
166
- "(#{emit_expression(expression)})"
167
- end
168
- when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
169
- checked_index_alias(expression) || emit_expression(expression)
170
- when IR::Name, IR::Member, IR::Index
171
- emit_expression(expression)
172
- else
173
- "(#{emit_expression(expression)})"
174
- end
175
- end
176
-
177
- def pointer_member_receiver?(expression)
178
- return true if checked_index_alias(expression)
179
- return pointer_member_receiver?(expression.operand) if expression.is_a?(IR::Unary) && expression.operator == "*"
180
-
181
- (expression.is_a?(IR::Name) && expression.pointer) ||
182
- (expression.respond_to?(:type) && (raw_pointer_type?(expression.type) || ref_type?(expression.type) || nullable_pointer_like_ir_type?(expression.type)))
183
- end
184
-
185
- def nullable_pointer_like_ir_type?(type)
186
- return false unless type.is_a?(Types::Nullable)
187
-
188
- c_backend_pointer_like_type?(type.base)
189
- end
190
-
191
- def wrap_pointer_member_receiver(expression)
192
- case expression
193
- when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
194
- checked_index_alias(expression) || emit_expression(expression)
195
- when IR::Name, IR::Member, IR::Index, IR::Call
196
- emit_expression(expression)
197
- else
198
- "(#{emit_expression(expression)})"
199
- end
200
- end
201
-
202
- def wrap_index_receiver(expression)
203
- case expression
204
- when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
205
- if (alias_name = checked_index_alias(expression))
206
- "(*#{alias_name})"
207
- else
208
- emit_expression(expression)
209
- end
210
- when IR::Name, IR::Member, IR::Index, IR::Call
211
- emit_expression(expression)
212
- else
213
- "(#{emit_expression(expression)})"
214
- end
215
- end
216
-
217
- def c_operator(operator)
218
- operator == "and" ? "&&" : operator == "or" ? "||" : operator
219
- end
220
-
221
- def void_type
222
- @void_type ||= Types::Registry.primitive("void")
223
- end
44
+ when IR::StaticAssert
45
+ collect_reinterpret_helpers_from_expression(statement.condition, helpers, seen)
46
+ collect_reinterpret_helpers_from_expression(statement.message, helpers, seen)
47
+ when IR::ReturnStmt
48
+ collect_reinterpret_helpers_from_expression(statement.value, helpers, seen) if statement.value
49
+ when IR::ExpressionStmt
50
+ collect_reinterpret_helpers_from_expression(statement.expression, helpers, seen)
51
+ end
52
+ end
53
+ end
54
+
55
+ def collect_reinterpret_helpers_from_expression(expression, helpers, seen)
56
+ case expression
57
+ when IR::Member
58
+ collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen)
59
+ when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
60
+ collect_reinterpret_helpers_from_expression(expression.receiver, helpers, seen)
61
+ collect_reinterpret_helpers_from_expression(expression.index, helpers, seen)
62
+ when IR::Call
63
+ collect_reinterpret_helpers_from_expression(expression.callee, helpers, seen) unless expression.callee.is_a?(String)
64
+ expression.arguments.each { |argument| collect_reinterpret_helpers_from_expression(argument, helpers, seen) }
65
+ when IR::Unary
66
+ collect_reinterpret_helpers_from_expression(expression.operand, helpers, seen)
67
+ when IR::Binary
68
+ collect_reinterpret_helpers_from_expression(expression.left, helpers, seen)
69
+ collect_reinterpret_helpers_from_expression(expression.right, helpers, seen)
70
+ when IR::Conditional
71
+ collect_reinterpret_helpers_from_expression(expression.condition, helpers, seen)
72
+ collect_reinterpret_helpers_from_expression(expression.then_expression, helpers, seen)
73
+ collect_reinterpret_helpers_from_expression(expression.else_expression, helpers, seen)
74
+ when IR::ReinterpretExpr
75
+ return if no_op_reinterpret?(expression.target_type, expression.source_type)
76
+
77
+ key = [expression.target_type, expression.source_type]
78
+ unless seen[key]
79
+ helpers << expression
80
+ seen[key] = true
81
+ end
82
+ collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
83
+ when IR::AddressOf
84
+ collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
85
+ when IR::Cast
86
+ collect_reinterpret_helpers_from_expression(expression.expression, helpers, seen)
87
+ when IR::AggregateLiteral
88
+ expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) }
89
+ when IR::ArrayLiteral
90
+ expression.elements.each { |element| collect_reinterpret_helpers_from_expression(element, helpers, seen) }
91
+ when IR::VariantLiteral
92
+ expression.fields.each { |field| collect_reinterpret_helpers_from_expression(field.value, helpers, seen) }
93
+ when IR::ZeroInit, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::Name, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
94
+ nil
95
+ end
96
+ end
97
+
98
+ def emit_reinterpret_helper(expression)
99
+ helper_name = reinterpret_helper_name(expression.target_type, expression.source_type)
100
+ params = c_declaration(expression.source_type, 'value')
101
+ [
102
+ "static inline #{c_function_declaration(expression.target_type, helper_name, params)} {",
103
+ "#{INDENT}_Static_assert(sizeof(#{layout_type_expression(expression.target_type)}) == sizeof(#{layout_type_expression(expression.source_type)}), \"reinterpret requires equal sizes\");",
104
+ "#{INDENT}#{c_declaration(expression.target_type, 'result')};",
105
+ "#{INDENT}memcpy(&result, &value, sizeof(result));",
106
+ "#{INDENT}return result;",
107
+ "}",
108
+ ]
109
+ end
110
+
111
+ def reinterpret_helper_name(target_type, source_type)
112
+ "mt_reinterpret_#{sanitize_identifier(target_type.to_s)}_from_#{sanitize_identifier(source_type.to_s)}"
113
+ end
114
+
115
+ def no_op_cast?(expression)
116
+ return false if expression.expression.type.is_a?(Types::Null)
117
+
118
+ c_type(expression.target_type) == c_type(expression.expression.type)
119
+ rescue StandardError
120
+ false
121
+ end
122
+
123
+ def no_op_reinterpret?(target_type, source_type)
124
+ c_type(target_type) == c_type(source_type)
125
+ rescue StandardError
126
+ false
127
+ end
128
+
129
+ def checked_array_index_helper_name(type)
130
+ return "mt_checked_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type))
131
+
132
+ "mt_checked_index_#{sanitize_identifier(type.to_s)}"
133
+ end
134
+
135
+ def checked_span_index_helper_name(type)
136
+ return "mt_checked_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type)
137
+
138
+ "mt_checked_span_index_#{sanitize_identifier(type.to_s)}"
139
+ end
140
+
141
+ def nullable_array_index_helper_name(type)
142
+ return "mt_nullable_index_array_#{sanitize_identifier(c_declaration(array_element_type(type), 'value'))}_#{array_length(type)}" if array_type?(type) && callable_container_element_type?(array_element_type(type))
143
+
144
+ "mt_nullable_index_#{sanitize_identifier(type.to_s)}"
145
+ end
146
+
147
+ def nullable_span_index_helper_name(type)
148
+ return "mt_nullable_span_index_#{sanitize_identifier(c_declaration(type.element_type, 'value'))}" if callable_container_element_type?(type.element_type)
149
+
150
+ "mt_nullable_span_index_#{sanitize_identifier(type.to_s)}"
151
+ end
152
+
153
+ def callable_container_element_type?(type)
154
+ type.is_a?(Types::Function) || type.is_a?(Types::Proc)
155
+ end
156
+
157
+ def wrap_member_receiver(expression)
158
+ case expression
159
+ when IR::Unary
160
+ if expression.operator == "*"
161
+ wrap_pointer_member_receiver(expression.operand)
162
+ else
163
+ "(#{emit_expression(expression)})"
164
+ end
165
+ when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
166
+ checked_index_alias(expression) || emit_expression(expression)
167
+ when IR::Name, IR::Member, IR::Index
168
+ emit_expression(expression)
169
+ else
170
+ "(#{emit_expression(expression)})"
171
+ end
172
+ end
173
+
174
+ def pointer_member_receiver?(expression)
175
+ return true if checked_index_alias(expression)
176
+ return pointer_member_receiver?(expression.operand) if expression.is_a?(IR::Unary) && expression.operator == "*"
177
+
178
+ if expression.is_a?(IR::Member)
179
+ field_type = variant_arm_payload_field_type(expression)
180
+ if field_type && expression.receiver.type.is_a?(Types::VariantArmPayload)
181
+ parent_c = named_type_c_name(expression.receiver.type.variant_type)
182
+ return true if aggregate_field_creates_cycle?(field_type, parent_c)
183
+ end
184
+ end
185
+
186
+ (expression.is_a?(IR::Name) && expression.pointer) ||
187
+ (expression.respond_to?(:type) && (raw_pointer_type?(expression.type) || ref_type?(expression.type) || nullable_pointer_like_ir_type?(expression.type)))
188
+ end
189
+
190
+ def variant_arm_payload_field_type(member_expr)
191
+ receiver_type = member_expr.receiver.type
192
+ return nil unless receiver_type.is_a?(Types::VariantArmPayload)
193
+
194
+ arm_name = receiver_type.arm_name
195
+ variant_type = receiver_type.variant_type
196
+ variant_type.arm(arm_name)&.fetch(member_expr.member)
197
+ end
198
+
199
+ def nullable_pointer_like_ir_type?(type)
200
+ return false unless type.is_a?(Types::Nullable)
201
+
202
+ c_backend_pointer_like_type?(type.base)
203
+ end
204
+
205
+ def wrap_pointer_member_receiver(expression)
206
+ case expression
207
+ when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
208
+ checked_index_alias(expression) || emit_expression(expression)
209
+ when IR::Name, IR::Member, IR::Index, IR::Call
210
+ emit_expression(expression)
211
+ else
212
+ "(#{emit_expression(expression)})"
213
+ end
214
+ end
215
+
216
+ def wrap_index_receiver(expression)
217
+ case expression
218
+ when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
219
+ if (alias_name = checked_index_alias(expression))
220
+ "(*#{alias_name})"
221
+ else
222
+ emit_expression(expression)
223
+ end
224
+ when IR::Name, IR::Member, IR::Index, IR::Call
225
+ emit_expression(expression)
226
+ else
227
+ "(#{emit_expression(expression)})"
228
+ end
229
+ end
230
+
231
+ def c_operator(operator)
232
+ operator == "and" ? "&&" : operator == "or" ? "||" : operator
233
+ end
234
+
235
+ def void_type
236
+ @void_type ||= Types::Registry.primitive("void")
237
+ end
224
238
  end
225
239
  end
226
240
  end