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,203 +1,205 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MilkTea
4
- module LowererForeignCstr
5
- def lower_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:, cleanup:)
6
- if (direct_value = lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:))
7
- return direct_value
8
- end
9
-
10
- public_type = parameter.type
11
- boundary_type = parameter.boundary_type
12
- items_type = pointer_to(pointer_to(@ctx.types.fetch("char")))
13
- data_type = pointer_to(@ctx.types.fetch("char"))
14
- len_type = @ctx.types.fetch("ptr_uint")
15
- lowered_value = lower_contextual_expression(argument_value, env:, expected_type: public_type)
16
- items_name = fresh_c_temp_name(env, "foreign_cstr_items")
17
- data_name = fresh_c_temp_name(env, "foreign_cstr_data")
18
- len_name = fresh_c_temp_name(env, "foreign_cstr_len")
19
-
20
- lowered << IR::LocalDecl.new(
21
- name: items_name,
22
- linkage_name: items_name,
23
- type: items_type,
24
- value: IR::NullLiteral.new(type: items_type),
25
- )
26
- lowered << IR::LocalDecl.new(
27
- name: data_name,
28
- linkage_name: data_name,
29
- type: data_type,
30
- value: IR::NullLiteral.new(type: data_type),
31
- )
32
- lowered << IR::LocalDecl.new(
33
- name: len_name,
34
- linkage_name: len_name,
35
- type: len_type,
36
- value: IR::IntegerLiteral.new(value: 0, type: len_type),
37
- )
38
- lowered << IR::ExpressionStmt.new(
39
- expression: IR::Call.new(
40
- callee: "mt_foreign_strs_to_cstrs_temp",
41
- arguments: [
42
- lowered_value,
43
- IR::AddressOf.new(expression: IR::Name.new(name: items_name, type: items_type, pointer: false), type: pointer_to(items_type)),
44
- IR::AddressOf.new(expression: IR::Name.new(name: data_name, type: data_type, pointer: false), type: pointer_to(data_type)),
45
- IR::AddressOf.new(expression: IR::Name.new(name: len_name, type: len_type, pointer: false), type: pointer_to(len_type)),
46
- ],
47
- type: @ctx.types.fetch("void"),
48
- ),
49
- )
50
- cleanup << IR::ExpressionStmt.new(
51
- expression: IR::Call.new(
52
- callee: "mt_free_foreign_cstrs_temp",
53
- arguments: [
54
- IR::Name.new(name: items_name, type: items_type, pointer: false),
55
- IR::Name.new(name: data_name, type: data_type, pointer: false),
56
- ],
57
- type: @ctx.types.fetch("void"),
58
- ),
59
- )
60
-
61
- converted_data = foreign_identity_projection_expression(
62
- IR::Name.new(name: items_name, type: items_type, pointer: false),
63
- pointer_to(boundary_type.element_type),
64
- )
65
- raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
66
-
67
- IR::AggregateLiteral.new(
68
- type: boundary_type,
69
- fields: [
70
- IR::AggregateField.new(name: "data", value: converted_data),
71
- IR::AggregateField.new(name: "len", value: IR::Name.new(name: len_name, type: len_type, pointer: false)),
72
- ],
73
- )
74
- end
75
-
76
- def lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:)
77
- actual_type = infer_expression_type(argument_value, env:)
78
- return unless array_type?(actual_type)
79
- return unless cstr_list_backed_expression?(argument_value, env)
4
+ module Lowering
5
+ module ForeignCstr
6
+ def lower_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:, cleanup:)
7
+ if (direct_value = lower_direct_cstr_list_argument(parameter, argument_value, env:, lowered:))
8
+ return direct_value
9
+ end
10
+
11
+ public_type = parameter.type
12
+ boundary_type = parameter.boundary_type
13
+ items_type = pointer_to(pointer_to(@ctx.types.fetch("char")))
14
+ data_type = pointer_to(@ctx.types.fetch("char"))
15
+ len_type = @ctx.types.fetch("ptr_uint")
16
+ lowered_value = lower_contextual_expression(argument_value, env:, expected_type: public_type)
17
+ items_name = fresh_c_temp_name(env, "foreign_cstr_items")
18
+ data_name = fresh_c_temp_name(env, "foreign_cstr_data")
19
+ len_name = fresh_c_temp_name(env, "foreign_cstr_len")
20
+
21
+ lowered << IR::LocalDecl.new(
22
+ name: items_name,
23
+ linkage_name: items_name,
24
+ type: items_type,
25
+ value: IR::NullLiteral.new(type: items_type),
26
+ )
27
+ lowered << IR::LocalDecl.new(
28
+ name: data_name,
29
+ linkage_name: data_name,
30
+ type: data_type,
31
+ value: IR::NullLiteral.new(type: data_type),
32
+ )
33
+ lowered << IR::LocalDecl.new(
34
+ name: len_name,
35
+ linkage_name: len_name,
36
+ type: len_type,
37
+ value: IR::IntegerLiteral.new(value: 0, type: len_type),
38
+ )
39
+ lowered << IR::ExpressionStmt.new(
40
+ expression: IR::Call.new(
41
+ callee: "mt_foreign_strs_to_cstrs_temp",
42
+ arguments: [
43
+ lowered_value,
44
+ IR::AddressOf.new(expression: IR::Name.new(name: items_name, type: items_type, pointer: false), type: pointer_to(items_type)),
45
+ IR::AddressOf.new(expression: IR::Name.new(name: data_name, type: data_type, pointer: false), type: pointer_to(data_type)),
46
+ IR::AddressOf.new(expression: IR::Name.new(name: len_name, type: len_type, pointer: false), type: pointer_to(len_type)),
47
+ ],
48
+ type: @ctx.types.fetch("void"),
49
+ ),
50
+ )
51
+ cleanup << IR::ExpressionStmt.new(
52
+ expression: IR::Call.new(
53
+ callee: "mt_free_foreign_cstrs_temp",
54
+ arguments: [
55
+ IR::Name.new(name: items_name, type: items_type, pointer: false),
56
+ IR::Name.new(name: data_name, type: data_type, pointer: false),
57
+ ],
58
+ type: @ctx.types.fetch("void"),
59
+ ),
60
+ )
80
61
 
