mt-lang 0.3.6 → 0.3.8
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/aggregate_utils.rb +1 -1
- data/lib/milk_tea/core/c_backend/expressions.rb +3 -3
- data/lib/milk_tea/core/c_backend/statements.rb +5 -5
- data/lib/milk_tea/core/c_backend/type_system.rb +8 -8
- data/lib/milk_tea/core/control_flow/builder.rb +6 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +12 -12
- data/lib/milk_tea/core/lowering/async/normalization.rb +5 -5
- data/lib/milk_tea/core/lowering/async.rb +4 -2
- data/lib/milk_tea/core/lowering/block.rb +41 -21
- data/lib/milk_tea/core/lowering/calls.rb +25 -25
- data/lib/milk_tea/core/lowering/declarations.rb +2 -2
- data/lib/milk_tea/core/lowering/dyn.rb +2 -1
- data/lib/milk_tea/core/lowering/events.rb +1 -1
- data/lib/milk_tea/core/lowering/expressions.rb +26 -26
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +2 -2
- data/lib/milk_tea/core/lowering/functions.rb +1 -1
- data/lib/milk_tea/core/lowering/loops.rb +6 -6
- data/lib/milk_tea/core/lowering/proc.rb +3 -3
- data/lib/milk_tea/core/lowering/resolve.rb +81 -81
- data/lib/milk_tea/core/lowering/str_buffer.rb +1 -1
- data/lib/milk_tea/core/lowering/utils.rb +22 -22
- data/lib/milk_tea/core/lowering.rb +4 -2
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +12 -2
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +5 -1
- data/std/parse.mt +13 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 180f49844f839480b6aed67ca33f5aef4532cb0a372dce913699b892fc85c4b1
|
|
4
|
+
data.tar.gz: f99ec00f1749c5142694ff93211a9745cc1cbd0c53e7a1b311125a53aafedfd0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8874f3444b514ac33d33949a01d438a5de17139443e618ba2fc282a47fefc9138df686493eb368b116802750a03b844535f881a2ba48c3fae8fbcfbb4062b608
|
|
7
|
+
data.tar.gz: 0172adf373b345e1b3d40f79c4c0f3e05e2da088053af78b582f258cff87312dd2bac29ba2434bafab09630e13455c7f75ea32cb33a517694206e46a4f2ce95e
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -32,7 +32,7 @@ module MilkTea
|
|
|
32
32
|
|
|
33
33
|
visit = lambda do |aggregate_decl|
|
|
34
34
|
return if visited[aggregate_decl.linkage_name]
|
|
35
|
-
raise CBackendError
|
|
35
|
+
raise CBackendError.new("cyclic aggregate dependency involving #{aggregate_decl.linkage_name}", line: 0, column: 0, path: @path) if visiting[aggregate_decl.linkage_name]
|
|
36
36
|
|
|
37
37
|
visiting[aggregate_decl.linkage_name] = true
|
|
38
38
|
aggregate_decl_dependencies(aggregate_decl).each do |dependency|
|
|
@@ -105,7 +105,7 @@ module MilkTea
|
|
|
105
105
|
when IR::VariantLiteral
|
|
106
106
|
emit_variant_literal(expression)
|
|
107
107
|
else
|
|
108
|
-
raise CBackendError
|
|
108
|
+
raise CBackendError.new("unsupported IR expression #{expression.class.name}", line: 0, column: 0, path: @path)
|
|
109
109
|
end
|
|
110
110
|
end
|
|
111
111
|
|
|
@@ -163,7 +163,7 @@ module MilkTea
|
|
|
163
163
|
when "+", "-" then 9
|
|
164
164
|
when "*", "/", "%" then 10
|
|
165
165
|
else
|
|
166
|
-
raise CBackendError
|
|
166
|
+
raise CBackendError.new("unsupported binary operator #{operator}", line: 0, column: 0, path: @path)
|
|
167
167
|
end
|
|
168
168
|
end
|
|
169
169
|
|
|
@@ -408,7 +408,7 @@ module MilkTea
|
|
|
408
408
|
end
|
|
409
409
|
return type.field(field_name) if type.respond_to?(:field)
|
|
410
410
|
|
|
411
|
-
raise CBackendError
|
|
411
|
+
raise CBackendError.new("unsupported aggregate field lookup for #{type}", line: 0, column: 0, path: @path)
|
|
412
412
|
end
|
|
413
413
|
|
|
414
414
|
def emit_aggregate_field_initializer(type, field)
|
|
@@ -178,7 +178,7 @@ module MilkTea
|
|
|
178
178
|
lines
|
|
179
179
|
end
|
|
180
180
|
else
|
|
181
|
-
raise CBackendError
|
|
181
|
+
raise CBackendError.new("unsupported IR statement #{statement.class.name}", line: 0, column: 0, path: @path)
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
184
|
|
|
@@ -501,7 +501,7 @@ module MilkTea
|
|
|
501
501
|
when IR::CheckedSpanIndex
|
|
502
502
|
"#{checked_span_index_helper_name(expression.receiver_type)}(#{emit_expression(expression.receiver)}, #{emit_expression(expression.index)})"
|
|
503
503
|
else
|
|
504
|
-
raise CBackendError
|
|
504
|
+
raise CBackendError.new("unsupported checked index alias expression #{expression.class.name}", line: 0, column: 0, path: @path)
|
|
505
505
|
end
|
|
506
506
|
end
|
|
507
507
|
|
|
@@ -533,19 +533,19 @@ module MilkTea
|
|
|
533
533
|
def emit_for_clause_statement(statement)
|
|
534
534
|
case statement
|
|
535
535
|
when IR::LocalDecl
|
|
536
|
-
raise CBackendError
|
|
536
|
+
raise CBackendError.new("array for-loop init declarations are unsupported", line: 0, column: 0, path: @path) if array_type?(statement.type)
|
|
537
537
|
|
|
538
538
|
"#{c_declaration(statement.type, statement.linkage_name)} = #{emit_initializer(statement.value)}"
|
|
539
539
|
when IR::Assignment
|
|
540
540
|
if array_type?(statement.target.type) && statement.operator == "="
|
|
541
|
-
raise CBackendError
|
|
541
|
+
raise CBackendError.new("array for-loop assignment clauses are unsupported", line: 0, column: 0, path: @path)
|
|
542
542
|
end
|
|
543
543
|
|
|
544
544
|
"#{emit_expression(statement.target)} #{statement.operator} #{emit_expression(statement.value)}"
|
|
545
545
|
when IR::ExpressionStmt
|
|
546
546
|
emit_expression(statement.expression)
|
|
547
547
|
else
|
|
548
|
-
raise CBackendError
|
|
548
|
+
raise CBackendError.new("unsupported for-loop clause #{statement.class.name}", line: 0, column: 0, path: @path)
|
|
549
549
|
end
|
|
550
550
|
end
|
|
551
551
|
|
|
@@ -171,7 +171,7 @@ module MilkTea
|
|
|
171
171
|
when Types::Handle
|
|
172
172
|
"void*"
|
|
173
173
|
else
|
|
174
|
-
raise CBackendError
|
|
174
|
+
raise CBackendError.new("unsupported C type #{type.class.name}", line: 0, column: 0, path: @path)
|
|
175
175
|
end
|
|
176
176
|
end
|
|
177
177
|
|
|
@@ -261,33 +261,33 @@ module MilkTea
|
|
|
261
261
|
def generic_c_type(type)
|
|
262
262
|
case type.name
|
|
263
263
|
when "ptr"
|
|
264
|
-
raise CBackendError
|
|
264
|
+
raise CBackendError.new("ptr requires exactly one type argument", line: 0, column: 0, path: @path) unless type.arguments.length == 1
|
|
265
265
|
|
|
266
266
|
"#{c_type(type.arguments.first)}*"
|
|
267
267
|
when "const_ptr"
|
|
268
|
-
raise CBackendError
|
|
268
|
+
raise CBackendError.new("const_ptr requires exactly one type argument", line: 0, column: 0, path: @path) unless type.arguments.length == 1
|
|
269
269
|
|
|
270
270
|
"const #{c_type(type.arguments.first)}*"
|
|
271
271
|
when "own"
|
|
272
|
-
raise CBackendError
|
|
272
|
+
raise CBackendError.new("own requires exactly one type argument", line: 0, column: 0, path: @path) unless type.arguments.length == 1
|
|
273
273
|
|
|
274
274
|
"#{c_type(type.arguments.first)}*"
|
|
275
275
|
when "ref"
|
|
276
|
-
raise CBackendError
|
|
276
|
+
raise CBackendError.new("ref requires at least one type argument", line: 0, column: 0, path: @path) unless [1, 2].include?(type.arguments.length)
|
|
277
277
|
|
|
278
278
|
"#{c_type(type.arguments.length == 1 ? type.arguments.first : type.arguments[1])}*"
|
|
279
279
|
when "array"
|
|
280
|
-
raise CBackendError
|
|
280
|
+
raise CBackendError.new("array requires exactly two type arguments", line: 0, column: 0, path: @path) unless type.arguments.length == 2
|
|
281
281
|
|
|
282
282
|
c_type(type.arguments.first)
|
|
283
283
|
when "str_buffer"
|
|
284
|
-
raise CBackendError
|
|
284
|
+
raise CBackendError.new("str_buffer requires exactly one type argument", line: 0, column: 0, path: @path) unless str_buffer_type?(type)
|
|
285
285
|
|
|
286
286
|
str_buffer_type_name(type)
|
|
287
287
|
when "atomic"
|
|
288
288
|
"_Atomic #{c_type(type.arguments.first)}"
|
|
289
289
|
else
|
|
290
|
-
raise CBackendError
|
|
290
|
+
raise CBackendError.new("unsupported generic C type #{type.name}", line: 0, column: 0, path: @path)
|
|
291
291
|
end
|
|
292
292
|
end
|
|
293
293
|
|
|
@@ -137,7 +137,12 @@ module MilkTea
|
|
|
137
137
|
@graph.add_edge(match_id, next_id)
|
|
138
138
|
else
|
|
139
139
|
stmt.arms.each do |arm|
|
|
140
|
-
|
|
140
|
+
arm_body = if arm.respond_to?(:body)
|
|
141
|
+
arm.body
|
|
142
|
+
else
|
|
143
|
+
[MilkTea::AST::ExpressionStmt.new(expression: arm.value, line: arm.value.respond_to?(:line) ? arm.value.line : nil)]
|
|
144
|
+
end
|
|
145
|
+
arm_entry = build_block(arm_body, next_id, break_target:, continue_target:)
|
|
141
146
|
if arm.binding_name
|
|
142
147
|
binding_key = declaration_binding_key(arm, arm.binding_name)
|
|
143
148
|
if binding_key
|
|
@@ -119,8 +119,8 @@ module MilkTea
|
|
|
119
119
|
statement_position: false,
|
|
120
120
|
)
|
|
121
121
|
lowered.concat(setup)
|
|
122
|
-
raise LoweringError
|
|
123
|
-
raise LoweringError
|
|
122
|
+
raise LoweringError.new("foreign call used to initialize #{statement.name} must return a value", line: 0, column: 0, path: @ctx.current_analysis_path) if call_type == @ctx.types.fetch("void")
|
|
123
|
+
raise LoweringError.new("consuming foreign calls must return void", line: 0, column: 0, path: @ctx.current_analysis_path) unless release_assignments.empty?
|
|
124
124
|
|
|
125
125
|
lowered << IR::Assignment.new(target:, operator: "=", value:)
|
|
126
126
|
lowered.concat(cleanup_statements)
|
|
@@ -307,7 +307,7 @@ module MilkTea
|
|
|
307
307
|
when AST::StaticAssert
|
|
308
308
|
lowered.concat(lower_static_assert(statement))
|
|
309
309
|
else
|
|
310
|
-
raise LoweringError
|
|
310
|
+
raise LoweringError.new("unsupported async cf statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
311
311
|
end
|
|
312
312
|
end
|
|
313
313
|
|
|
@@ -412,7 +412,7 @@ module MilkTea
|
|
|
412
412
|
def lower_async_cf_collection_for_stmt(statement, env:, frame_expr:, raw_frame_expr:, resume_linkage_name:, async_info:, active_defers:)
|
|
413
413
|
iterable_type = infer_expression_type(statement.iterable, env:)
|
|
414
414
|
element_type = collection_loop_type(iterable_type)
|
|
415
|
-
raise LoweringError
|
|
415
|
+
raise LoweringError.new("for loop expects start..stop, array[T, N], or span[T], got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless element_type
|
|
416
416
|
|
|
417
417
|
iterable_setup, prepared_iterable = prepare_expression_for_inline_lowering(statement.iterable, env:, expected_type: iterable_type)
|
|
418
418
|
continue_label = fresh_c_temp_name(env, "loop_continue")
|
|
@@ -468,7 +468,7 @@ module MilkTea
|
|
|
468
468
|
iterable = statement.iterables[index]
|
|
469
469
|
iterable_type = infer_expression_type(iterable, env:)
|
|
470
470
|
element_type = collection_loop_type(iterable_type)
|
|
471
|
-
raise LoweringError
|
|
471
|
+
raise LoweringError.new("parallel for loops expect arrays or spans for each iterable, got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless element_type
|
|
472
472
|
|
|
473
473
|
{
|
|
474
474
|
binding:,
|
|
@@ -744,7 +744,7 @@ module MilkTea
|
|
|
744
744
|
when AST::StaticAssert
|
|
745
745
|
lowered << lower_static_assert(statement, env: local_env)
|
|
746
746
|
else
|
|
747
|
-
raise LoweringError
|
|
747
|
+
raise LoweringError.new("unsupported async non-await statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
748
748
|
end
|
|
749
749
|
end
|
|
750
750
|
|
|
@@ -837,7 +837,7 @@ module MilkTea
|
|
|
837
837
|
def lower_async_collection_for_stmt(statement, env:, frame_expr:, raw_frame_expr:, async_info:, active_defers: [])
|
|
838
838
|
iterable_type = infer_expression_type(statement.iterable, env:)
|
|
839
839
|
element_type = collection_loop_type(iterable_type)
|
|
840
|
-
raise LoweringError
|
|
840
|
+
raise LoweringError.new("for loop expects start..stop, array[T, N], or span[T], got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless element_type
|
|
841
841
|
|
|
842
842
|
iterable_setup, prepared_iterable = prepare_expression_for_inline_lowering(statement.iterable, env:, expected_type: iterable_type)
|
|
843
843
|
iterable_linkage_name = fresh_c_temp_name(env, "for_items")
|
|
@@ -896,7 +896,7 @@ module MilkTea
|
|
|
896
896
|
iterable = statement.iterables[index]
|
|
897
897
|
iterable_type = infer_expression_type(iterable, env:)
|
|
898
898
|
element_type = collection_loop_type(iterable_type)
|
|
899
|
-
raise LoweringError
|
|
899
|
+
raise LoweringError.new("parallel for loops expect arrays or spans for each iterable, got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless element_type
|
|
900
900
|
|
|
901
901
|
{
|
|
902
902
|
binding:,
|
|
@@ -998,8 +998,8 @@ module MilkTea
|
|
|
998
998
|
statement_position: false,
|
|
999
999
|
)
|
|
1000
1000
|
lowered.concat(setup)
|
|
1001
|
-
raise LoweringError
|
|
1002
|
-
raise LoweringError
|
|
1001
|
+
raise LoweringError.new("foreign call used in assignment must return a value", line: 0, column: 0, path: @ctx.current_analysis_path) if call_type == @ctx.types.fetch("void")
|
|
1002
|
+
raise LoweringError.new("consuming foreign calls must return void", line: 0, column: 0, path: @ctx.current_analysis_path) unless release_assignments.empty?
|
|
1003
1003
|
|
|
1004
1004
|
lowered << IR::Assignment.new(target:, operator: statement.operator, value:)
|
|
1005
1005
|
lowered.concat(cleanup_statements)
|
|
@@ -1135,7 +1135,7 @@ module MilkTea
|
|
|
1135
1135
|
expected_type: await_info[:task_type],
|
|
1136
1136
|
)
|
|
1137
1137
|
lowered.concat(prepared_setup)
|
|
1138
|
-
raise LoweringError
|
|
1138
|
+
raise LoweringError.new("await does not support foreign task expressions", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_call_info(prepared_task, env)
|
|
1139
1139
|
|
|
1140
1140
|
task_expr = async_frame_field_expression(frame_expr, await_info[:field_name], await_info[:task_type])
|
|
1141
1141
|
task_frame_expr = async_task_frame_expression(task_expr, await_info[:task_type])
|
|
@@ -1382,7 +1382,7 @@ module MilkTea
|
|
|
1382
1382
|
[loop_exit_statement(target, local_defers:, outer_defers:)]
|
|
1383
1383
|
else
|
|
1384
1384
|
label = target[:label]
|
|
1385
|
-
raise LoweringError
|
|
1385
|
+
raise LoweringError.new("structured loop exits with cleanup are unsupported", line: 0, column: 0, path: @ctx.current_analysis_path) unless label
|
|
1386
1386
|
|
|
1387
1387
|
cleanup + [IR::GotoStmt.new(label:)]
|
|
1388
1388
|
end
|
|
@@ -166,7 +166,7 @@ module MilkTea
|
|
|
166
166
|
when AST::BreakStmt, AST::ContinueStmt, AST::StaticAssert, AST::PassStmt
|
|
167
167
|
[statement]
|
|
168
168
|
else
|
|
169
|
-
raise LoweringError
|
|
169
|
+
raise LoweringError.new("unsupported async statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
|
|
@@ -210,10 +210,10 @@ module MilkTea
|
|
|
210
210
|
end
|
|
211
211
|
[setup, AST::Call.new(callee: target.callee, arguments: normalized_args)]
|
|
212
212
|
else
|
|
213
|
-
raise LoweringError
|
|
213
|
+
raise LoweringError.new("unsupported assignment target #{target.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
214
214
|
end
|
|
215
215
|
else
|
|
216
|
-
raise LoweringError
|
|
216
|
+
raise LoweringError.new("unsupported assignment target #{target.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
217
217
|
end
|
|
218
218
|
end
|
|
219
219
|
|
|
@@ -372,7 +372,7 @@ module MilkTea
|
|
|
372
372
|
AST::TypeRef.new(name: AST::QualifiedName.new(parts: [type.name]), arguments: [], nullable: false)
|
|
373
373
|
when Types::Nullable
|
|
374
374
|
inner = ast_type_ref_for(type.base)
|
|
375
|
-
raise LoweringError
|
|
375
|
+
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)
|
|
376
376
|
|
|
377
377
|
AST::TypeRef.new(name: inner.name, arguments: inner.arguments, nullable: true)
|
|
378
378
|
when Types::GenericInstance
|
|
@@ -420,7 +420,7 @@ module MilkTea
|
|
|
420
420
|
return_type: ast_type_ref_for(type.return_type),
|
|
421
421
|
)
|
|
422
422
|
else
|
|
423
|
-
raise LoweringError
|
|
423
|
+
raise LoweringError.new("unsupported type for AST normalization #{type.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
424
424
|
end
|
|
425
425
|
end
|
|
426
426
|
|
|
@@ -8,7 +8,8 @@ module MilkTea
|
|
|
8
8
|
def build_async_main_entrypoint(binding, _constructor_c_name, async_info)
|
|
9
9
|
task_type = async_info[:task_type]
|
|
10
10
|
signature = root_main_entrypoint_signature(binding)
|
|
11
|
-
raise LoweringError
|
|
11
|
+
raise LoweringError.new("async main entrypoint requires a supported signature",
|
|
12
|
+
line: 0, column: 0, path: @ctx.current_analysis_path) unless signature
|
|
12
13
|
|
|
13
14
|
params, setup_statements, call_arguments, cleanup_statements = build_root_main_entrypoint_bridge(signature)
|
|
14
15
|
body = []
|
|
@@ -229,7 +230,8 @@ module MilkTea
|
|
|
229
230
|
cleanup,
|
|
230
231
|
]
|
|
231
232
|
else
|
|
232
|
-
raise LoweringError
|
|
233
|
+
raise LoweringError.new("unsupported root main entrypoint bridge #{signature[:kind]}",
|
|
234
|
+
line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
233
235
|
end
|
|
234
236
|
end
|
|
235
237
|
|
|
@@ -55,11 +55,13 @@ module MilkTea
|
|
|
55
55
|
when AST::PassStmt
|
|
56
56
|
nil
|
|
57
57
|
when AST::BreakStmt
|
|
58
|
-
raise LoweringError
|
|
58
|
+
raise LoweringError.new("break must be inside a loop",
|
|
59
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) unless loop_flow
|
|
59
60
|
|
|
60
61
|
lowered.concat(lower_loop_exit(loop_flow[:break_target], local_defers, loop_flow[:break_defers]))
|
|
61
62
|
when AST::ContinueStmt
|
|
62
|
-
raise LoweringError
|
|
63
|
+
raise LoweringError.new("continue must be inside a loop",
|
|
64
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) unless loop_flow
|
|
63
65
|
|
|
64
66
|
lowered.concat(lower_loop_exit(loop_flow[:continue_target], local_defers, loop_flow[:continue_defers]))
|
|
65
67
|
when AST::ReturnStmt
|
|
@@ -71,7 +73,8 @@ module MilkTea
|
|
|
71
73
|
when AST::WhenStmt
|
|
72
74
|
lower_block_when_stmt(statement, lowered:, local_env:, active_defers:, return_type:, loop_flow:, allow_return:)
|
|
73
75
|
else
|
|
74
|
-
raise LoweringError
|
|
76
|
+
raise LoweringError.new("unsupported statement #{statement.class.name}",
|
|
77
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path)
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
80
|
|
|
@@ -85,7 +88,8 @@ module MilkTea
|
|
|
85
88
|
captures = proc_capture_entries(expression, env)
|
|
86
89
|
captures.each do |capture|
|
|
87
90
|
if ref_type?(capture[:type]) || contains_ref_type?(capture[:type])
|
|
88
|
-
raise LoweringError
|
|
91
|
+
raise LoweringError.new("proc capture #{capture[:name]} cannot use ref types",
|
|
92
|
+
line: expression.line, column: expression.column, path: @ctx.current_analysis_path)
|
|
89
93
|
end
|
|
90
94
|
end
|
|
91
95
|
|
|
@@ -279,7 +283,8 @@ module MilkTea
|
|
|
279
283
|
when AST::ConstDecl
|
|
280
284
|
lower_emitted_const(decl, env:)
|
|
281
285
|
else
|
|
282
|
-
raise LoweringError
|
|
286
|
+
raise LoweringError.new("emit is not supported for #{decl.class.name}",
|
|
287
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path)
|
|
283
288
|
end
|
|
284
289
|
end
|
|
285
290
|
|
|
@@ -451,7 +456,8 @@ module MilkTea
|
|
|
451
456
|
end
|
|
452
457
|
|
|
453
458
|
def lower_block_return_stmt(statement, lowered:, local_defers:, local_env:, active_defers:, return_type:, allow_return:)
|
|
454
|
-
raise LoweringError
|
|
459
|
+
raise LoweringError.new("return is not allowed inside defer blocks",
|
|
460
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) unless allow_return
|
|
455
461
|
|
|
456
462
|
value = nil
|
|
457
463
|
prepared_setup = []
|
|
@@ -478,7 +484,8 @@ module MilkTea
|
|
|
478
484
|
contextual_int_to_float: contextual_int_to_float_target?(return_type),
|
|
479
485
|
) : nil
|
|
480
486
|
if prepared_cleanups.any? && cstr_trackable_type?(return_type)
|
|
481
|
-
raise LoweringError
|
|
487
|
+
raise LoweringError.new("formatted string temporaries cannot be returned as borrowed text; use std.fmt.format(f\"...\") when ownership must escape",
|
|
488
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path)
|
|
482
489
|
end
|
|
483
490
|
|
|
484
491
|
prepared_cleanup_list = prepared_cleanups.flat_map(&:itself)
|
|
@@ -523,8 +530,10 @@ module MilkTea
|
|
|
523
530
|
statement_position: false,
|
|
524
531
|
)
|
|
525
532
|
lowered.concat(setup)
|
|
526
|
-
raise LoweringError
|
|
527
|
-
|
|
533
|
+
raise LoweringError.new("foreign call used in assignment must return a value",
|
|
534
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) if call_type == @ctx.types.fetch("void")
|
|
535
|
+
raise LoweringError.new("consuming foreign calls must return void",
|
|
536
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) unless release_assignments.empty?
|
|
528
537
|
|
|
529
538
|
lowered << IR::Assignment.new(target:, operator: statement.operator, value:)
|
|
530
539
|
lowered.concat(cleanup_statements)
|
|
@@ -713,8 +722,10 @@ module MilkTea
|
|
|
713
722
|
statement_position: false,
|
|
714
723
|
)
|
|
715
724
|
lowered.concat(setup)
|
|
716
|
-
raise LoweringError
|
|
717
|
-
|
|
725
|
+
raise LoweringError.new("foreign call used to initialize #{statement.name} must return a value",
|
|
726
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) if call_type == @ctx.types.fetch("void")
|
|
727
|
+
raise LoweringError.new("consuming foreign calls must return void",
|
|
728
|
+
line: statement.line, column: statement.column, path: @ctx.current_analysis_path) unless release_assignments.empty?
|
|
718
729
|
|
|
719
730
|
lowered << IR::LocalDecl.new(name: decl_name, linkage_name:, type: storage_type, value:, line: statement.line, source_path: @ctx.current_analysis_path)
|
|
720
731
|
lowered.concat(cleanup_statements)
|
|
@@ -927,16 +938,25 @@ module MilkTea
|
|
|
927
938
|
nested_struct_c_name = nil
|
|
928
939
|
nested_struct_type = nil
|
|
929
940
|
if fields.size == 1 && fields.values.first.is_a?(Types::Struct)
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
941
|
+
native_field = fields.keys.first
|
|
942
|
+
has_native_reference = arm.pattern.arguments.any? do |arg|
|
|
943
|
+
next false if !arg.name && arg.value.is_a?(AST::Identifier) && arg.value.name == "_"
|
|
944
|
+
|
|
945
|
+
name = arg.name || (arg.value.is_a?(AST::Identifier) ? arg.value.name : nil)
|
|
946
|
+
name == native_field
|
|
947
|
+
end
|
|
948
|
+
unless has_native_reference
|
|
949
|
+
nested_struct_type = fields.values.first
|
|
950
|
+
nested_struct_fields = nested_struct_type.fields
|
|
951
|
+
single_field_name = fields.keys.first
|
|
952
|
+
nested_struct_c_name = fresh_c_temp_name(arm_local_env, "match_struct")
|
|
953
|
+
struct_expr = IR::Member.new(
|
|
954
|
+
receiver: IR::Name.new(name: payload_c_name, type: payload_type, pointer: false),
|
|
955
|
+
member: single_field_name,
|
|
956
|
+
type: nested_struct_type,
|
|
957
|
+
)
|
|
958
|
+
arm_body_ir << IR::LocalDecl.new(name: nested_struct_c_name, linkage_name: nested_struct_c_name, type: nested_struct_type, value: struct_expr)
|
|
959
|
+
end
|
|
940
960
|
end
|
|
941
961
|
|
|
942
962
|
if arm.pattern.is_a?(AST::Call) && !arm.pattern.arguments.empty?
|