mt-lang 0.3.23 → 0.3.25

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 (85) 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 +2 -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 +965 -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/linter/flow_rules.rb +3 -3
  82. metadata +4 -5
  83. data/lib/milk_tea/core/cst_builder.rb +0 -19
  84. data/lib/milk_tea/core/lowering/async/lowering.rb +0 -1404
  85. data/lib/milk_tea/core/token_stream.rb +0 -30
@@ -1,456 +1,458 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MilkTea
4
- module LowererAsync
5
- def normalize_async_body(binding, statements)
6
- counter = { value: 0 }
7
- env = empty_env
8
- binding.body_params.each do |param_binding|
9
- env[:scopes].last[param_binding.name] = local_binding(
10
- type: param_binding.type,
11
- linkage_name: param_binding.name,
12
- mutable: param_binding.mutable,
13
- pointer: false,
14
- )
4
+ module Lowering
5
+ module Async
6
+ def normalize_async_body(binding, statements)
7
+ counter = { value: 0 }
8
+ env = empty_env
9
+ binding.body_params.each do |param_binding|
10
+ env[:scopes].last[param_binding.name] = local_binding(
11
+ type: param_binding.type,
12
+ linkage_name: param_binding.name,
13
+ mutable: param_binding.mutable,
14
+ pointer: false,
15
+ )
16
+ end
17
+ env[:return_context] = {
18
+ return_type: binding.body_return_type,
19
+ active_defers: [],
20
+ local_defers: [],
21
+ allow_return: true,
22
+ }
23
+ normalize_async_statements(statements, counter, env, return_type: binding.body_return_type)
15
24
  end
16
- env[:return_context] = {
17
- return_type: binding.body_return_type,
18
- active_defers: [],
19
- local_defers: [],
20
- allow_return: true,
21
- }
22
- normalize_async_statements(statements, counter, env, return_type: binding.body_return_type)
23
- end
24
25
 
25
- def normalize_async_statements(statements, counter, env, return_type:)
26
- statements.flat_map { |statement| normalize_async_statement(statement, counter, env, return_type:) }
27
- end
26
+ def normalize_async_statements(statements, counter, env, return_type:)
27
+ statements.flat_map { |statement| normalize_async_statement(statement, counter, env, return_type:) }
28
+ end
28
29
 
29
- def normalize_async_statement(statement, counter, env, return_type:)
30
- case statement
31
- when AST::LocalDecl
32
- if statement.value
33
- local_type, storage_type = async_local_decl_types(statement, env:)
34
- expected_type = statement.else_body ? storage_type : (statement.type ? resolve_type_ref(statement.type) : nil)
35
- setup, value = if statement.value.is_a?(AST::AwaitExpr)
36
- inner_setup, inner_expr = normalize_async_expression(statement.value.expression, counter, env:, expected_type: expected_type)
37
- [inner_setup, AST::AwaitExpr.new(expression: inner_expr)]
38
- else
39
- normalize_async_expression(statement.value, counter, env:, expected_type: expected_type)
40
- end
41
- else_body = if statement.else_body
42
- else_env = duplicate_env(env)
43
- normalize_async_statements(statement.else_body, counter, else_env, return_type:)
44
- end
45
- normalized = AST::LocalDecl.new(kind: statement.kind, name: statement.name, type: statement.type, value: value, else_binding: statement.else_binding, else_body:, line: statement.line)
46
- if bind_let_else_local?(statement)
47
- current_actual_scope(env[:scopes])[statement.name] = local_binding(
48
- type: local_type,
49
- storage_type:,
50
- linkage_name: statement.name,
51
- mutable: statement.kind == :var,
52
- pointer: false,
53
- projection: statement.else_body ? let_else_binding_projection(storage_type) : nil,
54
- const_value: statement.else_body ? nil : statement.kind == :let ? compile_time_const_value(statement.value, env:) : nil,
55
- )
30
+ def normalize_async_statement(statement, counter, env, return_type:)
31
+ case statement
32
+ when AST::LocalDecl
33
+ if statement.value
34
+ local_type, storage_type = async_local_decl_types(statement, env:)
35
+ expected_type = statement.else_body ? storage_type : (statement.type ? resolve_type_ref(statement.type) : nil)
36
+ setup, value = if statement.value.is_a?(AST::AwaitExpr)
37
+ inner_setup, inner_expr = normalize_async_expression(statement.value.expression, counter, env:, expected_type: expected_type)
38
+ [inner_setup, AST::AwaitExpr.new(expression: inner_expr)]
39
+ else
40
+ normalize_async_expression(statement.value, counter, env:, expected_type: expected_type)
41
+ end
42
+ else_body = if statement.else_body
43
+ else_env = duplicate_env(env)
44
+ normalize_async_statements(statement.else_body, counter, else_env, return_type:)
45
+ end
46
+ normalized = AST::LocalDecl.new(kind: statement.kind, name: statement.name, type: statement.type, value: value, else_binding: statement.else_binding, else_body:, line: statement.line)
47
+ if bind_let_else_local?(statement)
48
+ current_actual_scope(env[:scopes])[statement.name] = local_binding(
49
+ type: local_type,
50
+ storage_type:,
51
+ linkage_name: statement.name,
52
+ mutable: statement.kind == :var,
53
+ pointer: false,
54
+ projection: statement.else_body ? let_else_binding_projection(storage_type) : nil,
55
+ const_value: statement.else_body ? nil : statement.kind == :let ? compile_time_const_value(statement.value, env:) : nil,
56
+ )
57
+ end
58
+ return setup + [normalized]
56
59
  end
57
- return setup + [normalized]
58
- end
59
60
 
