mt-lang 0.3.4 → 0.3.5
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.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/c_backend/feature_detection.rb +27 -55
- data/lib/milk_tea/core/c_backend/format_helpers.rb +551 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +0 -542
- data/lib/milk_tea/core/c_backend/type_collectors.rb +51 -204
- data/lib/milk_tea/core/c_backend.rb +2 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +1 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +147 -141
- data/lib/milk_tea/core/lowering/block.rb +759 -725
- data/lib/milk_tea/core/lowering/expressions.rb +94 -0
- data/lib/milk_tea/core/lowering/loops.rb +49 -0
- data/lib/milk_tea/core/lowering/resolve.rb +221 -214
- data/lib/milk_tea/core/lowering/utils.rb +0 -222
- data/lib/milk_tea/core/module_loader.rb +29 -48
- data/lib/milk_tea/core/parser/declarations.rb +2 -2
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +3 -120
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +116 -113
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +346 -343
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +37 -12
- data/lib/milk_tea/core/types/predicates.rb +501 -499
- data/lib/milk_tea/core/types/visitor.rb +1 -1
- metadata +3 -2
|
@@ -150,28 +150,16 @@ module MilkTea
|
|
|
150
150
|
projection: :result_failure_error,
|
|
151
151
|
)
|
|
152
152
|
end
|
|
153
|
-
else_body =
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
)
|
|
164
|
-
else
|
|
165
|
-
lower_async_non_await_statements(
|
|
166
|
-
statement.else_body,
|
|
167
|
-
env: else_env,
|
|
168
|
-
frame_expr:,
|
|
169
|
-
raw_frame_expr:,
|
|
170
|
-
async_info:,
|
|
171
|
-
active_defers:,
|
|
172
|
-
loop_flow:,
|
|
173
|
-
)
|
|
174
|
-
end
|
|
153
|
+
else_body = lower_async_body(
|
|
154
|
+
statement.else_body,
|
|
155
|
+
env: else_env,
|
|
156
|
+
frame_expr:,
|
|
157
|
+
raw_frame_expr:,
|
|
158
|
+
resume_linkage_name:,
|
|
159
|
+
async_info:,
|
|
160
|
+
active_defers:,
|
|
161
|
+
loop_flow:,
|
|
162
|
+
)
|
|
175
163
|
lowered << IR::IfStmt.new(
|
|
176
164
|
condition: let_else_failure_condition(target, storage_type),
|
|
177
165
|
then_body: else_body,
|
|
@@ -214,6 +202,35 @@ module MilkTea
|
|
|
214
202
|
end
|
|
215
203
|
end
|
|
216
204
|
|
|
205
|
+
def lower_async_body(body, env:, frame_expr:, raw_frame_expr:, async_info:, resume_linkage_name: nil, active_defers: [], loop_flow: nil)
|
|
206
|
+
if statements_contain_await?(body, async_info)
|
|
207
|
+
lower_async_cf_statements(body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow:)
|
|
208
|
+
else
|
|
209
|
+
lower_async_non_await_statements(body, env:, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow:)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def build_async_while_with_condition_setup(condition_setup, condition, body, break_label)
|
|
214
|
+
if condition_setup.empty?
|
|
215
|
+
stmts = [IR::WhileStmt.new(condition:, body:)]
|
|
216
|
+
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(body, break_label)
|
|
217
|
+
return stmts
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
loop_body = [
|
|
221
|
+
*condition_setup,
|
|
222
|
+
IR::IfStmt.new(
|
|
223
|
+
condition: IR::Unary.new(operator: "not", operand: condition, type: @ctx.types.fetch("bool")),
|
|
224
|
+
then_body: [loop_exit_statement(loop_exit_break(break_label), local_defers: [], outer_defers: [])],
|
|
225
|
+
else_body: nil,
|
|
226
|
+
),
|
|
227
|
+
*body,
|
|
228
|
+
]
|
|
229
|
+
stmts = [IR::WhileStmt.new(condition: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")), body: loop_body)]
|
|
230
|
+
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(loop_body, break_label)
|
|
231
|
+
stmts
|
|
232
|
+
end
|
|
233
|
+
|
|
217
234
|
# Lower a list of statements that MAY contain await expressions inside nested control flow.
|
|
218
235
|
# CPS-via-goto: labels placed inside if/while/match bodies, reachable from top-level switch dispatch.
|
|
219
236
|
def lower_async_cf_statements(statements, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers: [], loop_flow: nil)
|
|
@@ -304,20 +321,12 @@ module MilkTea
|
|
|
304
321
|
branch_entries = statement.branches.map do |branch|
|
|
305
322
|
condition_setup, prepared_cond = prepare_expression_for_inline_lowering(branch.condition, env:)
|
|
306
323
|
condition = lower_contextual_expression(prepared_cond, env:, expected_type: @ctx.types.fetch("bool"))
|
|
307
|
-
body =
|
|
308
|
-
lower_async_cf_statements(branch.body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow:)
|
|
309
|
-
else
|
|
310
|
-
lower_async_non_await_statements(branch.body, env:, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow:)
|
|
311
|
-
end
|
|
324
|
+
body = lower_async_body(branch.body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow:)
|
|
312
325
|
{ condition_setup:, condition:, body: }
|
|
313
326
|
end
|
|
314
327
|
|
|
315
328
|
else_body = if statement.else_body
|
|
316
|
-
|
|
317
|
-
lower_async_cf_statements(statement.else_body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow:)
|
|
318
|
-
else
|
|
319
|
-
lower_async_non_await_statements(statement.else_body, env:, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow:)
|
|
320
|
-
end
|
|
329
|
+
lower_async_body(statement.else_body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow:)
|
|
321
330
|
end
|
|
322
331
|
|
|
323
332
|
nested_else = else_body
|
|
@@ -336,31 +345,10 @@ module MilkTea
|
|
|
336
345
|
condition_setup, prepared_cond = prepare_expression_for_inline_lowering(statement.condition, env:)
|
|
337
346
|
condition = lower_contextual_expression(prepared_cond, env:, expected_type: @ctx.types.fetch("bool"))
|
|
338
347
|
inner_loop_flow = loop_flow(break_target: loop_exit_break(break_label), continue_target: loop_exit_continue(continue_label))
|
|
339
|
-
body =
|
|
340
|
-
lower_async_cf_statements(statement.body, env: duplicate_env(env), frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
341
|
-
else
|
|
342
|
-
lower_async_non_await_statements(statement.body, env: duplicate_env(env), frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
343
|
-
end
|
|
348
|
+
body = lower_async_body(statement.body, env: duplicate_env(env), frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
344
349
|
body << IR::LabelStmt.new(name: continue_label) if contains_label_target?(body, continue_label)
|
|
345
350
|
|
|
346
|
-
|
|
347
|
-
stmts = [IR::WhileStmt.new(condition:, body:)]
|
|
348
|
-
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(body, break_label)
|
|
349
|
-
return stmts
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
loop_body = [
|
|
353
|
-
*condition_setup,
|
|
354
|
-
IR::IfStmt.new(
|
|
355
|
-
condition: IR::Unary.new(operator: "not", operand: condition, type: @ctx.types.fetch("bool")),
|
|
356
|
-
then_body: [loop_exit_statement(loop_exit_break(break_label), local_defers: [], outer_defers: [])],
|
|
357
|
-
else_body: nil,
|
|
358
|
-
),
|
|
359
|
-
*body,
|
|
360
|
-
]
|
|
361
|
-
stmts = [IR::WhileStmt.new(condition: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")), body: loop_body)]
|
|
362
|
-
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(loop_body, break_label)
|
|
363
|
-
stmts
|
|
351
|
+
build_async_while_with_condition_setup(condition_setup, condition, body, break_label)
|
|
364
352
|
end
|
|
365
353
|
|
|
366
354
|
def lower_async_cf_for_stmt(statement, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:)
|
|
@@ -405,11 +393,7 @@ module MilkTea
|
|
|
405
393
|
)
|
|
406
394
|
inner_loop_flow = loop_flow(break_target: loop_exit_break(break_label), continue_target: loop_exit_continue(continue_label))
|
|
407
395
|
|
|
408
|
-
body =
|
|
409
|
-
lower_async_cf_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
410
|
-
else
|
|
411
|
-
lower_async_non_await_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
412
|
-
end
|
|
396
|
+
body = lower_async_body(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
413
397
|
body << IR::LabelStmt.new(name: continue_label) if contains_label_target?(body, continue_label)
|
|
414
398
|
|
|
415
399
|
cmp_op = inclusive ? "<=" : "<"
|
|
@@ -461,11 +445,7 @@ module MilkTea
|
|
|
461
445
|
inner_loop_flow = loop_flow(break_target: loop_exit_break(break_label), continue_target: loop_exit_continue(continue_label))
|
|
462
446
|
|
|
463
447
|
assign_item = IR::Assignment.new(target: loop_var_expr, operator: "=", value: item_value)
|
|
464
|
-
body_stmts =
|
|
465
|
-
lower_async_cf_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
466
|
-
else
|
|
467
|
-
lower_async_non_await_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
468
|
-
end
|
|
448
|
+
body_stmts = lower_async_body(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
469
449
|
body_stmts << IR::LabelStmt.new(name: continue_label) if contains_label_target?(body_stmts, continue_label)
|
|
470
450
|
|
|
471
451
|
stmts = [
|
|
@@ -533,11 +513,7 @@ module MilkTea
|
|
|
533
513
|
IR::Assignment.new(target: binding_target, operator: "=", value: loop_item_value)
|
|
534
514
|
end
|
|
535
515
|
inner_loop_flow = loop_flow(break_target: loop_exit_break(break_label), continue_target: loop_exit_continue(continue_label))
|
|
536
|
-
body_stmts =
|
|
537
|
-
lower_async_cf_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
538
|
-
else
|
|
539
|
-
lower_async_non_await_statements(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
540
|
-
end
|
|
516
|
+
body_stmts = lower_async_body(statement.body, env: inner_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: inner_loop_flow)
|
|
541
517
|
body_stmts << IR::LabelStmt.new(name: continue_label) if contains_label_target?(body_stmts, continue_label)
|
|
542
518
|
|
|
543
519
|
length_checks = iterable_entries.drop(1).each_with_index.map do |entry, offset|
|
|
@@ -593,11 +569,7 @@ module MilkTea
|
|
|
593
569
|
kind_expr = IR::Member.new(receiver: match_expr, member: "kind", type: kind_type)
|
|
594
570
|
cases = statement.arms.map do |arm|
|
|
595
571
|
arm_env, binding_decl = async_variant_match_arm_binding(arm, match_expr, match_type, env:, frame_expr:, local_fields: async_info[:local_fields])
|
|
596
|
-
arm_body =
|
|
597
|
-
lower_async_cf_statements(arm.body, env: arm_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
598
|
-
else
|
|
599
|
-
lower_async_non_await_statements(arm.body, env: arm_env, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
600
|
-
end
|
|
572
|
+
arm_body = lower_async_body(arm.body, env: arm_env, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
601
573
|
body = [binding_decl, *arm_body].compact + [IR::BreakStmt.new]
|
|
602
574
|
if wildcard_arm_pattern?(arm.pattern)
|
|
603
575
|
IR::SwitchDefaultCase.new(body: body)
|
|
@@ -611,11 +583,7 @@ module MilkTea
|
|
|
611
583
|
end
|
|
612
584
|
|
|
613
585
|
cases = statement.arms.map do |arm|
|
|
614
|
-
arm_body =
|
|
615
|
-
lower_async_cf_statements(arm.body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
616
|
-
else
|
|
617
|
-
lower_async_non_await_statements(arm.body, env:, frame_expr:, raw_frame_expr:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
618
|
-
end
|
|
586
|
+
arm_body = lower_async_body(arm.body, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:, loop_flow: arm_loop_flow)
|
|
619
587
|
if wildcard_arm_pattern?(arm.pattern)
|
|
620
588
|
IR::SwitchDefaultCase.new(body: arm_body + [IR::BreakStmt.new])
|
|
621
589
|
else
|
|
@@ -804,23 +772,7 @@ module MilkTea
|
|
|
804
772
|
body << IR::LabelStmt.new(name: continue_label) if contains_label_target?(body, continue_label)
|
|
805
773
|
cond = lower_expression(prepared_cond, env:, expected_type: @ctx.types.fetch("bool"))
|
|
806
774
|
|
|
807
|
-
|
|
808
|
-
stmts = [IR::WhileStmt.new(condition: cond, body:)]
|
|
809
|
-
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(body, break_label)
|
|
810
|
-
return IR::BlockStmt.new(body: stmts)
|
|
811
|
-
end
|
|
812
|
-
|
|
813
|
-
loop_body = [
|
|
814
|
-
*condition_setup,
|
|
815
|
-
IR::IfStmt.new(
|
|
816
|
-
condition: IR::Unary.new(operator: "not", operand: cond, type: @ctx.types.fetch("bool")),
|
|
817
|
-
then_body: [loop_exit_statement(loop_exit_break(break_label), local_defers: [], outer_defers: [])],
|
|
818
|
-
else_body: nil,
|
|
819
|
-
),
|
|
820
|
-
*body,
|
|
821
|
-
]
|
|
822
|
-
stmts = [IR::WhileStmt.new(condition: IR::BooleanLiteral.new(value: true, type: @ctx.types.fetch("bool")), body: loop_body)]
|
|
823
|
-
stmts << IR::LabelStmt.new(name: break_label) if contains_label_target?(loop_body, break_label)
|
|
775
|
+
stmts = build_async_while_with_condition_setup(condition_setup, cond, body, break_label)
|
|
824
776
|
IR::BlockStmt.new(body: stmts)
|
|
825
777
|
end
|
|
826
778
|
|
|
@@ -1242,28 +1194,16 @@ module MilkTea
|
|
|
1242
1194
|
projection: :result_failure_error,
|
|
1243
1195
|
)
|
|
1244
1196
|
end
|
|
1245
|
-
else_body =
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
)
|
|
1256
|
-
else
|
|
1257
|
-
lower_async_non_await_statements(
|
|
1258
|
-
statement.else_body,
|
|
1259
|
-
env: else_env,
|
|
1260
|
-
frame_expr:,
|
|
1261
|
-
raw_frame_expr:,
|
|
1262
|
-
async_info:,
|
|
1263
|
-
active_defers:,
|
|
1264
|
-
loop_flow:,
|
|
1265
|
-
)
|
|
1266
|
-
end
|
|
1197
|
+
else_body = lower_async_body(
|
|
1198
|
+
statement.else_body,
|
|
1199
|
+
env: else_env,
|
|
1200
|
+
frame_expr:,
|
|
1201
|
+
raw_frame_expr:,
|
|
1202
|
+
resume_linkage_name:,
|
|
1203
|
+
async_info:,
|
|
1204
|
+
active_defers:,
|
|
1205
|
+
loop_flow:,
|
|
1206
|
+
)
|
|
1267
1207
|
lowered << IR::IfStmt.new(
|
|
1268
1208
|
condition: let_else_failure_condition(target, storage_type),
|
|
1269
1209
|
then_body: else_body,
|
|
@@ -1315,28 +1255,16 @@ module MilkTea
|
|
|
1315
1255
|
next [] if cleanup_entry[:body].empty?
|
|
1316
1256
|
|
|
1317
1257
|
cleanup_env = duplicate_env(cleanup_entry[:env])
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
)
|
|
1329
|
-
else
|
|
1330
|
-
lower_async_non_await_statements(
|
|
1331
|
-
cleanup_entry[:body],
|
|
1332
|
-
env: cleanup_env,
|
|
1333
|
-
frame_expr:,
|
|
1334
|
-
raw_frame_expr:,
|
|
1335
|
-
async_info:,
|
|
1336
|
-
active_defers: [],
|
|
1337
|
-
loop_flow: nil,
|
|
1338
|
-
)
|
|
1339
|
-
end
|
|
1258
|
+
lower_async_body(
|
|
1259
|
+
cleanup_entry[:body],
|
|
1260
|
+
env: cleanup_env,
|
|
1261
|
+
frame_expr:,
|
|
1262
|
+
raw_frame_expr:,
|
|
1263
|
+
resume_linkage_name: async_info.fetch(:resume_linkage_name),
|
|
1264
|
+
async_info:,
|
|
1265
|
+
active_defers: [],
|
|
1266
|
+
loop_flow: nil,
|
|
1267
|
+
)
|
|
1340
1268
|
end
|
|
1341
1269
|
end
|
|
1342
1270
|
|
|
@@ -1403,5 +1331,83 @@ module MilkTea
|
|
|
1403
1331
|
lowered << IR::ReturnStmt.new(value: nil)
|
|
1404
1332
|
lowered
|
|
1405
1333
|
end
|
|
1334
|
+
|
|
1335
|
+
def async_variant_match_arm_binding(arm, scrutinee_expr, scrutinee_type, env:, frame_expr: nil, local_fields: nil)
|
|
1336
|
+
arm_env = duplicate_env(env)
|
|
1337
|
+
binding_decl = nil
|
|
1338
|
+
|
|
1339
|
+
if arm.binding_name && !wildcard_arm_pattern?(arm.pattern)
|
|
1340
|
+
arm_name = variant_match_arm_name_from_pattern(arm.pattern)
|
|
1341
|
+
if arm_name && scrutinee_type.has_payload?(arm_name)
|
|
1342
|
+
fields = scrutinee_type.arm(arm_name)
|
|
1343
|
+
payload_type = Types::VariantArmPayload.new(scrutinee_type, arm_name, fields)
|
|
1344
|
+
|
|
1345
|
+
field_key = async_match_binding_field_key(arm)
|
|
1346
|
+
field_info = local_fields&.fetch(field_key, nil)
|
|
1347
|
+
if field_info && frame_expr
|
|
1348
|
+
target = async_frame_field_expression(frame_expr, field_info[:field_name], field_info[:storage_type])
|
|
1349
|
+
binding_c = async_frame_field_c_name(field_info[:field_name])
|
|
1350
|
+
arm_env[:scopes].last[arm.binding_name] = local_binding(type: payload_type, linkage_name: binding_c, mutable: false, pointer: false)
|
|
1351
|
+
data_expr = IR::Member.new(receiver: scrutinee_expr, member: "data", type: nil)
|
|
1352
|
+
arm_expr = IR::Member.new(receiver: data_expr, member: arm_name, type: payload_type)
|
|
1353
|
+
binding_decl = IR::Assignment.new(target:, operator: "=", value: arm_expr)
|
|
1354
|
+
else
|
|
1355
|
+
data_expr = IR::Member.new(receiver: scrutinee_expr, member: "data", type: nil)
|
|
1356
|
+
arm_expr = IR::Member.new(receiver: data_expr, member: arm_name, type: payload_type)
|
|
1357
|
+
binding_c = c_local_name(arm.binding_name)
|
|
1358
|
+
arm_env[:scopes].last[arm.binding_name] = local_binding(type: payload_type, linkage_name: binding_c, mutable: false, pointer: false)
|
|
1359
|
+
binding_decl = IR::LocalDecl.new(name: arm.binding_name, linkage_name: binding_c, type: payload_type, value: arm_expr)
|
|
1360
|
+
end
|
|
1361
|
+
end
|
|
1362
|
+
end
|
|
1363
|
+
|
|
1364
|
+
[arm_env, binding_decl]
|
|
1365
|
+
end
|
|
1366
|
+
|
|
1367
|
+
def bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
|
|
1368
|
+
return unless scrutinee_type.is_a?(Types::Variant)
|
|
1369
|
+
return unless arm.binding_name && !wildcard_arm_pattern?(arm.pattern)
|
|
1370
|
+
|
|
1371
|
+
arm_name = variant_match_arm_name_from_pattern(arm.pattern)
|
|
1372
|
+
return unless arm_name && scrutinee_type.has_payload?(arm_name)
|
|
1373
|
+
|
|
1374
|
+
fields = scrutinee_type.arm(arm_name)
|
|
1375
|
+
payload_type = Types::VariantArmPayload.new(scrutinee_type, arm_name, fields)
|
|
1376
|
+
arm_env[:scopes].last[arm.binding_name] = local_binding(type: payload_type, linkage_name: c_local_name(arm.binding_name), mutable: true, pointer: false)
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
def lower_async_loop_exit(target, local_defers, outer_defers, frame_expr:, raw_frame_expr:, async_info:)
|
|
1380
|
+
cleanup = lower_async_cleanup_entries(local_defers, outer_defers, frame_expr:, raw_frame_expr:, async_info:)
|
|
1381
|
+
if cleanup.empty?
|
|
1382
|
+
[loop_exit_statement(target, local_defers:, outer_defers:)]
|
|
1383
|
+
else
|
|
1384
|
+
label = target[:label]
|
|
1385
|
+
raise LoweringError, "structured loop exits with cleanup are unsupported" unless label
|
|
1386
|
+
|
|
1387
|
+
cleanup + [IR::GotoStmt.new(label:)]
|
|
1388
|
+
end
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
def async_local_decl_field_key(statement)
|
|
1392
|
+
return "__discard_#{statement.line}" if statement.name == "_"
|
|
1393
|
+
|
|
1394
|
+
statement.name
|
|
1395
|
+
end
|
|
1396
|
+
|
|
1397
|
+
def async_local_decl_field_name(statement)
|
|
1398
|
+
return "local_discard_#{statement.line}" if statement.name == "_"
|
|
1399
|
+
|
|
1400
|
+
"local_#{statement.name}"
|
|
1401
|
+
end
|
|
1402
|
+
|
|
1403
|
+
def async_match_binding_field_key(arm)
|
|
1404
|
+
@async_binding_counter ||= 0
|
|
1405
|
+
@async_binding_counter += 1
|
|
1406
|
+
"match_binding_#{@async_binding_counter}"
|
|
1407
|
+
end
|
|
1408
|
+
|
|
1409
|
+
def async_match_binding_field_name(arm)
|
|
1410
|
+
"local_match_binding_#{@async_binding_counter}"
|
|
1411
|
+
end
|
|
1406
1412
|
end
|
|
1407
1413
|
end
|