81
- boundary_type = parameter.boundary_type
82
- boundary_element_type = boundary_type.element_type
83
- len = array_length(actual_type)
84
- len_type = @ctx.types.fetch("ptr_uint")
62
+ converted_data = foreign_identity_projection_expression(
63
+ IR::Name.new(name: items_name, type: items_type, pointer: false),
64
+ pointer_to(boundary_type.element_type),
65
+ )
66
+ raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
85
67
 
86
- if len.zero?
87
- return IR::AggregateLiteral.new(
68
+ IR::AggregateLiteral.new(
88
69
  type: boundary_type,
89
70
  fields: [
90
- IR::AggregateField.new(name: "data", value: IR::NullLiteral.new(type: pointer_to(boundary_element_type))),
91
- IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: 0, type: len_type)),
71
+ IR::AggregateField.new(name: "data", value: converted_data),
72
+ IR::AggregateField.new(name: "len", value: IR::Name.new(name: len_name, type: len_type, pointer: false)),
92
73
  ],
93
74
  )
94
75
  end
95
76
 
96
- source = lower_expression(argument_value, env:, expected_type: actual_type)
97
- item_type = array_element_type(actual_type)
98
- items_array_type = Types::Registry.generic_instance("array", [boundary_element_type, Types::LiteralTypeArg.new(len)])
99
- items_name = fresh_c_temp_name(env, "foreign_cstr_items")
100
- items = (0...len).map do |index|
101
- item = IR::Index.new(
102
- receiver: source,
103
- index: IR::IntegerLiteral.new(value: index, type: len_type),
104
- type: item_type,
77
+ def lower_direct_cstr_list_argument(parameter, argument_value, env:, lowered:)
78
+ actual_type = infer_expression_type(argument_value, env:)
79
+ return unless array_type?(actual_type)
80
+ return unless cstr_list_backed_expression?(argument_value, env)
81
+
82
+ boundary_type = parameter.boundary_type
83
+ boundary_element_type = boundary_type.element_type
84
+ len = array_length(actual_type)
85
+ len_type = @ctx.types.fetch("ptr_uint")
86
+
87
+ if len.zero?
88
+ return IR::AggregateLiteral.new(
89
+ type: boundary_type,
90
+ fields: [
91
+ IR::AggregateField.new(name: "data", value: IR::NullLiteral.new(type: pointer_to(boundary_element_type))),
92
+ IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: 0, type: len_type)),
93
+ ],
94
+ )
95
+ end
96
+
97
+ source = lower_expression(argument_value, env:, expected_type: actual_type)
98
+ item_type = array_element_type(actual_type)
99
+ items_array_type = Types::Registry.generic_instance("array", [boundary_element_type, Types::LiteralTypeArg.new(len)])
100
+ items_name = fresh_c_temp_name(env, "foreign_cstr_items")
101
+ items = (0...len).map do |index|
102
+ item = IR::Index.new(
103
+ receiver: source,
104
+ index: IR::IntegerLiteral.new(value: index, type: len_type),
105
+ type: item_type,
106
+ )
107
+ item = IR::Member.new(receiver: item, member: "data", type: pointer_to(@ctx.types.fetch("char"))) if item_type == @ctx.types.fetch("str")
108
+
109
+ converted = foreign_identity_projection_expression(item, boundary_element_type)
110
+ raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted
111
+
112
+ converted
113
+ end
114
+
115
+ lowered << IR::LocalDecl.new(
116
+ name: items_name,
117
+ linkage_name: items_name,
118
+ type: items_array_type,
119
+ value: IR::ArrayLiteral.new(type: items_array_type, elements: items),
105
120
  )