60
- local_type = resolve_type_ref(statement.type)
61
- current_actual_scope(env[:scopes])[statement.name] = local_binding(
62
- type: local_type,
63
- storage_type: local_type,
64
- linkage_name: statement.name,
65
- mutable: statement.kind == :var,
66
- pointer: false,
67
- const_value: nil,
68
- )
69
- [statement]
70
- when AST::Assignment
71
- target_setup, target = normalize_async_assignment_target(statement.target, counter, env:)
72
- return target_setup + [AST::Assignment.new(target:, operator: statement.operator, value: statement.value)] if statement.value.is_a?(AST::AwaitExpr)
61
+ local_type = resolve_type_ref(statement.type)
62
+ current_actual_scope(env[:scopes])[statement.name] = local_binding(
63
+ type: local_type,
64
+ storage_type: local_type,
65
+ linkage_name: statement.name,
66
+ mutable: statement.kind == :var,
67
+ pointer: false,
68
+ const_value: nil,
69
+ )
70
+ [statement]
71
+ when AST::Assignment
72
+ target_setup, target = normalize_async_assignment_target(statement.target, counter, env:)
73
+ return target_setup + [AST::Assignment.new(target:, operator: statement.operator, value: statement.value)] if statement.value.is_a?(AST::AwaitExpr)
73
74
 
74
- target_type = infer_expression_type(statement.target, env:)
75
- setup, value = normalize_async_expression(statement.value, counter, env:, expected_type: target_type)
76
- target_setup + setup + [AST::Assignment.new(target:, operator: statement.operator, value: value)]
77
- when AST::ExpressionStmt
78
- return [statement] if statement.expression.is_a?(AST::AwaitExpr)
75
+ target_type = infer_expression_type(statement.target, env:)
76
+ setup, value = normalize_async_expression(statement.value, counter, env:, expected_type: target_type)
77
+ target_setup + setup + [AST::Assignment.new(target:, operator: statement.operator, value: value)]
78
+ when AST::ExpressionStmt
79
+ return [statement] if statement.expression.is_a?(AST::AwaitExpr)
79
80
 
80
- setup, expression = normalize_async_expression(statement.expression, counter, env:)
81
- setup + [AST::ExpressionStmt.new(expression: expression, line: statement.line)]
82
- when AST::ReturnStmt
83
- return [statement] unless statement.value
84
- return [statement] if statement.value.is_a?(AST::AwaitExpr)
81
+ setup, expression = normalize_async_expression(statement.expression, counter, env:)
82
+ setup + [AST::ExpressionStmt.new(expression: expression, line: statement.line)]
83
+ when AST::ReturnStmt
84
+ return [statement] unless statement.value
85
+ return [statement] if statement.value.is_a?(AST::AwaitExpr)
85
86
 
