mt-lang 0.3.24 → 0.3.26

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