106
- item = IR::Member.new(receiver: item, member: "data", type: pointer_to(@ctx.types.fetch("char"))) if item_type == @ctx.types.fetch("str")
107
121
 
108
- converted = foreign_identity_projection_expression(item, boundary_element_type)
109
- raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted
110
-
111
- converted
112
- end
113
-
114
- lowered << IR::LocalDecl.new(
115
- name: items_name,
116
- linkage_name: items_name,
117
- type: items_array_type,
118
- value: IR::ArrayLiteral.new(type: items_array_type, elements: items),
119
- )
120
-
121
- items_ref = IR::Name.new(name: items_name, type: items_array_type, pointer: false)
122
- IR::AggregateLiteral.new(
123
- type: boundary_type,
124
- fields: [
125
- IR::AggregateField.new(
126
- name: "data",
127
- value: IR::AddressOf.new(
128
- expression: IR::Index.new(
129
- receiver: items_ref,
130
- index: IR::IntegerLiteral.new(value: 0, type: len_type),
131
- type: boundary_element_type,
122
+ items_ref = IR::Name.new(name: items_name, type: items_array_type, pointer: false)
123
+ IR::AggregateLiteral.new(
124
+ type: boundary_type,
125
+ fields: [
126
+ IR::AggregateField.new(
127
+ name: "data",
128
+ value: IR::AddressOf.new(
129
+ expression: IR::Index.new(
130
+ receiver: items_ref,
131
+ index: IR::IntegerLiteral.new(value: 0, type: len_type),
132
+ type: boundary_element_type,
133
+ ),
134
+ type: pointer_to(boundary_element_type),
132
135
  ),
133
- type: pointer_to(boundary_element_type),
134
136
  ),
135
- ),
136
- IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: len, type: len_type)),
137
- ],
138
- )
139
- end
140
-
141
- def inlineable_foreign_argument_expression?(expression)
142
- case expression
143
- when IR::Name, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::ZeroInit, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
144
- true
145
- when IR::Call
146
- return false if temporary_foreign_cstr_expression?(expression)
147
-
148
- callee_inlineable = expression.callee.is_a?(String) || inlineable_foreign_argument_expression?(expression.callee)
149
- callee_inlineable && expression.arguments.all? { |argument| inlineable_foreign_argument_expression?(argument) }
150
- when IR::Member
151
- inlineable_foreign_argument_expression?(expression.receiver)
152
- when IR::Index
153
- inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
154
- when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
155
- inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
156
- when IR::Unary
157
- inlineable_foreign_argument_expression?(expression.operand)
158
- when IR::Binary
159
- inlineable_foreign_argument_expression?(expression.left) && inlineable_foreign_argument_expression?(expression.right)
160
- when IR::Conditional
161
- inlineable_foreign_argument_expression?(expression.condition) &&
162
- inlineable_foreign_argument_expression?(expression.then_expression) &&
163
- inlineable_foreign_argument_expression?(expression.else_expression)
164
- when IR::ReinterpretExpr, IR::Cast
165
- inlineable_foreign_argument_expression?(expression.expression)
166
- when IR::AddressOf
167
- inlineable_foreign_argument_expression?(expression.expression)
168
- when IR::AggregateLiteral
169
- expression.fields.all? { |field| inlineable_foreign_argument_expression?(field.value) }
170
- else
171
- false
137
+ IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: len, type: len_type)),
138
+ ],
139
+ )
172
140
  end
173
- end
174
141
 