86
- setup, value = normalize_async_expression(statement.value, counter, env:, expected_type: return_type)
87
- setup + [AST::ReturnStmt.new(value: value, line: statement.line)]
88
- when AST::IfStmt
89
- normalize_async_if_statement(statement, counter, env, return_type:)
90
- when AST::MatchStmt
91
- expr_setup, expression = normalize_async_expression(statement.expression, counter, env:)
92
- scrutinee_type = infer_expression_type(statement.expression, env:)
93
- arms = statement.arms.map do |arm|
94
- arm_env = duplicate_env(env)
95
- bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
96
- AST::MatchArm.new(pattern: arm.pattern, binding_name: arm.binding_name, body: normalize_async_statements(arm.body, counter, arm_env, return_type:), line: arm.line, column: arm.column)
97
- end
98
- expr_setup + [AST::MatchStmt.new(expression:, arms:)]
99
- when AST::WhileStmt
100
- condition_setup, condition = normalize_async_expression(statement.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
101
- body_env = duplicate_env(env)
102
- body = normalize_async_statements(statement.body, counter, body_env, return_type:)
103
- if condition_setup.empty?
104
- [AST::WhileStmt.new(condition:, body:)]
105
- else
106
- cond_name = fresh_async_temp_name(counter)
107
- condition_eval = condition_setup + [AST::LocalDecl.new(kind: :let, name: cond_name, type: ast_type_ref_for(@ctx.types.fetch("bool")), value: condition)]
108
- [
109
- AST::WhileStmt.new(
110
- condition: AST::BooleanLiteral.new(value: true),
111
- body: condition_eval + [
112
- AST::IfStmt.new(
113
- branches: [AST::IfBranch.new(condition: AST::UnaryOp.new(operator: "not", operand: AST::Identifier.new(name: cond_name)), body: [AST::BreakStmt.new])],
114
- else_body: nil,
115
- ),
116
- *body,
117
- ],
118
- ),
119
- ]
120
- end
121
- when AST::ForStmt
122
- original_iterable = statement.iterable
123
- loop_type = if range_iterable?(original_iterable)
124
- infer_range_loop_type(original_iterable, env:)
125
- else
126
- iterable_type = infer_expression_type(original_iterable, env:)
127
- collection_loop_type(iterable_type)
128
- end
129
- for_env = duplicate_env(env)
130
- if statement.parallel?
131
- iterable_setups = []
132
- normalized_iterables = statement.iterables.map do |iterable|
133
- setup, normalized_iterable = normalize_async_expression(iterable, counter, env:)
134
- iterable_setups.concat(setup)
135
- normalized_iterable
87
+ setup, value = normalize_async_expression(statement.value, counter, env:, expected_type: return_type)
88
+ setup + [AST::ReturnStmt.new(value: value, line: statement.line)]
89
+ when AST::IfStmt
90
+ normalize_async_if_statement(statement, counter, env, return_type:)
91
+ when AST::MatchStmt
92
+ expr_setup, expression = normalize_async_expression(statement.expression, counter, env:)
93
+ scrutinee_type = infer_expression_type(statement.expression, env:)
94
+ arms = statement.arms.map do |arm|
95
+ arm_env = duplicate_env(env)
96
+ bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
97
+ AST::MatchArm.new(pattern: arm.pattern, binding_name: arm.binding_name, body: normalize_async_statements(arm.body, counter, arm_env, return_type:), line: arm.line, column: arm.column)
136
98
  end
137
- statement.bindings.each_with_index do |binding, index|
138
- iterable_type = infer_expression_type(statement.iterables[index], env:)
139
- element_type = collection_loop_type(iterable_type)
140
- binding_type = collection_loop_binding_type(iterable_type, element_type) || element_type
141
- current_actual_scope(for_env[:scopes])[binding.name] = local_binding(type: binding_type, linkage_name: binding.name, mutable: false, pointer: false)
99
+ expr_setup + [AST::MatchStmt.new(expression:, arms:)]
100
+ when AST::WhileStmt
101
+ condition_setup, condition = normalize_async_expression(statement.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
102
+ body_env = duplicate_env(env)
103
+ body = normalize_async_statements(statement.body, counter, body_env, return_type:)
104
+ if condition_setup.empty?
105
+ [AST::WhileStmt.new(condition:, body:)]
106
+ else
107
+ cond_name = fresh_async_temp_name(counter)
108
+ condition_eval = condition_setup + [AST::LocalDecl.new(kind: :let, name: cond_name, type: ast_type_ref_for(@ctx.types.fetch("bool")), value: condition)]
109
+ [
110
+ AST::WhileStmt.new(
111
+ condition: AST::BooleanLiteral.new(value: true),
112
+ body: condition_eval + [
113
+ AST::IfStmt.new(
114
+ branches: [AST::IfBranch.new(condition: AST::UnaryOp.new(operator: "not", operand: AST::Identifier.new(name: cond_name)), body: [AST::BreakStmt.new])],
115
+ else_body: nil,
116
+ ),
117
+ *body,
118
+ ],
119
+ ),
120
+ ]
142
121
  end
122
+ when AST::ForStmt
123
+ original_iterable = statement.iterable
124
+ loop_type = if range_iterable?(original_iterable)
125
+ infer_range_loop_type(original_iterable, env:)
126
+ else
127
+ iterable_type = infer_expression_type(original_iterable, env:)
128
+ collection_loop_type(iterable_type)
129
+ end
130
+ for_env = duplicate_env(env)
131
+ if statement.parallel?
132
+ iterable_setups = []
133
+ normalized_iterables = statement.iterables.map do |iterable|
134
+ setup, normalized_iterable = normalize_async_expression(iterable, counter, env:)
135
+ iterable_setups.concat(setup)
136
+ normalized_iterable
137
+ end
138
+ statement.bindings.each_with_index do |binding, index|
139
+ iterable_type = infer_expression_type(statement.iterables[index], env:)
140
+ element_type = collection_loop_type(iterable_type)
141
+ binding_type = collection_loop_binding_type(iterable_type, element_type) || element_type
142
+ current_actual_scope(for_env[:scopes])[binding.name] = local_binding(type: binding_type, linkage_name: binding.name, mutable: false, pointer: false)
143
+ end
144
+ body = normalize_async_statements(statement.body, counter, for_env, return_type:)
145
+ return iterable_setups + [AST::ForStmt.new(bindings: statement.bindings, iterables: normalized_iterables, body:, line: statement.line, column: statement.column)]
146
+ end
147
+
148
+ iterable_setup, iterable = normalize_async_expression(statement.iterable, counter, env:)
149
+ current_actual_scope(for_env[:scopes])[statement.name] = local_binding(type: loop_type, linkage_name: statement.name, mutable: false, pointer: false)
143
150
  body = normalize_async_statements(statement.body, counter, for_env, return_type:)
144
- return iterable_setups + [AST::ForStmt.new(bindings: statement.bindings, iterables: normalized_iterables, body:, line: statement.line, column: statement.column)]
151
+ iterable_setup + [AST::ForStmt.new(bindings: statement.bindings, iterables: [iterable], body:, line: statement.line, column: statement.column)]
152
+ when AST::UnsafeStmt
153
+ unsafe_env = duplicate_env(env)
154
+ [AST::UnsafeStmt.new(body: normalize_async_statements(statement.body, counter, unsafe_env, return_type:), line: statement.line, column: statement.column, length: statement.length)]
155
+ when AST::DeferStmt
156
+ cleanup_env = duplicate_env(env)
157
+ cleanup_env[:return_context] = cleanup_env[:return_context]&.merge(allow_return: false)
158
+ cleanup_body = normalize_async_statements(statement.body, counter, cleanup_env, return_type:)
159
+ [AST::DeferStmt.new(body: cleanup_body, line: statement.line, column: statement.column, length: statement.length)]
160
+ when AST::BreakStmt, AST::ContinueStmt, AST::StaticAssert, AST::PassStmt
161
+ [statement]
162
+ else
163
+ raise LoweringError.new("unsupported async statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
145
164
  end
146
-
147
- iterable_setup, iterable = normalize_async_expression(statement.iterable, counter, env:)
148
- current_actual_scope(for_env[:scopes])[statement.name] = local_binding(type: loop_type, linkage_name: statement.name, mutable: false, pointer: false)
149
- body = normalize_async_statements(statement.body, counter, for_env, return_type:)
150
- iterable_setup + [AST::ForStmt.new(bindings: statement.bindings, iterables: [iterable], body:, line: statement.line, column: statement.column)]
151
- when AST::UnsafeStmt
152
- unsafe_env = duplicate_env(env)
153
- [AST::UnsafeStmt.new(body: normalize_async_statements(statement.body, counter, unsafe_env, return_type:), line: statement.line, column: statement.column, length: statement.length)]
154
- when AST::DeferStmt
155
- cleanup_env = duplicate_env(env)
156
- cleanup_env[:return_context] = cleanup_env[:return_context]&.merge(allow_return: false)
157
- cleanup_body = normalize_async_statements(statement.body, counter, cleanup_env, return_type:)
158
- [AST::DeferStmt.new(body: cleanup_body, line: statement.line, column: statement.column, length: statement.length)]
159
- when AST::BreakStmt, AST::ContinueStmt, AST::StaticAssert, AST::PassStmt
160
- [statement]
161
- else
162
- raise LoweringError.new("unsupported async statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
163
165
  end
164
- end
165
166
 
166
- def normalize_async_if_statement(statement, counter, env, return_type:)
167
- else_body = if statement.else_body
168
- else_env = duplicate_env(env)
169
- normalize_async_statements(statement.else_body, counter, else_env, return_type:)
170
- end
171
- normalize_async_if_branches(statement.branches, else_body, counter, env, return_type:)
172
- end
167
+ def normalize_async_if_statement(statement, counter, env, return_type:)
168
+ else_body = if statement.else_body
169
+ else_env = duplicate_env(env)
170
+ normalize_async_statements(statement.else_body, counter, else_env, return_type:)
171
+ end
172
+ normalize_async_if_branches(statement.branches, else_body, counter, env, return_type:)
173
+ end
173
174
 
174
- def normalize_async_if_branches(branches, else_body, counter, env, return_type:)
175
- return else_body || [] if branches.empty?
175
+ def normalize_async_if_branches(branches, else_body, counter, env, return_type:)
176
+ return else_body || [] if branches.empty?
176
177
 
177
- branch = branches.first
178
- condition_setup, condition = normalize_async_expression(branch.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
179
- then_env = duplicate_env(env)
180
- then_body = normalize_async_statements(branch.body, counter, then_env, return_type:)
181
- chained_else = normalize_async_if_branches(branches.drop(1), else_body, counter, env, return_type:)
182
- condition_setup + [AST::IfStmt.new(branches: [AST::IfBranch.new(condition:, body: then_body)], else_body: chained_else)]
183
- end
178
+ branch = branches.first
179
+ condition_setup, condition = normalize_async_expression(branch.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
180
+ then_env = duplicate_env(env)
181
+ then_body = normalize_async_statements(branch.body, counter, then_env, return_type:)
182
+ chained_else = normalize_async_if_branches(branches.drop(1), else_body, counter, env, return_type:)
183
+ condition_setup + [AST::IfStmt.new(branches: [AST::IfBranch.new(condition:, body: then_body)], else_body: chained_else)]
184
+ end
184
185
 
185
- def normalize_async_assignment_target(target, counter, env:)
186
- case target
187
- when AST::Identifier
188
- [[], target]
189
- when AST::MemberAccess
190
- receiver_setup, receiver = normalize_async_expression(target.receiver, counter, env:)
191
- [receiver_setup, AST::MemberAccess.new(receiver:, member: target.member)]
192
- when AST::IndexAccess
193
- receiver_setup, receiver = normalize_async_expression(target.receiver, counter, env:)
194
- index_setup, index = normalize_async_expression(target.index, counter, env:)
195
- [receiver_setup + index_setup, AST::IndexAccess.new(receiver:, index:)]
196
- when AST::Call
197
- if read_call?(target)
198
- setup = []
199
- normalized_args = target.arguments.map do |arg|
200
- arg_setup, value = normalize_async_expression(arg.value, counter, env:)
201
- setup.concat(arg_setup)
202
- AST::Argument.new(name: arg.name, value:)
186
+ def normalize_async_assignment_target(target, counter, env:)
187
+ case target
188
+ when AST::Identifier
189
+ [[], target]
190
+ when AST::MemberAccess
191
+ receiver_setup, receiver = normalize_async_expression(target.receiver, counter, env:)
192
+ [receiver_setup, AST::MemberAccess.new(receiver:, member: target.member)]
193
+ when AST::IndexAccess
194
+ receiver_setup, receiver = normalize_async_expression(target.receiver, counter, env:)
195
+ index_setup, index = normalize_async_expression(target.index, counter, env:)
196
+ [receiver_setup + index_setup, AST::IndexAccess.new(receiver:, index:)]
197
+ when AST::Call
198
+ if read_call?(target)
199
+ setup = []
200
+ normalized_args = target.arguments.map do |arg|
201
+ arg_setup, value = normalize_async_expression(arg.value, counter, env:)
202
+ setup.concat(arg_setup)
203
+ AST::Argument.new(name: arg.name, value:)
204
+ end
205
+ [setup, AST::Call.new(callee: target.callee, arguments: normalized_args)]
206
+ else
207
+ raise LoweringError.new("unsupported assignment target #{target.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
203
208
  end
204
- [setup, AST::Call.new(callee: target.callee, arguments: normalized_args)]
205
209
  else
206
210
  raise LoweringError.new("unsupported assignment target #{target.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
207
211
  end
208
- else
209
- raise LoweringError.new("unsupported assignment target #{target.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
210
212
  end
211
- end
212
213
 
213
- def normalize_async_expression(expression, counter, env:, expected_type: nil)
214
- case expression
215
- when AST::AwaitExpr
216
- inner_setup, inner = normalize_async_expression(expression.expression, counter, env:)
217
- temp_name = fresh_async_temp_name(counter)
218
- [
219
- inner_setup + [AST::LocalDecl.new(kind: :let, name: temp_name, type: nil, value: AST::AwaitExpr.new(expression: inner))],
220
- AST::Identifier.new(name: temp_name),
221
- ]
222
- when AST::Call
223
- setup = []
224
- callee_setup, callee = normalize_async_expression(expression.callee, counter, env:)
225
- setup.concat(callee_setup)
226
- arguments = expression.arguments.map do |argument|
227
- argument_setup, value = normalize_async_expression(argument.value, counter, env:)
228
- setup.concat(argument_setup)
229
- AST::Argument.new(name: argument.name, value: value)
230
- end
231
- [setup, AST::Call.new(callee: callee, arguments: arguments)]
232
- when AST::Specialization
233
- setup = []
234
- callee_setup, callee = normalize_async_expression(expression.callee, counter, env:)
235
- setup.concat(callee_setup)
236
- arguments = expression.arguments.map do |argument|
237
- argument_setup, value = normalize_async_expression(argument.value, counter, env:)
238
- setup.concat(argument_setup)
239
- AST::TypeArgument.new(value: value)
240
- end
241
- [setup, AST::Specialization.new(callee: callee, arguments: arguments)]
242
- when AST::PrefixCast
243
- setup, expr = normalize_async_expression(expression.expression, counter, env:)
244
- [setup, AST::PrefixCast.new(target_type: expression.target_type, expression: expr)]
245
- when AST::UnaryOp
246
- setup, operand = normalize_async_expression(expression.operand, counter, env:, expected_type: expected_type)
247
- [setup, AST::UnaryOp.new(operator: expression.operator, operand: operand)]
248
- when AST::BinaryOp
249
- if %w[and or].include?(expression.operator)
250
- left_setup, left = normalize_async_expression(expression.left, counter, env:, expected_type: @ctx.types.fetch("bool"))
251
- right_setup, right = normalize_async_expression(expression.right, counter, env:, expected_type: @ctx.types.fetch("bool"))
214
+ def normalize_async_expression(expression, counter, env:, expected_type: nil)
215
+ case expression
216
+ when AST::AwaitExpr
217
+ inner_setup, inner = normalize_async_expression(expression.expression, counter, env:)
252
218
  temp_name = fresh_async_temp_name(counter)
219
+ [
220
+ inner_setup + [AST::LocalDecl.new(kind: :let, name: temp_name, type: nil, value: AST::AwaitExpr.new(expression: inner))],
221
+ AST::Identifier.new(name: temp_name),
222
+ ]
223
+ when AST::Call
224
+ setup = []
225
+ callee_setup, callee = normalize_async_expression(expression.callee, counter, env:)
226
+ setup.concat(callee_setup)
227
+ arguments = expression.arguments.map do |argument|
228
+ argument_setup, value = normalize_async_expression(argument.value, counter, env:)
229
+ setup.concat(argument_setup)
230
+ AST::Argument.new(name: argument.name, value: value)
231
+ end
232
+ [setup, AST::Call.new(callee: callee, arguments: arguments)]
233
+ when AST::Specialization
234
+ setup = []
235
+ callee_setup, callee = normalize_async_expression(expression.callee, counter, env:)
236
+ setup.concat(callee_setup)
237
+ arguments = expression.arguments.map do |argument|
238
+ argument_setup, value = normalize_async_expression(argument.value, counter, env:)
239
+ setup.concat(argument_setup)
240
+ AST::TypeArgument.new(value: value)
241
+ end
242
+ [setup, AST::Specialization.new(callee: callee, arguments: arguments)]
243
+ when AST::PrefixCast
244
+ setup, expr = normalize_async_expression(expression.expression, counter, env:)
245
+ [setup, AST::PrefixCast.new(target_type: expression.target_type, expression: expr)]
246
+ when AST::UnaryOp
247
+ setup, operand = normalize_async_expression(expression.operand, counter, env:, expected_type: expected_type)
248
+ [setup, AST::UnaryOp.new(operator: expression.operator, operand: operand)]
249
+ when AST::BinaryOp
250
+ if %w[and or].include?(expression.operator)
251
+ left_setup, left = normalize_async_expression(expression.left, counter, env:, expected_type: @ctx.types.fetch("bool"))
252
+ right_setup, right = normalize_async_expression(expression.right, counter, env:, expected_type: @ctx.types.fetch("bool"))
253
+ temp_name = fresh_async_temp_name(counter)
253
254
 
254
- temp_init = expression.operator == "and" ? AST::BooleanLiteral.new(value: false) : AST::BooleanLiteral.new(value: true)
255
- short_circuit_value = expression.operator == "and" ? AST::BooleanLiteral.new(value: false) : AST::BooleanLiteral.new(value: true)
255
+ temp_init = expression.operator == "and" ? AST::BooleanLiteral.new(value: false) : AST::BooleanLiteral.new(value: true)
256
+ short_circuit_value = expression.operator == "and" ? AST::BooleanLiteral.new(value: false) : AST::BooleanLiteral.new(value: true)
256
257
 
257
- branch_body = right_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: right)]
258
- else_body = [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: short_circuit_value)]
258
+ branch_body = right_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: right)]
259
+ else_body = [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: short_circuit_value)]
259
260
 
260
- if expression.operator == "or"
261
- branch_body, else_body = else_body, branch_body
262
- end
261
+ if expression.operator == "or"
262
+ branch_body, else_body = else_body, branch_body
263
+ end
263
264
 
264
- setup = [AST::LocalDecl.new(kind: :var, name: temp_name, type: nil, value: temp_init)]
265
- setup.concat(left_setup)
266
- setup << AST::IfStmt.new(branches: [AST::IfBranch.new(condition: left, body: branch_body)], else_body: else_body)
267
- return [setup, AST::Identifier.new(name: temp_name)]
268
- end
265
+ setup = [AST::LocalDecl.new(kind: :var, name: temp_name, type: nil, value: temp_init)]
266
+ setup.concat(left_setup)
267
+ setup << AST::IfStmt.new(branches: [AST::IfBranch.new(condition: left, body: branch_body)], else_body: else_body)
268
+ return [setup, AST::Identifier.new(name: temp_name)]
269
+ end
269
270
 
270
- left_setup, left = normalize_async_expression(expression.left, counter, env:)
271
- right_setup, right = normalize_async_expression(expression.right, counter, env:)
272
- [left_setup + right_setup, AST::BinaryOp.new(operator: expression.operator, left: left, right: right)]
273
- when AST::IfExpr
274
- condition_setup, condition = normalize_async_expression(expression.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
275
- result_type = infer_expression_type(expression, env:, expected_type:)
276
- then_setup, then_expression = normalize_async_expression(expression.then_expression, counter, env:, expected_type: result_type)
277
- else_setup, else_expression = normalize_async_expression(expression.else_expression, counter, env:, expected_type: result_type)
271
+ left_setup, left = normalize_async_expression(expression.left, counter, env:)
272
+ right_setup, right = normalize_async_expression(expression.right, counter, env:)
273
+ [left_setup + right_setup, AST::BinaryOp.new(operator: expression.operator, left: left, right: right)]
274
+ when AST::IfExpr
275
+ condition_setup, condition = normalize_async_expression(expression.condition, counter, env:, expected_type: @ctx.types.fetch("bool"))
276
+ result_type = infer_expression_type(expression, env:, expected_type:)
277
+ then_setup, then_expression = normalize_async_expression(expression.then_expression, counter, env:, expected_type: result_type)
278
+ else_setup, else_expression = normalize_async_expression(expression.else_expression, counter, env:, expected_type: result_type)
278
279
 
279
- return [[], AST::IfExpr.new(condition:, then_expression:, else_expression:)] if condition_setup.empty? && then_setup.empty? && else_setup.empty?
280
+ return [[], AST::IfExpr.new(condition:, then_expression:, else_expression:)] if condition_setup.empty? && then_setup.empty? && else_setup.empty?
280
281
 
281
- temp_name = fresh_async_temp_name(counter)
282
- setup = condition_setup + [
283
- AST::LocalDecl.new(kind: :var, name: temp_name, type: ast_type_ref_for(result_type), value: nil),
284
- AST::IfStmt.new(
285
- branches: [AST::IfBranch.new(condition:, body: then_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: then_expression)])],
286
- else_body: else_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: else_expression)],
287
- ),
288
- ]
289
- [setup, AST::Identifier.new(name: temp_name)]
290
- when AST::MatchExpr
291
- expression_setup, normalized_expression = normalize_async_expression(expression.expression, counter, env:)
292
- result_type = infer_expression_type(expression, env:, expected_type:)
293
- scrutinee_type = infer_expression_type(expression.expression, env:)
294
- normalized_arms = expression.arms.map do |arm|
295
- arm_env = duplicate_env(env)
296
- bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
297
- pattern_setup, normalized_pattern = normalize_async_expression(arm.pattern, counter, env:)
298
- value_setup, normalized_value = normalize_async_expression(arm.value, counter, env: arm_env, expected_type: result_type)
299
- [pattern_setup, value_setup, AST::MatchExprArm.new(
300
- pattern: normalized_pattern,
301
- binding_name: arm.binding_name,
302
- binding_line: arm.binding_line,
303
- binding_column: arm.binding_column,
304
- value: normalized_value,
305
- line: arm.line,
306
- column: arm.column,
307
- )]
308
- end
282
+ temp_name = fresh_async_temp_name(counter)
283
+ setup = condition_setup + [
284
+ AST::LocalDecl.new(kind: :var, name: temp_name, type: ast_type_ref_for(result_type), value: nil),
285
+ AST::IfStmt.new(
286
+ branches: [AST::IfBranch.new(condition:, body: then_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: then_expression)])],
287
+ else_body: else_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: else_expression)],
288
+ ),
289
+ ]
290
+ [setup, AST::Identifier.new(name: temp_name)]
291
+ when AST::MatchExpr
292
+ expression_setup, normalized_expression = normalize_async_expression(expression.expression, counter, env:)
293
+ result_type = infer_expression_type(expression, env:, expected_type:)
294
+ scrutinee_type = infer_expression_type(expression.expression, env:)
295
+ normalized_arms = expression.arms.map do |arm|
296
+ arm_env = duplicate_env(env)
297
+ bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
298
+ pattern_setup, normalized_pattern = normalize_async_expression(arm.pattern, counter, env:)
299
+ value_setup, normalized_value = normalize_async_expression(arm.value, counter, env: arm_env, expected_type: result_type)
300
+ [pattern_setup, value_setup, AST::MatchExprArm.new(
301
+ pattern: normalized_pattern,
302
+ binding_name: arm.binding_name,
303
+ binding_line: arm.binding_line,
304
+ binding_column: arm.binding_column,
305
+ value: normalized_value,
306
+ line: arm.line,
307
+ column: arm.column,
308
+ )]
309
+ end
309
310
 
