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,1054 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module LowererEvents
5
+ private
6
+
7
+ def event_method_kind(receiver_type, member_name)
8
+ return unless receiver_type.is_a?(Types::Event)
9
+
10
+ case member_name
11
+ when "subscribe" then :event_subscribe
12
+ when "subscribe_once" then :event_subscribe_once
13
+ when "unsubscribe" then :event_unsubscribe
14
+ when "emit" then :event_emit
15
+ when "wait" then :event_wait
16
+ end
17
+ end
18
+
19
+ def event_method_type(kind, event_type)
20
+ case kind
21
+ when :event_subscribe, :event_subscribe_once
22
+ Types::Registry.function(
23
+ kind.to_s,
24
+ params: [Types::Registry.parameter("listener", event_listener_function_type(event_type))],
25
+ return_type: event_subscription_result_type,
26
+ )
27
+ when :event_subscribe_stateful, :event_subscribe_once_stateful
28
+ Types::Registry.function(
29
+ kind.to_s,
30
+ params: [
31
+ Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void"))),
32
+ Types::Registry.parameter("listener", event_stateful_listener_function_type(event_type)),
33
+ ],
34
+ return_type: event_subscription_result_type,
35
+ )
36
+ when :event_unsubscribe
37
+ Types::Registry.function(
38
+ kind.to_s,
39
+ params: [Types::Registry.parameter("subscription", @ctx.types.fetch("Subscription"))],
40
+ return_type: @ctx.types.fetch("bool"),
41
+ )
42
+ when :event_emit
43
+ params = []
44
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
45
+ Types::Registry.function(kind.to_s, params:, return_type: @ctx.types.fetch("void"))
46
+ when :event_wait
47
+ Types::Registry.function(kind.to_s, params: [], return_type: Types::Registry.task(event_wait_result_type(event_type)))
48
+ else
49
+ raise LoweringError, "unsupported event method #{kind}"
50
+ end
51
+ end
52
+
53
+ def event_member_from_owner_type(receiver_type, member_name)
54
+ owner_type = receiver_type
55
+ loop do
56
+ case owner_type
57
+ when Types::Nullable
58
+ owner_type = owner_type.base
59
+ when Types::GenericInstance
60
+ if %w[ptr const_ptr own ref].include?(owner_type.name) && owner_type.arguments.length == 1
61
+ owner_type = owner_type.arguments.first
62
+ else
63
+ break
64
+ end
65
+ else
66
+ break
67
+ end
68
+ end
69
+
70
+ return unless owner_type.respond_to?(:event)
71
+
72
+ owner_type.event(member_name)
73
+ end
74
+
75
+ def lower_event_storage_pointer(expression, env:)
76
+ event_type = infer_expression_type(expression, env:)
77
+ IR::AddressOf.new(
78
+ expression: lower_expression(expression, env:, expected_type: event_type),
79
+ type: pointer_to(event_type),
80
+ )
81
+ end
82
+
83
+ def event_listener_function_type(event_type)
84
+ params = []
85
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
86
+ Types::Registry.function("#{event_type.name}__listener", params:, return_type: @ctx.types.fetch("void"))
87
+ end
88
+
89
+ def event_stateful_listener_function_type(event_type)
90
+ params = [Types::Registry.parameter("state", pointer_to(@ctx.types.fetch("void")))]
91
+ params << Types::Registry.parameter("payload", event_type.payload_type) if event_type.payload_type
92
+ Types::Registry.function("#{event_type.name}__stateful_listener", params:, return_type: @ctx.types.fetch("void"))
93
+ end
94
+
95
+ def array_of(type, length)
96
+ Types::Registry.generic_instance("array", [type, Types::LiteralTypeArg.new(length)])
97
+ end
98
+
99
+ def ensure_subscription_runtime
100
+ return if @artifacts.subscription_runtime_emitted
101
+
102
+ subscription_type = @ctx.types.fetch("Subscription")
103
+ @artifacts.synthetic_structs << IR::StructDecl.new(
104
+ name: subscription_type.name,
105
+ linkage_name: subscription_type.linkage_name,
106
+ fields: [
107
+ IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
108
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
109
+ ],
110
+ packed: false,
111
+ alignment: nil,
112
+ )
113
+ @artifacts.subscription_runtime_emitted = true
114
+ end
115
+
116
+ def ensure_event_error_enum
117
+ return if @artifacts.event_error_enum_emitted
118
+
119
+ event_error_type = @ctx.types.fetch("EventError")
120
+ @artifacts.synthetic_enums << IR::EnumDecl.new(
121
+ name: event_error_type.name,
122
+ linkage_name: c_type_name(event_error_type),
123
+ backing_type: event_error_type.backing_type,
124
+ members: [
125
+ IR::EnumMember.new(
126
+ name: "full",
127
+ linkage_name: enum_member_c_name(event_error_type, "full"),
128
+ value: IR::IntegerLiteral.new(value: 0, type: event_error_type.backing_type),
129
+ ),
130
+ ],
131
+ flags: false,
132
+ )
133
+ @artifacts.event_error_enum_emitted = true
134
+ end
135
+
136
+ def ensure_event_runtime(event_type)
137
+ return @artifacts.event_runtime_infos.fetch(event_type) if @artifacts.event_runtime_infos.key?(event_type)
138
+
139
+ ensure_subscription_runtime
140
+ ensure_event_error_enum
141
+
142
+ void_ptr = pointer_to(@ctx.types.fetch("void"))
143
+ listener_type = event_listener_function_type(event_type)
144
+ subscription_result_type = event_subscription_result_type
145
+ wait_result_type = event_wait_result_type(event_type)
146
+ task_type = Types::Registry.task(wait_result_type)
147
+ wake_type = task_type.field("ready").params.fetch(0).type == void_ptr ? task_type.field("set_waiter").params.fetch(2).type : Types::Registry.function(nil, params: [Types::Registry.parameter("frame", void_ptr)], return_type: @ctx.types.fetch("void"))
148
+ slot_type = Types::Struct.new("#{event_type.linkage_name}__slot").define_fields(
149
+ "active" => @ctx.types.fetch("bool"),
150
+ "once" => @ctx.types.fetch("bool"),
151
+ "generation" => @ctx.types.fetch("ptr_uint"),
152
+ "state" => void_ptr,
153
+ "listener" => void_ptr,
154
+ "wait_frame" => void_ptr,
155
+ )
156
+ snapshot_type = Types::Struct.new("#{event_type.linkage_name}__snapshot").define_fields(
157
+ "slot" => @ctx.types.fetch("ptr_uint"),
158
+ "generation" => @ctx.types.fetch("ptr_uint"),
159
+ "once" => @ctx.types.fetch("bool"),
160
+ "wait_slot" => @ctx.types.fetch("bool"),
161
+ "stateful" => @ctx.types.fetch("bool"),
162
+ "state" => void_ptr,
163
+ "listener" => void_ptr,
164
+ )
165
+ wait_frame_type = Types::Struct.new("#{event_type.linkage_name}__wait_frame").define_fields(
166
+ "ready" => @ctx.types.fetch("bool"),
167
+ "waiter_frame" => void_ptr,
168
+ "waiter" => wake_type,
169
+ "event" => void_ptr,
170
+ "subscription" => @ctx.types.fetch("Subscription"),
171
+ "result" => wait_result_type,
172
+ )
173
+ slots_type = array_of(slot_type, event_type.capacity)
174
+ snapshots_type = array_of(snapshot_type, event_type.capacity)
175
+
176
+ @artifacts.synthetic_structs << IR::StructDecl.new(
177
+ name: slot_type.name,
178
+ linkage_name: slot_type.name,
179
+ fields: [
180
+ IR::Field.new(name: "active", type: @ctx.types.fetch("bool")),
181
+ IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
182
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
183
+ IR::Field.new(name: "state", type: void_ptr),
184
+ IR::Field.new(name: "listener", type: void_ptr),
185
+ IR::Field.new(name: "wait_frame", type: void_ptr),
186
+ ],
187
+ packed: false,
188
+ alignment: nil,
189
+ )
190
+ @artifacts.synthetic_structs << IR::StructDecl.new(
191
+ name: snapshot_type.name,
192
+ linkage_name: snapshot_type.name,
193
+ fields: [
194
+ IR::Field.new(name: "slot", type: @ctx.types.fetch("ptr_uint")),
195
+ IR::Field.new(name: "generation", type: @ctx.types.fetch("ptr_uint")),
196
+ IR::Field.new(name: "once", type: @ctx.types.fetch("bool")),
197
+ IR::Field.new(name: "wait_slot", type: @ctx.types.fetch("bool")),
198
+ IR::Field.new(name: "stateful", type: @ctx.types.fetch("bool")),
199
+ IR::Field.new(name: "state", type: void_ptr),
200
+ IR::Field.new(name: "listener", type: void_ptr),
201
+ ],
202
+ packed: false,
203
+ alignment: nil,
204
+ )
205
+ @artifacts.synthetic_structs << IR::StructDecl.new(
206
+ name: wait_frame_type.name,
207
+ linkage_name: wait_frame_type.name,
208
+ fields: [
209
+ IR::Field.new(name: "ready", type: @ctx.types.fetch("bool")),
210
+ IR::Field.new(name: "waiter_frame", type: void_ptr),
211
+ IR::Field.new(name: "waiter", type: wake_type),
212
+ IR::Field.new(name: "event", type: void_ptr),
213
+ IR::Field.new(name: "subscription", type: @ctx.types.fetch("Subscription")),
214
+ IR::Field.new(name: "result", type: wait_result_type),
215
+ ],
216
+ packed: false,
217
+ alignment: nil,
218
+ )
219
+ @artifacts.synthetic_structs << IR::StructDecl.new(
220
+ name: event_type.name,
221
+ linkage_name: event_type.linkage_name,
222
+ fields: [IR::Field.new(name: "slots", type: slots_type)],
223
+ packed: false,
224
+ alignment: nil,
225
+ )
226
+
227
+ runtime = {
228
+ event_type:,
229
+ event_pointer_type: pointer_to(event_type),
230
+ listener_type:,
231
+ stateful_listener_type: event_stateful_listener_function_type(event_type),
232
+ slot_type:,
233
+ slot_pointer_type: pointer_to(slot_type),
234
+ slots_type:,
235
+ snapshot_type:,
236
+ snapshots_type:,
237
+ wait_frame_type:,
238
+ wait_frame_pointer_type: pointer_to(wait_frame_type),
239
+ void_ptr:,
240
+ wake_type:,
241
+ subscription_result_type:,
242
+ wait_result_type:,
243
+ task_type:,
244
+ subscribe_linkage_name: "#{event_type.linkage_name}__subscribe",
245
+ subscribe_once_linkage_name: "#{event_type.linkage_name}__subscribe_once",
246
+ subscribe_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_stateful",
247
+ subscribe_once_stateful_linkage_name: "#{event_type.linkage_name}__subscribe_once_stateful",
248
+ unsubscribe_linkage_name: "#{event_type.linkage_name}__unsubscribe",
249
+ emit_linkage_name: "#{event_type.linkage_name}__emit",
250
+ wait_linkage_name: "#{event_type.linkage_name}__wait",
251
+ wait_ready_linkage_name: "#{event_type.linkage_name}__wait__ready",
252
+ wait_set_waiter_linkage_name: "#{event_type.linkage_name}__wait__set_waiter",
253
+ wait_release_linkage_name: "#{event_type.linkage_name}__wait__release",
254
+ wait_take_result_linkage_name: "#{event_type.linkage_name}__wait__take_result",
255
+ }
256
+
257
+ @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: false)
258
+ @artifacts.synthetic_functions << build_event_subscribe_function(runtime, once: true)
259
+ @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: false)
260
+ @artifacts.synthetic_functions << build_event_subscribe_stateful_function(runtime, once: true)
261
+ @artifacts.synthetic_functions << build_event_unsubscribe_function(runtime)
262
+ @artifacts.synthetic_functions << build_event_emit_function(runtime)
263
+ @artifacts.synthetic_functions << build_event_wait_ready_function(runtime)
264
+ @artifacts.synthetic_functions << build_event_wait_set_waiter_function(runtime)
265
+ @artifacts.synthetic_functions << build_event_wait_release_function(runtime)
266
+ @artifacts.synthetic_functions << build_event_wait_take_result_function(runtime)
267
+ @artifacts.synthetic_functions << build_event_wait_function(runtime)
268
+
269
+ @artifacts.event_runtime_infos[event_type] = runtime
270
+ end
271
+
272
+ def build_event_subscribe_function(runtime, once:)
273
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
274
+ listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:listener_type), pointer: false)
275
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
276
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
277
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
278
+
279
+ body = [
280
+ IR::ForStmt.new(
281
+ init: IR::LocalDecl.new(
282
+ name: "__mt_slot_index",
283
+ linkage_name: "__mt_slot_index",
284
+ type: @ctx.types.fetch("ptr_uint"),
285
+ value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
286
+ ),
287
+ condition: IR::Binary.new(
288
+ operator: "<",
289
+ left: slot_index_expr,
290
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
291
+ type: @ctx.types.fetch("bool"),
292
+ ),
293
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
294
+ body: [
295
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
296
+ active_event_slot_continue_guard(slot_pointer_expr),
297
+ IR::LocalDecl.new(
298
+ name: "__mt_generation",
299
+ linkage_name: "__mt_generation",
300
+ type: @ctx.types.fetch("ptr_uint"),
301
+ value: event_next_generation_expression(slot_pointer_expr),
302
+ ),
303
+ *event_slot_activate_statements(
304
+ slot_pointer_expr,
305
+ runtime,
306
+ generation_expr: generation_expr,
307
+ once: once,
308
+ wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
309
+ listener_expr: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: listener_expr, type: runtime.fetch(:void_ptr)),
310
+ ),
311
+ IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
312
+ ],
313
+ ),
314
+ IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
315
+ ]
316
+
317
+ IR::Function.new(
318
+ name: once ? "#{runtime.fetch(:subscribe_once_linkage_name)}_fn" : "#{runtime.fetch(:subscribe_linkage_name)}_fn",
319
+ linkage_name: once ? runtime.fetch(:subscribe_once_linkage_name) : runtime.fetch(:subscribe_linkage_name),
320
+ params: [
321
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
322
+ IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:listener_type), pointer: false),
323
+ ],
324
+ return_type: runtime.fetch(:subscription_result_type),
325
+ body:,
326
+ entry_point: false,
327
+ )
328
+ end
329
+
330
+ def build_event_subscribe_stateful_function(runtime, once:)
331
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
332
+ state_expr = IR::Name.new(name: "state", type: runtime.fetch(:void_ptr), pointer: false)
333
+ listener_expr = IR::Name.new(name: "listener", type: runtime.fetch(:void_ptr), pointer: false)
334
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
335
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
336
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
337
+
338
+ body = [
339
+ IR::ForStmt.new(
340
+ init: IR::LocalDecl.new(
341
+ name: "__mt_slot_index",
342
+ linkage_name: "__mt_slot_index",
343
+ type: @ctx.types.fetch("ptr_uint"),
344
+ value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint")),
345
+ ),
346
+ condition: IR::Binary.new(
347
+ operator: "<",
348
+ left: slot_index_expr,
349
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
350
+ type: @ctx.types.fetch("bool"),
351
+ ),
352
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
353
+ body: [
354
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
355
+ active_event_slot_continue_guard(slot_pointer_expr),
356
+ IR::LocalDecl.new(
357
+ name: "__mt_generation",
358
+ linkage_name: "__mt_generation",
359
+ type: @ctx.types.fetch("ptr_uint"),
360
+ value: event_next_generation_expression(slot_pointer_expr),
361
+ ),
362
+ *event_slot_activate_stateful_statements(
363
+ slot_pointer_expr,
364
+ runtime,
365
+ generation_expr: generation_expr,
366
+ once: once,
367
+ state_expr: state_expr,
368
+ wait_frame_expr: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
369
+ listener_expr: listener_expr,
370
+ ),
371
+ IR::ReturnStmt.new(value: event_subscription_success_literal(runtime.fetch(:subscription_result_type), slot_index_expr, generation_expr)),
372
+ ],
373
+ ),
374
+ IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:subscription_result_type))),
375
+ ]
376
+
377
+ linkage_name = once ? runtime.fetch(:subscribe_once_stateful_linkage_name) : runtime.fetch(:subscribe_stateful_linkage_name)
378
+ IR::Function.new(
379
+ name: "#{linkage_name}_fn",
380
+ linkage_name:,
381
+ params: [
382
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
383
+ IR::Param.new(name: "state", linkage_name: "state", type: runtime.fetch(:void_ptr), pointer: false),
384
+ IR::Param.new(name: "listener", linkage_name: "listener", type: runtime.fetch(:void_ptr), pointer: false),
385
+ ],
386
+ return_type: runtime.fetch(:subscription_result_type),
387
+ body:,
388
+ entry_point: false,
389
+ )
390
+ end
391
+
392
+ def build_event_unsubscribe_function(runtime)
393
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
394
+ subscription_expr = IR::Name.new(name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false)
395
+ slot_index_expr = subscription_field_expression(subscription_expr, "slot", @ctx.types.fetch("ptr_uint"))
396
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
397
+
398
+ false_value = IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))
399
+ true_value = IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))
400
+ body = [
401
+ IR::IfStmt.new(
402
+ condition: IR::Binary.new(
403
+ operator: ">=",
404
+ left: slot_index_expr,
405
+ right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")),
406
+ type: @ctx.types.fetch("bool"),
407
+ ),
408
+ then_body: [IR::ReturnStmt.new(value: false_value)],
409
+ else_body: nil,
410
+ ),
411
+ IR::LocalDecl.new(
412
+ name: "__mt_slot",
413
+ linkage_name: "__mt_slot",
414
+ type: runtime.fetch(:slot_pointer_type),
415
+ value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
416
+ ),
417
+ IR::IfStmt.new(
418
+ condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
419
+ then_body: [IR::ReturnStmt.new(value: false_value)],
420
+ else_body: nil,
421
+ ),
422
+ IR::IfStmt.new(
423
+ condition: IR::Binary.new(
424
+ operator: "!=",
425
+ left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
426
+ right: subscription_field_expression(subscription_expr, "generation", @ctx.types.fetch("ptr_uint")),
427
+ type: @ctx.types.fetch("bool"),
428
+ ),
429
+ then_body: [IR::ReturnStmt.new(value: false_value)],
430
+ else_body: nil,
431
+ ),
432
+ *event_slot_clear_statements(slot_pointer_expr, runtime),
433
+ IR::ReturnStmt.new(value: true_value),
434
+ ]
435
+
436
+ IR::Function.new(
437
+ name: "#{runtime.fetch(:unsubscribe_linkage_name)}_fn",
438
+ linkage_name: runtime.fetch(:unsubscribe_linkage_name),
439
+ params: [
440
+ IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false),
441
+ IR::Param.new(name: "subscription", linkage_name: "subscription", type: @ctx.types.fetch("Subscription"), pointer: false),
442
+ ],
443
+ return_type: @ctx.types.fetch("bool"),
444
+ body:,
445
+ entry_point: false,
446
+ )
447
+ end
448
+
449
+ def build_event_emit_function(runtime)
450
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
451
+ payload_expr = runtime.fetch(:event_type).payload_type ? IR::Name.new(name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) : nil
452
+ snapshots_expr = IR::Name.new(name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), pointer: false)
453
+ snapshot_count_expr = IR::Name.new(name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), pointer: false)
454
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
455
+ dispatch_index_expr = IR::Name.new(name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
456
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
457
+ frame_pointer_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
458
+
459
+ collect_body = [
460
+ event_slot_local_decl(event_expr, slot_index_expr, runtime),
461
+ inactive_event_slot_continue_guard(slot_pointer_expr),
462
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")), operator: "=", value: slot_index_expr),
463
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))),
464
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "once", @ctx.types.fetch("bool")), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool"))),
465
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
466
+ operator: "=",
467
+ value: IR::Binary.new(
468
+ operator: "!=",
469
+ left: event_slot_wait_frame_expression(slot_pointer_expr, runtime),
470
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
471
+ type: @ctx.types.fetch("bool"),
472
+ ),
473
+ ),
474
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "stateful", @ctx.types.fetch("bool")), operator: "=", value: IR::Binary.new(operator: "!=", left: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)), type: @ctx.types.fetch("bool"))),
475
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "state", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr))),
476
+ IR::Assignment.new(target: snapshot_field_expression(snapshots_expr, snapshot_count_expr, runtime, "listener", runtime.fetch(:void_ptr)), operator: "=", value: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:void_ptr))),
477
+ IR::Assignment.new(target: snapshot_count_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
478
+ ]
479
+
480
+ snapshot_subscription_expr = event_subscription_literal(
481
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
482
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
483
+ )
484
+ current_slot_active = event_slot_active_expression(slot_pointer_expr)
485
+ current_slot_generation = event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint"))
486
+ current_wait_frame = event_slot_wait_frame_expression(slot_pointer_expr, runtime)
487
+ wait_slot_condition = IR::Binary.new(
488
+ operator: "and",
489
+ left: current_slot_active,
490
+ right: IR::Binary.new(
491
+ operator: "and",
492
+ left: IR::Binary.new(
493
+ operator: "==",
494
+ left: current_slot_generation,
495
+ right: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "generation", @ctx.types.fetch("ptr_uint")),
496
+ type: @ctx.types.fetch("bool"),
497
+ ),
498
+ right: IR::Binary.new(
499
+ operator: "!=",
500
+ left: current_wait_frame,
501
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
502
+ type: @ctx.types.fetch("bool"),
503
+ ),
504
+ type: @ctx.types.fetch("bool"),
505
+ ),
506
+ type: @ctx.types.fetch("bool"),
507
+ )
508
+
509
+ wait_result_value = event_wait_success_literal(runtime.fetch(:wait_result_type), payload_expr)
510
+ waiter_frame_expr = wait_frame_field_expression(frame_pointer_expr, "waiter_frame", runtime.fetch(:void_ptr))
511
+
512
+ dispatch_body = [
513
+ IR::IfStmt.new(
514
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "wait_slot", @ctx.types.fetch("bool")),
515
+ then_body: [
516
+ IR::LocalDecl.new(
517
+ name: "__mt_slot",
518
+ linkage_name: "__mt_slot",
519
+ type: runtime.fetch(:slot_pointer_type),
520
+ value: event_slot_pointer_expression(
521
+ event_expr,
522
+ snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "slot", @ctx.types.fetch("ptr_uint")),
523
+ runtime,
524
+ ),
525
+ ),
526
+ IR::IfStmt.new(
527
+ condition: wait_slot_condition,
528
+ then_body: [
529
+ IR::LocalDecl.new(
530
+ name: "__mt_wait_frame",
531
+ linkage_name: "__mt_wait_frame",
532
+ type: runtime.fetch(:wait_frame_pointer_type),
533
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: current_wait_frame, type: runtime.fetch(:wait_frame_pointer_type)),
534
+ ),
535
+ IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr)),
536
+ IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "result", runtime.fetch(:wait_result_type)), operator: "=", value: wait_result_value),
537
+ IR::Assignment.new(target: wait_frame_field_expression(frame_pointer_expr, "ready", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
538
+ IR::IfStmt.new(
539
+ condition: IR::Binary.new(
540
+ operator: "!=",
541
+ left: waiter_frame_expr,
542
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
543
+ type: @ctx.types.fetch("bool"),
544
+ ),
545
+ then_body: [
546
+ IR::LocalDecl.new(name: "__mt_waiter_frame", linkage_name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), value: waiter_frame_expr),
547
+ IR::Assignment.new(target: waiter_frame_expr, operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
548
+ IR::ExpressionStmt.new(
549
+ expression: IR::Call.new(
550
+ callee: wait_frame_field_expression(frame_pointer_expr, "waiter", runtime.fetch(:wake_type)),
551
+ arguments: [IR::Name.new(name: "__mt_waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)],
552
+ type: @ctx.types.fetch("void"),
553
+ ),
554
+ ),
555
+ ],
556
+ else_body: nil,
557
+ ),
558
+ ],
559
+ else_body: nil,
560
+ ),
561
+ ],
562
+ else_body: [
563
+ IR::IfStmt.new(
564
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "once", @ctx.types.fetch("bool")),
565
+ then_body: [IR::ExpressionStmt.new(expression: event_unsubscribe_call(runtime, event_expr, snapshot_subscription_expr))],
566
+ else_body: nil,
567
+ ),
568
+ IR::IfStmt.new(
569
+ condition: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "stateful", @ctx.types.fetch("bool")),
570
+ then_body: [
571
+ IR::ExpressionStmt.new(expression: event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
572
+ ],
573
+ else_body: [
574
+ IR::ExpressionStmt.new(expression: event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)),
575
+ ],
576
+ ),
577
+ ],
578
+ ),
579
+ ]
580
+
581
+ body = [
582
+ IR::LocalDecl.new(name: "__mt_snapshots", linkage_name: "__mt_snapshots", type: runtime.fetch(:snapshots_type), value: IR::ZeroInit.new(type: runtime.fetch(:snapshots_type))),
583
+ IR::LocalDecl.new(name: "__mt_snapshot_count", linkage_name: "__mt_snapshot_count", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
584
+ IR::ForStmt.new(
585
+ init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
586
+ condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
587
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
588
+ body: collect_body,
589
+ ),
590
+ IR::ForStmt.new(
591
+ init: IR::LocalDecl.new(name: "__mt_dispatch_index", linkage_name: "__mt_dispatch_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
592
+ condition: IR::Binary.new(operator: "<", left: dispatch_index_expr, right: snapshot_count_expr, type: @ctx.types.fetch("bool")),
593
+ post: IR::Assignment.new(target: dispatch_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
594
+ body: dispatch_body,
595
+ ),
596
+ IR::ReturnStmt.new(value: nil),
597
+ ]
598
+
599
+ params = [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)]
600
+ params << IR::Param.new(name: "payload", linkage_name: "payload", type: runtime.fetch(:event_type).payload_type, pointer: false) if runtime.fetch(:event_type).payload_type
601
+
602
+ IR::Function.new(
603
+ name: "#{runtime.fetch(:emit_linkage_name)}_fn",
604
+ linkage_name: runtime.fetch(:emit_linkage_name),
605
+ params:,
606
+ return_type: @ctx.types.fetch("void"),
607
+ body:,
608
+ entry_point: false,
609
+ )
610
+ end
611
+
612
+ def build_event_wait_ready_function(runtime)
613
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
614
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
615
+
616
+ IR::Function.new(
617
+ name: "#{runtime.fetch(:wait_ready_linkage_name)}_fn",
618
+ linkage_name: runtime.fetch(:wait_ready_linkage_name),
619
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
620
+ return_type: @ctx.types.fetch("bool"),
621
+ body: [
622
+ IR::IfStmt.new(
623
+ condition: IR::Binary.new(
624
+ operator: "==",
625
+ left: raw_frame_expr,
626
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
627
+ type: @ctx.types.fetch("bool"),
628
+ ),
629
+ then_body: [IR::ReturnStmt.new(value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")))],
630
+ else_body: nil,
631
+ ),
632
+ IR::LocalDecl.new(
633
+ name: "__mt_wait_frame",
634
+ linkage_name: "__mt_wait_frame",
635
+ type: runtime.fetch(:wait_frame_pointer_type),
636
+ value: IR::Cast.new(
637
+ target_type: runtime.fetch(:wait_frame_pointer_type),
638
+ expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
639
+ type: runtime.fetch(:wait_frame_pointer_type),
640
+ ),
641
+ ),
642
+ IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool"))),
643
+ ],
644
+ entry_point: false,
645
+ )
646
+ end
647
+
648
+ def build_event_wait_set_waiter_function(runtime)
649
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
650
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
651
+ waiter_frame_expr = IR::Name.new(name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false)
652
+ waiter_expr = IR::Name.new(name: "waiter", type: runtime.fetch(:wake_type), pointer: false)
653
+
654
+ IR::Function.new(
655
+ name: "#{runtime.fetch(:wait_set_waiter_linkage_name)}_fn",
656
+ linkage_name: runtime.fetch(:wait_set_waiter_linkage_name),
657
+ params: [
658
+ IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false),
659
+ IR::Param.new(name: "waiter_frame", linkage_name: "waiter_frame", type: runtime.fetch(:void_ptr), pointer: false),
660
+ IR::Param.new(name: "waiter", linkage_name: "waiter", type: runtime.fetch(:wake_type), pointer: false),
661
+ ],
662
+ return_type: @ctx.types.fetch("void"),
663
+ body: [
664
+ IR::IfStmt.new(
665
+ condition: IR::Binary.new(
666
+ operator: "==",
667
+ left: raw_frame_expr,
668
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
669
+ type: @ctx.types.fetch("bool"),
670
+ ),
671
+ then_body: [
672
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
673
+ IR::ReturnStmt.new(value: nil),
674
+ ],
675
+ else_body: nil,
676
+ ),
677
+ IR::LocalDecl.new(
678
+ name: "__mt_wait_frame",
679
+ linkage_name: "__mt_wait_frame",
680
+ type: runtime.fetch(:wait_frame_pointer_type),
681
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
682
+ ),
683
+ IR::IfStmt.new(
684
+ condition: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")),
685
+ then_body: [
686
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: waiter_expr, arguments: [waiter_frame_expr], type: @ctx.types.fetch("void"))),
687
+ IR::ReturnStmt.new(value: nil),
688
+ ],
689
+ else_body: nil,
690
+ ),
691
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter_frame", runtime.fetch(:void_ptr)), operator: "=", value: waiter_frame_expr),
692
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "waiter", runtime.fetch(:wake_type)), operator: "=", value: waiter_expr),
693
+ IR::ReturnStmt.new(value: nil),
694
+ ],
695
+ entry_point: false,
696
+ )
697
+ end
698
+
699
+ def build_event_wait_release_function(runtime)
700
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
701
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
702
+
703
+ IR::Function.new(
704
+ name: "#{runtime.fetch(:wait_release_linkage_name)}_fn",
705
+ linkage_name: runtime.fetch(:wait_release_linkage_name),
706
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
707
+ return_type: @ctx.types.fetch("void"),
708
+ body: [
709
+ IR::IfStmt.new(
710
+ condition: IR::Binary.new(
711
+ operator: "==",
712
+ left: raw_frame_expr,
713
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
714
+ type: @ctx.types.fetch("bool"),
715
+ ),
716
+ then_body: [IR::ReturnStmt.new(value: nil)],
717
+ else_body: nil,
718
+ ),
719
+ IR::LocalDecl.new(
720
+ name: "__mt_wait_frame",
721
+ linkage_name: "__mt_wait_frame",
722
+ type: runtime.fetch(:wait_frame_pointer_type),
723
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: raw_frame_expr, type: runtime.fetch(:wait_frame_pointer_type)),
724
+ ),
725
+ IR::IfStmt.new(
726
+ condition: IR::Unary.new(operator: "not", operand: wait_frame_field_expression(frame_expr, "ready", @ctx.types.fetch("bool")), type: @ctx.types.fetch("bool")),
727
+ then_body: [
728
+ IR::ExpressionStmt.new(
729
+ expression: event_unsubscribe_call(
730
+ runtime,
731
+ IR::Cast.new(target_type: runtime.fetch(:event_pointer_type), expression: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), type: runtime.fetch(:event_pointer_type)),
732
+ wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")),
733
+ ),
734
+ ),
735
+ ],
736
+ else_body: nil,
737
+ ),
738
+ IR::ExpressionStmt.new(expression: IR::Call.new(callee: "mt_async_free", arguments: [raw_frame_expr], type: @ctx.types.fetch("void"))),
739
+ IR::ReturnStmt.new(value: nil),
740
+ ],
741
+ entry_point: false,
742
+ )
743
+ end
744
+
745
+ def build_event_wait_take_result_function(runtime)
746
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
747
+ raw_frame_expr = IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false)
748
+
749
+ IR::Function.new(
750
+ name: "#{runtime.fetch(:wait_take_result_linkage_name)}_fn",
751
+ linkage_name: runtime.fetch(:wait_take_result_linkage_name),
752
+ params: [IR::Param.new(name: "frame", linkage_name: "frame", type: runtime.fetch(:void_ptr), pointer: false)],
753
+ return_type: runtime.fetch(:wait_result_type),
754
+ body: [
755
+ IR::IfStmt.new(
756
+ condition: IR::Binary.new(
757
+ operator: "==",
758
+ left: raw_frame_expr,
759
+ right: IR::NullLiteral.new(type: runtime.fetch(:void_ptr)),
760
+ type: @ctx.types.fetch("bool"),
761
+ ),
762
+ then_body: [IR::ReturnStmt.new(value: event_failure_literal(runtime.fetch(:wait_result_type)))],
763
+ else_body: nil,
764
+ ),
765
+ IR::LocalDecl.new(
766
+ name: "__mt_wait_frame",
767
+ linkage_name: "__mt_wait_frame",
768
+ type: runtime.fetch(:wait_frame_pointer_type),
769
+ value: IR::Cast.new(target_type: runtime.fetch(:wait_frame_pointer_type), expression: IR::Name.new(name: "frame", type: runtime.fetch(:void_ptr), pointer: false), type: runtime.fetch(:wait_frame_pointer_type)),
770
+ ),
771
+ IR::ReturnStmt.new(value: wait_frame_field_expression(frame_expr, "result", runtime.fetch(:wait_result_type))),
772
+ ],
773
+ entry_point: false,
774
+ )
775
+ end
776
+
777
+ def build_event_wait_function(runtime)
778
+ event_expr = IR::Name.new(name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)
779
+ frame_expr = IR::Name.new(name: "__mt_wait_frame", type: runtime.fetch(:wait_frame_pointer_type), pointer: false)
780
+ raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
781
+ slot_index_expr = IR::Name.new(name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), pointer: false)
782
+ generation_expr = IR::Name.new(name: "__mt_generation", type: @ctx.types.fetch("ptr_uint"), pointer: false)
783
+ slot_pointer_expr = IR::Name.new(name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), pointer: false)
784
+
785
+ body = [
786
+ IR::ForStmt.new(
787
+ init: IR::LocalDecl.new(name: "__mt_slot_index", linkage_name: "__mt_slot_index", type: @ctx.types.fetch("ptr_uint"), value: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("ptr_uint"))),
788
+ condition: IR::Binary.new(operator: "<", left: slot_index_expr, right: IR::IntegerLiteral.new(value: runtime.fetch(:event_type).capacity, type: @ctx.types.fetch("ptr_uint")), type: @ctx.types.fetch("bool")),
789
+ post: IR::Assignment.new(target: slot_index_expr, operator: "+=", value: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint"))),
790
+ body: [
791
+ IR::LocalDecl.new(name: "__mt_slot", linkage_name: "__mt_slot", type: runtime.fetch(:slot_pointer_type), value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime)),
792
+ active_event_slot_continue_guard(slot_pointer_expr),
793
+ IR::LocalDecl.new(
794
+ name: "__mt_generation",
795
+ linkage_name: "__mt_generation",
796
+ type: @ctx.types.fetch("ptr_uint"),
797
+ value: event_next_generation_expression(slot_pointer_expr),
798
+ ),
799
+ IR::LocalDecl.new(
800
+ name: "__mt_wait_frame",
801
+ linkage_name: "__mt_wait_frame",
802
+ type: runtime.fetch(:wait_frame_pointer_type),
803
+ value: IR::Cast.new(
804
+ target_type: runtime.fetch(:wait_frame_pointer_type),
805
+ expression: IR::Call.new(callee: "mt_async_alloc", arguments: [IR::SizeofExpr.new(target_type: runtime.fetch(:wait_frame_type), type: @ctx.types.fetch("ptr_uint"))], type: runtime.fetch(:void_ptr)),
806
+ type: runtime.fetch(:wait_frame_pointer_type),
807
+ ),
808
+ ),
809
+ IR::Assignment.new(
810
+ target: IR::Unary.new(operator: "*", operand: frame_expr, type: runtime.fetch(:wait_frame_type)),
811
+ operator: "=",
812
+ value: IR::ZeroInit.new(type: runtime.fetch(:wait_frame_type)),
813
+ ),
814
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "event", runtime.fetch(:void_ptr)), operator: "=", value: IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: event_expr, type: runtime.fetch(:void_ptr))),
815
+ *event_slot_activate_statements(
816
+ slot_pointer_expr,
817
+ runtime,
818
+ generation_expr: generation_expr,
819
+ once: true,
820
+ wait_frame_expr: raw_frame_expr,
821
+ ),
822
+ IR::Assignment.new(target: wait_frame_field_expression(frame_expr, "subscription", @ctx.types.fetch("Subscription")), operator: "=", value: event_subscription_literal(slot_index_expr, generation_expr)),
823
+ IR::ReturnStmt.new(value: event_task_literal(runtime, frame_expr)),
824
+ ],
825
+ ),
826
+ IR::ReturnStmt.new(value: event_immediate_failure_task_literal(runtime)),
827
+ ]
828
+
829
+ IR::Function.new(
830
+ name: "#{runtime.fetch(:wait_linkage_name)}_fn",
831
+ linkage_name: runtime.fetch(:wait_linkage_name),
832
+ params: [IR::Param.new(name: "event", linkage_name: "event", type: runtime.fetch(:event_pointer_type), pointer: false)],
833
+ return_type: runtime.fetch(:task_type),
834
+ body:,
835
+ entry_point: false,
836
+ )
837
+ end
838
+
839
+ def event_slot_pointer_expression(event_expr, slot_index_expr, runtime)
840
+ IR::AddressOf.new(
841
+ expression: IR::Index.new(
842
+ receiver: IR::Member.new(receiver: event_expr, member: "slots", type: runtime.fetch(:slots_type)),
843
+ index: slot_index_expr,
844
+ type: runtime.fetch(:slot_type),
845
+ ),
846
+ type: runtime.fetch(:slot_pointer_type),
847
+ )
848
+ end
849
+
850
+ def event_slot_local_decl(event_expr, slot_index_expr, runtime, local_name: "__mt_slot")
851
+ IR::LocalDecl.new(
852
+ name: local_name,
853
+ linkage_name: local_name,
854
+ type: runtime.fetch(:slot_pointer_type),
855
+ value: event_slot_pointer_expression(event_expr, slot_index_expr, runtime),
856
+ )
857
+ end
858
+
859
+ def event_slot_active_expression(slot_pointer_expr)
860
+ event_slot_field_expression(slot_pointer_expr, "active", @ctx.types.fetch("bool"))
861
+ end
862
+
863
+ def event_slot_wait_frame_expression(slot_pointer_expr, runtime)
864
+ event_slot_field_expression(slot_pointer_expr, "wait_frame", runtime.fetch(:void_ptr))
865
+ end
866
+
867
+ def active_event_slot_continue_guard(slot_pointer_expr)
868
+ IR::IfStmt.new(
869
+ condition: event_slot_active_expression(slot_pointer_expr),
870
+ then_body: [IR::ContinueStmt.new],
871
+ else_body: nil,
872
+ )
873
+ end
874
+
875
+ def inactive_event_slot_continue_guard(slot_pointer_expr)
876
+ IR::IfStmt.new(
877
+ condition: IR::Unary.new(operator: "not", operand: event_slot_active_expression(slot_pointer_expr), type: @ctx.types.fetch("bool")),
878
+ then_body: [IR::ContinueStmt.new],
879
+ else_body: nil,
880
+ )
881
+ end
882
+
883
+ def event_next_generation_expression(slot_pointer_expr)
884
+ IR::Binary.new(
885
+ operator: "+",
886
+ left: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")),
887
+ right: IR::IntegerLiteral.new(value: 1, type: @ctx.types.fetch("ptr_uint")),
888
+ type: @ctx.types.fetch("ptr_uint"),
889
+ )
890
+ end
891
+
892
+ def event_slot_activate_statements(slot_pointer_expr, runtime, generation_expr:, once:, wait_frame_expr:, listener_expr: nil)
893
+ statements = [
894
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
895
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
896
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
897
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
898
+ ]
899
+ statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
900
+ statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
901
+ statements
902
+ end
903
+
904
+ def event_slot_activate_stateful_statements(slot_pointer_expr, runtime, generation_expr:, once:, state_expr:, wait_frame_expr:, listener_expr: nil)
905
+ statements = [
906
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool"))),
907
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: once, type: @ctx.types.fetch("bool"))),
908
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "generation", @ctx.types.fetch("ptr_uint")), operator: "=", value: generation_expr),
909
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "state", runtime.fetch(:void_ptr)), operator: "=", value: state_expr),
910
+ ]
911
+ statements << IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "listener", runtime.fetch(:listener_type)), operator: "=", value: listener_expr) if listener_expr
912
+ statements << IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: wait_frame_expr)
913
+ statements
914
+ end
915
+
916
+ def event_slot_clear_statements(slot_pointer_expr, runtime)
917
+ [
918
+ IR::Assignment.new(target: event_slot_active_expression(slot_pointer_expr), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
919
+ IR::Assignment.new(target: event_slot_field_expression(slot_pointer_expr, "once", @ctx.types.fetch("bool")), operator: "=", value: IR::BooleanLiteral.new(value: false, type: @ctx.types.fetch("bool"))),
920
+ IR::Assignment.new(target: event_slot_wait_frame_expression(slot_pointer_expr, runtime), operator: "=", value: IR::NullLiteral.new(type: runtime.fetch(:void_ptr))),
921
+ ]
922
+ end
923
+
924
+ def event_slot_field_expression(slot_pointer_expr, field_name, field_type)
925
+ IR::Member.new(receiver: slot_pointer_expr, member: field_name, type: field_type)
926
+ end
927
+
928
+ def snapshot_field_expression(snapshots_expr, index_expr, runtime, field_name, field_type)
929
+ IR::Member.new(
930
+ receiver: IR::Index.new(receiver: snapshots_expr, index: index_expr, type: runtime.fetch(:snapshot_type)),
931
+ member: field_name,
932
+ type: field_type,
933
+ )
934
+ end
935
+
936
+ def subscription_field_expression(subscription_expr, field_name, field_type)
937
+ IR::Member.new(receiver: subscription_expr, member: field_name, type: field_type)
938
+ end
939
+
940
+ def wait_frame_field_expression(frame_expr, field_name, field_type)
941
+ IR::Member.new(receiver: frame_expr, member: field_name, type: field_type)
942
+ end
943
+
944
+ def event_subscription_literal(slot_expr, generation_expr)
945
+ IR::AggregateLiteral.new(
946
+ type: @ctx.types.fetch("Subscription"),
947
+ fields: [
948
+ IR::AggregateField.new(name: "slot", value: slot_expr),
949
+ IR::AggregateField.new(name: "generation", value: generation_expr),
950
+ ],
951
+ )
952
+ end
953
+
954
+ def event_subscription_success_literal(result_type, slot_expr, generation_expr)
955
+ IR::VariantLiteral.new(
956
+ type: result_type,
957
+ arm_name: "success",
958
+ fields: [IR::AggregateField.new(name: "value", value: event_subscription_literal(slot_expr, generation_expr))],
959
+ )
960
+ end
961
+
962
+ def event_wait_success_literal(result_type, payload_expr)
963
+ IR::VariantLiteral.new(
964
+ type: result_type,
965
+ arm_name: "success",
966
+ fields: [IR::AggregateField.new(name: "value", value: payload_expr || void_value_expression)],
967
+ )
968
+ end
969
+
970
+ def event_failure_literal(result_type)
971
+ IR::VariantLiteral.new(
972
+ type: result_type,
973
+ arm_name: "failure",
974
+ fields: [
975
+ IR::AggregateField.new(
976
+ name: "error",
977
+ value: IR::Name.new(name: enum_member_c_name(@ctx.types.fetch("EventError"), "full"), type: @ctx.types.fetch("EventError"), pointer: false),
978
+ ),
979
+ ],
980
+ )
981
+ end
982
+
983
+ def void_value_expression
984
+ IR::Cast.new(
985
+ target_type: @ctx.types.fetch("void"),
986
+ expression: IR::IntegerLiteral.new(value: 0, type: @ctx.types.fetch("int")),
987
+ type: @ctx.types.fetch("void"),
988
+ )
989
+ end
990
+
991
+ def event_unsubscribe_call(runtime, event_expr, subscription_expr)
992
+ IR::Call.new(
993
+ callee: runtime.fetch(:unsubscribe_linkage_name),
994
+ arguments: [event_expr, subscription_expr],
995
+ type: @ctx.types.fetch("void"),
996
+ )
997
+ end
998
+
999
+ def event_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
1000
+ listener_type = runtime.fetch(:listener_type)
1001
+ listener_expr = IR::Cast.new(
1002
+ target_type: listener_type,
1003
+ expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1004
+ type: listener_type,
1005
+ )
1006
+ arguments = []
1007
+ arguments << payload_expr if runtime.fetch(:event_type).payload_type
1008
+ IR::Call.new(
1009
+ callee: listener_expr,
1010
+ arguments:,
1011
+ type: @ctx.types.fetch("void"),
1012
+ )
1013
+ end
1014
+
1015
+ def event_stateful_listener_call_expression(runtime, snapshots_expr, dispatch_index_expr, payload_expr)
1016
+ listener_type = runtime.fetch(:stateful_listener_type)
1017
+ listener_expr = IR::Cast.new(
1018
+ target_type: listener_type,
1019
+ expression: snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "listener", runtime.fetch(:void_ptr)),
1020
+ type: listener_type,
1021
+ )
1022
+ state_expr = snapshot_field_expression(snapshots_expr, dispatch_index_expr, runtime, "state", runtime.fetch(:void_ptr))
1023
+ arguments = [state_expr]
1024
+ arguments << payload_expr if runtime.fetch(:event_type).payload_type
1025
+ IR::Call.new(
1026
+ callee: listener_expr,
1027
+ arguments:,
1028
+ type: @ctx.types.fetch("void"),
1029
+ )
1030
+ end
1031
+
1032
+ def event_task_literal(runtime, frame_expr)
1033
+ raw_frame_expr = IR::Cast.new(target_type: runtime.fetch(:void_ptr), expression: frame_expr, type: runtime.fetch(:void_ptr))
1034
+ event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1035
+ end
1036
+
1037
+ def event_immediate_failure_task_literal(runtime)
1038
+ event_task_literal_from_raw_frame(runtime, IR::NullLiteral.new(type: runtime.fetch(:void_ptr)))
1039
+ end
1040
+
1041
+ def event_task_literal_from_raw_frame(runtime, raw_frame_expr)
1042
+ IR::AggregateLiteral.new(
1043
+ type: runtime.fetch(:task_type),
1044
+ fields: [
1045
+ IR::AggregateField.new(name: "frame", value: raw_frame_expr),
1046
+ IR::AggregateField.new(name: "ready", value: IR::Name.new(name: runtime.fetch(:wait_ready_linkage_name), type: runtime.fetch(:task_type).field("ready"), pointer: false)),
1047
+ IR::AggregateField.new(name: "set_waiter", value: IR::Name.new(name: runtime.fetch(:wait_set_waiter_linkage_name), type: runtime.fetch(:task_type).field("set_waiter"), pointer: false)),
1048
+ IR::AggregateField.new(name: "release", value: IR::Name.new(name: runtime.fetch(:wait_release_linkage_name), type: runtime.fetch(:task_type).field("release"), pointer: false)),
1049
+ IR::AggregateField.new(name: "take_result", value: IR::Name.new(name: runtime.fetch(:wait_take_result_linkage_name), type: runtime.fetch(:task_type).field("take_result"), pointer: false)),
1050
+ ],
1051
+ )
1052
+ end
1053
+ end
1054
+ end