175
- def lower_contextual_expression(expression, env:, expected_type:, external_numeric: false, contextual_int_to_float: false)
176
- if string_literal_cstr_compatibility?(expression, expected_type)
177
- return IR::StringLiteral.new(value: expression.value, type: expected_type, cstring: true)
142
+ def inlineable_foreign_argument_expression?(expression)
143
+ case expression
144
+ when IR::Name, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::ZeroInit, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
145
+ true
146
+ when IR::Call
147
+ return false if temporary_foreign_cstr_expression?(expression)
148
+
149
+ callee_inlineable = expression.callee.is_a?(String) || inlineable_foreign_argument_expression?(expression.callee)
150
+ callee_inlineable && expression.arguments.all? { |argument| inlineable_foreign_argument_expression?(argument) }
151
+ when IR::Member
152
+ inlineable_foreign_argument_expression?(expression.receiver)
153
+ when IR::Index
154
+ inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
155
+ when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
156
+ inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
157
+ when IR::Unary
158
+ inlineable_foreign_argument_expression?(expression.operand)
159
+ when IR::Binary
160
+ inlineable_foreign_argument_expression?(expression.left) && inlineable_foreign_argument_expression?(expression.right)
161
+ when IR::Conditional
162
+ inlineable_foreign_argument_expression?(expression.condition) &&
163
+ inlineable_foreign_argument_expression?(expression.then_expression) &&
164
+ inlineable_foreign_argument_expression?(expression.else_expression)
165
+ when IR::ReinterpretExpr, IR::Cast
166
+ inlineable_foreign_argument_expression?(expression.expression)
167
+ when IR::AddressOf
168
+ inlineable_foreign_argument_expression?(expression.expression)
169
+ when IR::AggregateLiteral
170
+ expression.fields.all? { |field| inlineable_foreign_argument_expression?(field.value) }
171
+ else
172
+ false
173
+ end
178
174
  end
179
175
 
180
- lowered = lower_expression(expression, env:, expected_type: expected_type)
181
- return lowered unless expected_type
182
- if (materialized = materialize_pointer_backed_value(lowered, expected_type))
183
- return materialized
176
+ def lower_contextual_expression(expression, env:, expected_type:, external_numeric: false, contextual_int_to_float: false)
177
+ if string_literal_cstr_compatibility?(expression, expected_type)
178
+ return IR::StringLiteral.new(value: expression.value, type: expected_type, cstring: true)
179
+ end
180
+
181
+ lowered = lower_expression(expression, env:, expected_type: expected_type)
182
+ return lowered unless expected_type
183
+ if (materialized = materialize_pointer_backed_value(lowered, expected_type))
184
+ return materialized
185
+ end
186
+ return lowered if lowered.type == expected_type
187
+ return lower_fn_to_proc_expression(expression, lowered, env:, expected_type:) if direct_function_to_proc_contextual_compatibility?(expression, lowered.type, env:, expected_type:)
188
+ return lower_str_buffer_to_span_expression(lowered, expected_type) if str_buffer_to_span_compatible?(lowered.type, expected_type)
189
+ return lower_array_to_span_expression(lowered, expected_type) if array_to_span_compatible?(lowered.type, expected_type)
190
+ return cast_expression(lowered, expected_type) if contextual_numeric_compatibility?(expression, lowered.type, expected_type, env:, external_numeric:, contextual_int_to_float:)
191
+
192
+ lowered
184
193
  end
185
- return lowered if lowered.type == expected_type
186
- return lower_direct_function_to_proc_expression(expression, lowered, env:, expected_type:) if direct_function_to_proc_contextual_compatibility?(expression, lowered.type, env:, expected_type:)
187
- return lower_str_buffer_to_span_expression(lowered, expected_type) if str_buffer_to_span_compatible?(lowered.type, expected_type)
188
- return lower_array_to_span_expression(lowered, expected_type) if array_to_span_compatible?(lowered.type, expected_type)
189
- return cast_expression(lowered, expected_type) if contextual_numeric_compatibility?(expression, lowered.type, expected_type, env:, external_numeric:, contextual_int_to_float:)
190
194
 
191
- lowered
192
- end
193
-
194
- def materialize_pointer_backed_value(lowered, expected_type)
195
- return nil unless lowered.is_a?(IR::Name) && lowered.pointer
196
- return nil unless lowered.type == expected_type
197
- return nil if ref_type?(expected_type)
198
- return nil if pointer_type?(expected_type)
195
+ def materialize_pointer_backed_value(lowered, expected_type)
196
+ return nil unless lowered.is_a?(IR::Name) && lowered.pointer
197
+ return nil unless lowered.type == expected_type
198
+ return nil if ref_type?(expected_type)
199
+ return nil if pointer_type?(expected_type)
199
200
 
200
- IR::Unary.new(operator: "*", operand: lowered, type: lowered.type)
201
+ IR::Unary.new(operator: "*", operand: lowered, type: lowered.type)
202
+ end
201
203
  end
202
204
  end
203
205
  end