310
- if expression_setup.empty? && normalized_arms.all? { |pattern_setup, value_setup, _arm| pattern_setup.empty? && value_setup.empty? }
311
- return [[], AST::MatchExpr.new(expression: normalized_expression, arms: normalized_arms.map(&:last), line: expression.line, column: expression.column, length: expression.length)]
312
- end
311
+ if expression_setup.empty? && normalized_arms.all? { |pattern_setup, value_setup, _arm| pattern_setup.empty? && value_setup.empty? }
312
+ return [[], AST::MatchExpr.new(expression: normalized_expression, arms: normalized_arms.map(&:last), line: expression.line, column: expression.column, length: expression.length)]
313
+ end
313
314
 
314
- temp_name = fresh_async_temp_name(counter)
315
- setup = expression_setup + [
316
- AST::LocalDecl.new(kind: :var, name: temp_name, type: ast_type_ref_for(result_type), value: nil),
317
- AST::MatchStmt.new(
318
- expression: normalized_expression,
319
- arms: normalized_arms.map do |pattern_setup, value_setup, arm|
320
- AST::MatchArm.new(
321
- pattern: arm.pattern,
322
- binding_name: arm.binding_name,
323
- binding_line: arm.binding_line,
324
- binding_column: arm.binding_column,
325
- body: pattern_setup + value_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: arm.value)],
326
- line: arm.line,
327
- column: arm.column,
328
- )
329
- end,
330
- line: expression.line,
331
- column: expression.column,
332
- length: expression.length,
333
- ),
334
- ]
335
- [setup, AST::Identifier.new(name: temp_name)]
336
- when AST::UnsafeExpr
337
- normalize_async_expression(expression.expression, counter, env:, expected_type:)
338
- when AST::MemberAccess
339
- setup, receiver = normalize_async_expression(expression.receiver, counter, env:)
340
- [setup, AST::MemberAccess.new(receiver: receiver, member: expression.member)]
341
- when AST::IndexAccess
342
- receiver_setup, receiver = normalize_async_expression(expression.receiver, counter, env:)
343
- index_setup, index = normalize_async_expression(expression.index, counter, env:)
344
- [receiver_setup + index_setup, AST::IndexAccess.new(receiver: receiver, index: index)]
345
- when AST::RangeExpr
346
- start_setup, start_expr = normalize_async_expression(expression.start_expr, counter, env:)
347
- end_setup, end_expr = normalize_async_expression(expression.end_expr, counter, env:)
348
- [start_setup + end_setup, AST::RangeExpr.new(start_expr:, end_expr:, line: expression.line, column: expression.column)]
349
- when AST::FormatString
350
- setup = []
351
- parts = expression.parts.map do |part|
352
- if part.is_a?(AST::FormatExprPart)
353
- expression_setup, inner_expression = normalize_async_expression(part.expression, counter, env:)
354
- setup.concat(expression_setup)
355
- AST::FormatExprPart.new(expression: inner_expression, format_spec: part.format_spec)
356
- else
357
- part
315
+ temp_name = fresh_async_temp_name(counter)
316
+ setup = expression_setup + [
317
+ AST::LocalDecl.new(kind: :var, name: temp_name, type: ast_type_ref_for(result_type), value: nil),
318
+ AST::MatchStmt.new(
319
+ expression: normalized_expression,
320
+ arms: normalized_arms.map do |pattern_setup, value_setup, arm|
321
+ AST::MatchArm.new(
322
+ pattern: arm.pattern,
323
+ binding_name: arm.binding_name,
324
+ binding_line: arm.binding_line,
325
+ binding_column: arm.binding_column,
326
+ body: pattern_setup + value_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: arm.value)],
327
+ line: arm.line,
328
+ column: arm.column,
329
+ )
330
+ end,
331
+ line: expression.line,
332
+ column: expression.column,
333
+ length: expression.length,
334
+ ),
335
+ ]
336
+ [setup, AST::Identifier.new(name: temp_name)]
337
+ when AST::UnsafeExpr
338
+ normalize_async_expression(expression.expression, counter, env:, expected_type:)
339
+ when AST::MemberAccess
340
+ setup, receiver = normalize_async_expression(expression.receiver, counter, env:)
341
+ [setup, AST::MemberAccess.new(receiver: receiver, member: expression.member)]
342
+ when AST::IndexAccess
343
+ receiver_setup, receiver = normalize_async_expression(expression.receiver, counter, env:)
344
+ index_setup, index = normalize_async_expression(expression.index, counter, env:)
345
+ [receiver_setup + index_setup, AST::IndexAccess.new(receiver: receiver, index: index)]
346
+ when AST::RangeExpr
347
+ start_setup, start_expr = normalize_async_expression(expression.start_expr, counter, env:)
348
+ end_setup, end_expr = normalize_async_expression(expression.end_expr, counter, env:)
349
+ [start_setup + end_setup, AST::RangeExpr.new(start_expr:, end_expr:, line: expression.line, column: expression.column)]
350
+ when AST::FormatString
351
+ setup = []
352
+ parts = expression.parts.map do |part|
353
+ if part.is_a?(AST::FormatExprPart)
354
+ expression_setup, inner_expression = normalize_async_expression(part.expression, counter, env:)
355
+ setup.concat(expression_setup)
356
+ AST::FormatExprPart.new(expression: inner_expression, format_spec: part.format_spec)
357
+ else
358
+ part
359
+ end
358
360
  end
361
+ [setup, AST::FormatString.new(parts: parts)]
362
+ else
363
+ [[], expression]
359
364
  end
360
- [setup, AST::FormatString.new(parts: parts)]
361
- else
362
- [[], expression]
363
365
  end
364
- end
365
366
 
366
- def ast_type_ref_for(type)
367
- case type
368
- when Types::Primitive
369
- AST::TypeRef.new(name: AST::QualifiedName.new(parts: [type.name]), arguments: [], nullable: false)
370
- when Types::Nullable
371
- inner = ast_type_ref_for(type.base)
372
- raise LoweringError.new("nullable annotation is only valid for named/generic types", line: 0, column: 0, path: @ctx.current_analysis_path) unless inner.is_a?(AST::TypeRef)
367
+ def ast_type_ref_for(type)
368
+ case type
369
+ when Types::Primitive
370
+ AST::TypeRef.new(name: AST::QualifiedName.new(parts: [type.name]), arguments: [], nullable: false)
371
+ when Types::Nullable
372
+ inner = ast_type_ref_for(type.base)
373
+ raise LoweringError.new("nullable annotation is only valid for named/generic types", line: 0, column: 0, path: @ctx.current_analysis_path) unless inner.is_a?(AST::TypeRef)
373
374
 
374
- AST::TypeRef.new(name: inner.name, arguments: inner.arguments, nullable: true)
375
- when Types::GenericInstance
376
- AST::TypeRef.new(
377
- name: AST::QualifiedName.new(parts: type.name.split(".")),
378
- arguments: type.arguments.map do |argument|
379
- if argument.is_a?(Types::LiteralTypeArg)
380
- AST::TypeArgument.new(value: AST::IntegerLiteral.new(lexeme: argument.value.to_s, value: argument.value))
381
- else
382
- AST::TypeArgument.new(value: ast_type_ref_for(argument))
383
- end
384
- end,
385
- nullable: false,
386
- )
387
- when Types::Span
388
- AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: [AST::TypeArgument.new(value: ast_type_ref_for(type.element_type))], nullable: false)
389
- when Types::Task
390
- AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["Task"]), arguments: [AST::TypeArgument.new(value: ast_type_ref_for(type.result_type))], nullable: false)
391
- when Types::TypeVar
392
- AST::TypeRef.new(name: AST::QualifiedName.new(parts: [type.name]), arguments: [], nullable: false)
393
- when Types::StructInstance
394
- base_parts = type.module_name ? type.module_name.split(".") + [type.name] : [type.name]
395
- AST::TypeRef.new(
396
- name: AST::QualifiedName.new(parts: base_parts),
397
- arguments: type.arguments.map do |argument|
398
- if argument.is_a?(Types::LiteralTypeArg)
399
- AST::TypeArgument.new(value: AST::IntegerLiteral.new(lexeme: argument.value.to_s, value: argument.value))
400
- else
401
- AST::TypeArgument.new(value: ast_type_ref_for(argument))
402
- end
403
- end,
404
- nullable: false,
405
- )
406
- when Types::Struct, Types::Union, Types::Opaque, Types::Enum, Types::Flags
407
- parts = type.module_name ? type.module_name.split(".") + [type.name] : [type.name]
408
- AST::TypeRef.new(name: AST::QualifiedName.new(parts: parts), arguments: [], nullable: false)
409
- when Types::Function
410
- AST::FunctionType.new(
411
- params: type.params.each_with_index.map { |param, i| AST::Param.new(name: param.name || "p#{i}", type: ast_type_ref_for(param.type)) },
412
- return_type: ast_type_ref_for(type.return_type),
413
- )
414
- when Types::Proc
415
- AST::ProcType.new(
416
- params: type.params.each_with_index.map { |param, i| AST::Param.new(name: param.name || "p#{i}", type: ast_type_ref_for(param.type)) },
417
- return_type: ast_type_ref_for(type.return_type),
418
- )
419
- else
420
- raise LoweringError.new("unsupported type for AST normalization #{type.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
375
+ AST::TypeRef.new(name: inner.name, arguments: inner.arguments, nullable: true)
376
+ when Types::GenericInstance
377
+ AST::TypeRef.new(
378
+ name: AST::QualifiedName.new(parts: type.name.split(".")),
379
+ arguments: type.arguments.map do |argument|
380
+ if argument.is_a?(Types::LiteralTypeArg)
381
+ AST::TypeArgument.new(value: AST::IntegerLiteral.new(lexeme: argument.value.to_s, value: argument.value))
382
+ else
383
+ AST::TypeArgument.new(value: ast_type_ref_for(argument))
384
+ end
385
+ end,
386
+ nullable: false,
387
+ )
388
+ when Types::Span
389
+ AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: [AST::TypeArgument.new(value: ast_type_ref_for(type.element_type))], nullable: false)
390
+ when Types::Task
391
+ AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["Task"]), arguments: [AST::TypeArgument.new(value: ast_type_ref_for(type.result_type))], nullable: false)
392
+ when Types::TypeVar
393
+ AST::TypeRef.new(name: AST::QualifiedName.new(parts: [type.name]), arguments: [], nullable: false)
394
+ when Types::StructInstance
395
+ base_parts = type.module_name ? type.module_name.split(".") + [type.name] : [type.name]
396
+ AST::TypeRef.new(
397
+ name: AST::QualifiedName.new(parts: base_parts),
398
+ arguments: type.arguments.map do |argument|
399
+ if argument.is_a?(Types::LiteralTypeArg)
400
+ AST::TypeArgument.new(value: AST::IntegerLiteral.new(lexeme: argument.value.to_s, value: argument.value))
401
+ else
402
+ AST::TypeArgument.new(value: ast_type_ref_for(argument))
403
+ end
404
+ end,
405
+ nullable: false,
406
+ )
407
+ when Types::Struct, Types::Union, Types::Opaque, Types::Enum, Types::Flags
408
+ parts = type.module_name ? type.module_name.split(".") + [type.name] : [type.name]
409
+ AST::TypeRef.new(name: AST::QualifiedName.new(parts: parts), arguments: [], nullable: false)
410
+ when Types::Function
411
+ AST::FunctionType.new(
412
+ params: type.params.each_with_index.map { |param, i| AST::Param.new(name: param.name || "p#{i}", type: ast_type_ref_for(param.type)) },
413
+ return_type: ast_type_ref_for(type.return_type),
414
+ )
415
+ when Types::Proc
416
+ AST::ProcType.new(
417
+ params: type.params.each_with_index.map { |param, i| AST::Param.new(name: param.name || "p#{i}", type: ast_type_ref_for(param.type)) },
418
+ return_type: ast_type_ref_for(type.return_type),
419
+ )
420
+ else
421
+ raise LoweringError.new("unsupported type for AST normalization #{type.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
422
+ end
421
423
  end
422
- end
423
424
 
424
- def async_expression_contains_await?(expression)
425
- case expression
426
- when AST::AwaitExpr
427
- true
428
- when AST::Call, AST::Specialization
429
- async_expression_contains_await?(expression.callee) || expression.arguments.any? { |argument| async_expression_contains_await?(argument.value) }
430
- when AST::UnaryOp
431
- async_expression_contains_await?(expression.operand)
432
- when AST::BinaryOp
433
- async_expression_contains_await?(expression.left) || async_expression_contains_await?(expression.right)
434
- when AST::IfExpr
435
- async_expression_contains_await?(expression.condition) || async_expression_contains_await?(expression.then_expression) || async_expression_contains_await?(expression.else_expression)
436
- when AST::MatchExpr
437
- async_expression_contains_await?(expression.expression) || expression.arms.any? { |arm| async_expression_contains_await?(arm.pattern) || async_expression_contains_await?(arm.value) }
438
- when AST::UnsafeExpr
439
- async_expression_contains_await?(expression.expression)
440
- when AST::MemberAccess
441
- async_expression_contains_await?(expression.receiver)
442
- when AST::IndexAccess
443
- async_expression_contains_await?(expression.receiver) || async_expression_contains_await?(expression.index)
444
- when AST::FormatString
445
- expression.parts.any? { |part| part.is_a?(AST::FormatExprPart) && async_expression_contains_await?(part.expression) }
446
- else
447
- false
425
+ def async_expression_contains_await?(expression)
426
+ case expression
427
+ when AST::AwaitExpr
428
+ true
429
+ when AST::Call, AST::Specialization
430
+ async_expression_contains_await?(expression.callee) || expression.arguments.any? { |argument| async_expression_contains_await?(argument.value) }
431
+ when AST::UnaryOp
432
+ async_expression_contains_await?(expression.operand)
433
+ when AST::BinaryOp
434
+ async_expression_contains_await?(expression.left) || async_expression_contains_await?(expression.right)
435
+ when AST::IfExpr
436
+ async_expression_contains_await?(expression.condition) || async_expression_contains_await?(expression.then_expression) || async_expression_contains_await?(expression.else_expression)
437
+ when AST::MatchExpr
438
+ async_expression_contains_await?(expression.expression) || expression.arms.any? { |arm| async_expression_contains_await?(arm.pattern) || async_expression_contains_await?(arm.value) }
439
+ when AST::UnsafeExpr
440
+ async_expression_contains_await?(expression.expression)
441
+ when AST::MemberAccess
442
+ async_expression_contains_await?(expression.receiver)
443
+ when AST::IndexAccess
444
+ async_expression_contains_await?(expression.receiver) || async_expression_contains_await?(expression.index)
445
+ when AST::FormatString
446
+ expression.parts.any? { |part| part.is_a?(AST::FormatExprPart) && async_expression_contains_await?(part.expression) }
447
+ else
448
+ false
449
+ end
448
450
  end
449
- end
450
451
 
451
- def fresh_async_temp_name(counter)
452
- counter[:value] += 1
453
- "__mt_async_tmp_#{counter[:value]}"
452
+ def fresh_async_temp_name(counter)
453
+ counter[:value] += 1
454
+ "__mt_async_tmp_#{counter[:value]}"
455
+ end
454
456
  end
455
457
  end
456
458
  end