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
|
@@ -21,7 +21,7 @@ module MilkTea
|
|
|
21
21
|
case kind
|
|
22
22
|
when :function
|
|
23
23
|
if callee_binding && foreign_function_binding?(callee_binding)
|
|
24
|
-
raise LoweringError
|
|
24
|
+
raise LoweringError.new("consuming foreign calls must be top-level expression statements", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_call_consumes_binding?(callee_binding)
|
|
25
25
|
|
|
26
26
|
return lower_foreign_call_inline(expression, callee_binding, env:, type:)
|
|
27
27
|
end
|
|
@@ -287,7 +287,7 @@ module MilkTea
|
|
|
287
287
|
elsif receiver_type.is_a?(Types::Span)
|
|
288
288
|
IR::NullableSpanIndex.new(receiver:, index:, receiver_type:, type:)
|
|
289
289
|
else
|
|
290
|
-
raise LoweringError
|
|
290
|
+
raise LoweringError.new("get expects an array or span, got #{receiver_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
291
291
|
end
|
|
292
292
|
when :ref_of
|
|
293
293
|
argument = expression.arguments.fetch(0)
|
|
@@ -311,7 +311,7 @@ module MilkTea
|
|
|
311
311
|
when :dyn_method
|
|
312
312
|
lower_dyn_method_call(expression, receiver, callee_type, env:, type:)
|
|
313
313
|
else
|
|
314
|
-
raise LoweringError
|
|
314
|
+
raise LoweringError.new("unsupported call kind #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
315
315
|
end
|
|
316
316
|
end
|
|
317
317
|
|
|
@@ -488,7 +488,7 @@ module MilkTea
|
|
|
488
488
|
def lower_foreign_call_components(foreign_call, env:, expected_type:, statement_position:)
|
|
489
489
|
call = foreign_call.fetch(:call)
|
|
490
490
|
binding = foreign_call.fetch(:binding)
|
|
491
|
-
raise LoweringError
|
|
491
|
+
raise LoweringError.new("consuming foreign calls must be top-level expression statements", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_call_consumes_binding?(binding) && !statement_position
|
|
492
492
|
|
|
493
493
|
previous_type_substitutions = @ctx.current_type_substitutions
|
|
494
494
|
@ctx.current_type_substitutions = binding.type_substitutions
|
|
@@ -540,7 +540,7 @@ module MilkTea
|
|
|
540
540
|
return [lowered, nil]
|
|
541
541
|
end
|
|
542
542
|
|
|
543
|
-
raise LoweringError
|
|
543
|
+
raise LoweringError.new("consuming foreign calls must return void", line: 0, column: 0, path: @ctx.current_analysis_path) unless release_assignments.empty?
|
|
544
544
|
|
|
545
545
|
if discard_result
|
|
546
546
|
lowered << IR::ExpressionStmt.new(expression: lowered_call)
|
|
@@ -583,12 +583,12 @@ module MilkTea
|
|
|
583
583
|
|
|
584
584
|
argument = call.arguments.fetch(index)
|
|
585
585
|
unless argument.value.is_a?(AST::Identifier)
|
|
586
|
-
raise LoweringError
|
|
586
|
+
raise LoweringError.new("consuming foreign calls require bare nullable local or parameter bindings", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
587
587
|
end
|
|
588
588
|
|
|
589
589
|
lowered_binding = lookup_value(argument.value.name, env)
|
|
590
590
|
unless lowered_binding && lowered_binding[:storage_type].is_a?(Types::Nullable) && lowered_binding[:storage_type].base == parameter.type
|
|
591
|
-
raise LoweringError
|
|
591
|
+
raise LoweringError.new("consuming foreign calls require bare nullable local or parameter bindings", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
592
592
|
end
|
|
593
593
|
|
|
594
594
|
lowered_binding.merge(name: argument.value.name)
|
|
@@ -757,14 +757,14 @@ module MilkTea
|
|
|
757
757
|
converted = foreign_identity_projection_expression(lowered_value, parameter.boundary_type)
|
|
758
758
|
return converted if converted
|
|
759
759
|
|
|
760
|
-
raise LoweringError
|
|
760
|
+
raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{parameter.boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
761
761
|
end
|
|
762
762
|
when :in
|
|
763
763
|
lower_foreign_in_argument_value(parameter, argument, env:)
|
|
764
764
|
when :out, :inout
|
|
765
765
|
lower_foreign_pointer_argument_value(parameter, argument, env:)
|
|
766
766
|
else
|
|
767
|
-
raise LoweringError
|
|
767
|
+
raise LoweringError.new("unsupported foreign passing mode #{parameter.passing_mode}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
768
768
|
end
|
|
769
769
|
end
|
|
770
770
|
|
|
@@ -779,7 +779,7 @@ module MilkTea
|
|
|
779
779
|
|
|
780
780
|
data_expression = IR::Member.new(receiver: lowered_value, member: "data", type: pointer_to(public_element_type))
|
|
781
781
|
converted_data = foreign_identity_projection_expression(data_expression, pointer_to(boundary_element_type))
|
|
782
|
-
raise LoweringError
|
|
782
|
+
raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
|
|
783
783
|
|
|
784
784
|
len_expression = IR::Member.new(receiver: lowered_value, member: "len", type: @ctx.types.fetch("ptr_uint"))
|
|
785
785
|
IR::AggregateLiteral.new(
|
|
@@ -799,7 +799,7 @@ module MilkTea
|
|
|
799
799
|
converted = foreign_identity_projection_expression(address, parameter.boundary_type)
|
|
800
800
|
return converted if converted
|
|
801
801
|
|
|
802
|
-
raise LoweringError
|
|
802
|
+
raise LoweringError.new("unsupported foreign pointer boundary mapping #{parameter.type} as #{parameter.boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
803
803
|
end
|
|
804
804
|
|
|
805
805
|
def foreign_slot_boundary_value_type(type)
|
|
@@ -841,7 +841,7 @@ module MilkTea
|
|
|
841
841
|
converted = foreign_identity_projection_expression(address, parameter.boundary_type)
|
|
842
842
|
return converted if converted
|
|
843
843
|
|
|
844
|
-
raise LoweringError
|
|
844
|
+
raise LoweringError.new("unsupported foreign in boundary mapping #{parameter.type} as #{parameter.boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
845
845
|
end
|
|
846
846
|
|
|
847
847
|
def lower_foreign_char_pointer_buffer_argument_value(parameter, argument, env:)
|
|
@@ -869,7 +869,7 @@ module MilkTea
|
|
|
869
869
|
converted = foreign_identity_projection_expression(lowered_value, parameter.boundary_type)
|
|
870
870
|
return converted if converted
|
|
871
871
|
|
|
872
|
-
raise LoweringError
|
|
872
|
+
raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{parameter.boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
873
873
|
end
|
|
874
874
|
|
|
875
875
|
def lower_foreign_call_inline(expression, binding, env:, type:)
|
|
@@ -888,7 +888,7 @@ module MilkTea
|
|
|
888
888
|
next unless total_references > 1
|
|
889
889
|
next if duplicable_foreign_argument_expression?(expression.arguments.fetch(index).value)
|
|
890
890
|
|
|
891
|
-
raise LoweringError
|
|
891
|
+
raise LoweringError.new("foreign call #{binding.name} cannot be used inline because #{param_ast.name} is referenced multiple times in its mapping; use it as a statement, local initializer, assignment, or return expression", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
892
892
|
end
|
|
893
893
|
|
|
894
894
|
binding.ast.params.each_with_index do |param_ast, index|
|
|
@@ -896,13 +896,13 @@ module MilkTea
|
|
|
896
896
|
next unless automatic_foreign_cstr_temp_needed?(parameter, expression.arguments.fetch(index).value, env:) ||
|
|
897
897
|
automatic_foreign_cstr_list_temp_needed?(parameter, expression.arguments.fetch(index).value, env:)
|
|
898
898
|
|
|
899
|
-
raise LoweringError
|
|
899
|
+
raise LoweringError.new("foreign call #{binding.name} cannot be used inline because #{param_ast.name} needs temporary foreign text storage; use it as a statement, local initializer, assignment, or return expression", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
900
900
|
end
|
|
901
901
|
|
|
902
902
|
expression.arguments.drop(binding.type.params.length).each do |argument|
|
|
903
903
|
next unless automatic_variadic_foreign_cstr_temp_needed?(argument.value, env:)
|
|
904
904
|
|
|
905
|
-
raise LoweringError
|
|
905
|
+
raise LoweringError.new("foreign call #{binding.name} cannot be used inline because a variadic argument needs temporary foreign text storage; use it as a statement, local initializer, assignment, or return expression", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
906
906
|
end
|
|
907
907
|
|
|
908
908
|
binding.ast.params.each_with_index do |param_ast, index|
|
|
@@ -911,7 +911,7 @@ module MilkTea
|
|
|
911
911
|
next unless parameter.passing_mode == :in
|
|
912
912
|
next if addressable_storage_expression?(foreign_argument_expression(argument))
|
|
913
913
|
|
|
914
|
-
raise LoweringError
|
|
914
|
+
raise LoweringError.new("foreign call #{binding.name} cannot be used inline because #{param_ast.name} needs temporary in storage; use it as a statement, local initializer, assignment, or return expression", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
915
915
|
end
|
|
916
916
|
|
|
917
917
|
replacements = {}
|
|
@@ -978,7 +978,7 @@ module MilkTea
|
|
|
978
978
|
)
|
|
979
979
|
return lowered_argument unless temporary_foreign_cstr_expression?(lowered_argument)
|
|
980
980
|
|
|
981
|
-
raise LoweringError
|
|
981
|
+
raise LoweringError.new("foreign variadic call cannot be used inline because an extra argument needs temporary foreign text storage; use it as a statement, local initializer, assignment, or return expression", line: 0, column: 0, path: @ctx.current_analysis_path) unless lowered && cleanup
|
|
982
982
|
|
|
983
983
|
temp_name = fresh_c_temp_name(env, "foreign_arg")
|
|
984
984
|
lowered << IR::LocalDecl.new(
|
|
@@ -1128,7 +1128,7 @@ module MilkTea
|
|
|
1128
1128
|
|
|
1129
1129
|
case kind
|
|
1130
1130
|
when :function
|
|
1131
|
-
raise LoweringError
|
|
1131
|
+
raise LoweringError.new("consuming foreign calls must be top-level expression statements", line: 0, column: 0, path: @ctx.current_analysis_path) if callee_binding && foreign_function_binding?(callee_binding) && foreign_call_consumes_binding?(callee_binding)
|
|
1132
1132
|
|
|
1133
1133
|
arguments = expression.arguments.map.with_index do |argument, index|
|
|
1134
1134
|
expected_arg_type = index < callee_type.params.length ? callee_type.params[index].type : nil
|
|
@@ -1301,7 +1301,7 @@ module MilkTea
|
|
|
1301
1301
|
)
|
|
1302
1302
|
end
|
|
1303
1303
|
else
|
|
1304
|
-
raise LoweringError
|
|
1304
|
+
raise LoweringError.new("unsupported inline foreign mapping call kind #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1305
1305
|
end
|
|
1306
1306
|
end
|
|
1307
1307
|
|
|
@@ -1537,9 +1537,9 @@ module MilkTea
|
|
|
1537
1537
|
|
|
1538
1538
|
if (callable_resolution = resolve_specialized_callable_binding(expression, env:))
|
|
1539
1539
|
callable_kind, function_binding, = callable_resolution
|
|
1540
|
-
raise LoweringError
|
|
1540
|
+
raise LoweringError.new("specialized method must be called", line: 0, column: 0, path: @ctx.current_analysis_path) if callable_kind == :method
|
|
1541
1541
|
|
|
1542
|
-
raise LoweringError
|
|
1542
|
+
raise LoweringError.new("foreign function #{function_binding.name} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_function_binding?(function_binding)
|
|
1543
1543
|
|
|
1544
1544
|
if function_binding.external
|
|
1545
1545
|
return IR::Name.new(name: external_function_c_name(function_binding), type:, pointer: false)
|
|
@@ -1552,9 +1552,9 @@ module MilkTea
|
|
|
1552
1552
|
)
|
|
1553
1553
|
end
|
|
1554
1554
|
|
|
1555
|
-
raise LoweringError
|
|
1555
|
+
raise LoweringError.new("specialization #{expression.callee.name} must be called", line: 0, column: 0, path: @ctx.current_analysis_path) if expression.callee.is_a?(AST::Identifier)
|
|
1556
1556
|
|
|
1557
|
-
raise LoweringError
|
|
1557
|
+
raise LoweringError.new("unsupported specialization #{expression.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1558
1558
|
end
|
|
1559
1559
|
|
|
1560
1560
|
def atomic_method_kind(receiver_type, name)
|
|
@@ -1602,7 +1602,7 @@ module MilkTea
|
|
|
1602
1602
|
arg = lower_contextual_expression(expression.arguments.first.value, env:, expected_type: elem_type)
|
|
1603
1603
|
IR::Call.new(callee: "__atomic_exchange_n", arguments: [addr, arg, seq_cst], type: elem_type)
|
|
1604
1604
|
when :atomic_compare_exchange
|
|
1605
|
-
raise LoweringError
|
|
1605
|
+
raise LoweringError.new("atomic compare_exchange is not yet implemented in the built-in surface; use std.sync.AtomicUint for compare-exchange operations", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1606
1606
|
end
|
|
1607
1607
|
end
|
|
1608
1608
|
|
|
@@ -76,7 +76,7 @@ module MilkTea
|
|
|
76
76
|
when Hash
|
|
77
77
|
fields = const_value.map do |name, field_value|
|
|
78
78
|
field_type = type.field(name)
|
|
79
|
-
raise LoweringError
|
|
79
|
+
raise LoweringError.new("constant struct field #{name} not found in #{type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless field_type
|
|
80
80
|
IR::AggregateField.new(name:, value: lower_const_value_literal(field_type, field_value))
|
|
81
81
|
end
|
|
82
82
|
IR::AggregateLiteral.new(type:, fields:)
|
|
@@ -131,7 +131,7 @@ module MilkTea
|
|
|
131
131
|
|
|
132
132
|
def lower_static_assert(statement, env:)
|
|
133
133
|
condition_value = compile_time_const_value(statement.condition, env:)
|
|
134
|
-
raise LoweringError
|
|
134
|
+
raise LoweringError.new("static_assert condition must lower to a compile-time bool constant", line: 0, column: 0, path: @ctx.current_analysis_path) unless condition_value == true || condition_value == false
|
|
135
135
|
|
|
136
136
|
IR::StaticAssert.new(
|
|
137
137
|
condition: IR::BooleanLiteral.new(value: condition_value, type: @ctx.types.fetch("bool")),
|
|
@@ -110,7 +110,8 @@ module MilkTea
|
|
|
110
110
|
|
|
111
111
|
interface.methods.each do |method_name, method_binding|
|
|
112
112
|
method_info = @method_definitions[[concrete_type, method_name]]
|
|
113
|
-
raise LoweringError
|
|
113
|
+
raise LoweringError.new("no method #{method_name} for #{concrete_type}",
|
|
114
|
+
line: 0, column: 0, path: @ctx.current_analysis_path) unless method_info
|
|
114
115
|
|
|
115
116
|
method_analysis, method_ast = method_info
|
|
116
117
|
method_key = method_ast.kind == :static ? "static:#{method_ast.name}" : method_ast.name
|
|
@@ -46,7 +46,7 @@ module MilkTea
|
|
|
46
46
|
when :event_wait
|
|
47
47
|
Types::Registry.function(kind.to_s, params: [], return_type: Types::Registry.task(event_wait_result_type(event_type)))
|
|
48
48
|
else
|
|
49
|
-
raise LoweringError
|
|
49
|
+
raise LoweringError.new("unsupported event method #{kind}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -283,7 +283,7 @@ module MilkTea
|
|
|
283
283
|
parameter_type: append_argument_type,
|
|
284
284
|
}
|
|
285
285
|
else
|
|
286
|
-
raise LoweringError
|
|
286
|
+
raise LoweringError.new("unsupported format spec #{part.format_spec.inspect}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
287
287
|
end
|
|
288
288
|
else
|
|
289
289
|
append_plan = format_string_append_plan(value_type, context: "formatted string interpolation of #{value_type}")
|
|
@@ -434,7 +434,7 @@ module MilkTea
|
|
|
434
434
|
capacity: IR::IntegerLiteral.new(value: str_buffer_capacity(lowered_receiver.type), type: @ctx.types.fetch("ptr_uint")),
|
|
435
435
|
}
|
|
436
436
|
else
|
|
437
|
-
raise LoweringError
|
|
437
|
+
raise LoweringError.new("unsupported explicit format sink #{info[:sink_kind]}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
438
438
|
end
|
|
439
439
|
end
|
|
440
440
|
|
|
@@ -451,7 +451,7 @@ module MilkTea
|
|
|
451
451
|
],
|
|
452
452
|
)
|
|
453
453
|
else
|
|
454
|
-
raise LoweringError
|
|
454
|
+
raise LoweringError.new("unsupported explicit format sink #{sink_target[:kind]}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
455
455
|
end
|
|
456
456
|
end
|
|
457
457
|
|
|
@@ -560,7 +560,7 @@ module MilkTea
|
|
|
560
560
|
value: offset_value,
|
|
561
561
|
)
|
|
562
562
|
else
|
|
563
|
-
raise LoweringError
|
|
563
|
+
raise LoweringError.new("unsupported explicit format sink #{sink_target[:kind]}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
564
564
|
end
|
|
565
565
|
|
|
566
566
|
sink_statements.concat(copied_part_cleanups)
|
|
@@ -588,7 +588,7 @@ module MilkTea
|
|
|
588
588
|
type: @ctx.types.fetch("void"),
|
|
589
589
|
)
|
|
590
590
|
else
|
|
591
|
-
raise LoweringError
|
|
591
|
+
raise LoweringError.new("unsupported explicit format sink #{sink_target[:kind]}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
592
592
|
end
|
|
593
593
|
end
|
|
594
594
|
|
|
@@ -820,7 +820,7 @@ module MilkTea
|
|
|
820
820
|
end
|
|
821
821
|
|
|
822
822
|
if part[:kind] == :custom_expression
|
|
823
|
-
raise LoweringError
|
|
823
|
+
raise LoweringError.new("custom format parts require statement lowering", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
824
824
|
end
|
|
825
825
|
|
|
826
826
|
IR::Call.new(
|
|
@@ -837,7 +837,7 @@ module MilkTea
|
|
|
837
837
|
when :append
|
|
838
838
|
part[:format_binding].append_binding
|
|
839
839
|
else
|
|
840
|
-
raise LoweringError
|
|
840
|
+
raise LoweringError.new("unsupported custom format hook #{hook}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
841
841
|
end
|
|
842
842
|
|
|
843
843
|
if env
|
|
@@ -883,7 +883,7 @@ module MilkTea
|
|
|
883
883
|
}
|
|
884
884
|
end
|
|
885
885
|
|
|
886
|
-
raise LoweringError
|
|
886
|
+
raise LoweringError.new("formatted string interpolation supports str, cstr, bool, numeric primitives, integer-backed enums/flags, and types implementing format_len()/append_format(output: ref[std.string.String]), got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
887
887
|
end
|
|
888
888
|
|
|
889
889
|
def format_string_hex_append_plan(type, uppercase:)
|
|
@@ -892,7 +892,7 @@ module MilkTea
|
|
|
892
892
|
end
|
|
893
893
|
|
|
894
894
|
unless type.is_a?(Types::Primitive) && type.integer?
|
|
895
|
-
raise LoweringError
|
|
895
|
+
raise LoweringError.new("format spec ':x' and ':X' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
896
896
|
end
|
|
897
897
|
|
|
898
898
|
if type.signed_integer?
|
|
@@ -903,7 +903,7 @@ module MilkTea
|
|
|
903
903
|
return [uppercase ? "append_ulong_hex_upper" : "append_ulong_hex", @ctx.types.fetch("ulong")]
|
|
904
904
|
end
|
|
905
905
|
|
|
906
|
-
raise LoweringError
|
|
906
|
+
raise LoweringError.new("format spec ':x' and ':X' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
907
907
|
end
|
|
908
908
|
|
|
909
909
|
def format_string_oct_append_plan(type, uppercase:)
|
|
@@ -913,7 +913,7 @@ module MilkTea
|
|
|
913
913
|
end
|
|
914
914
|
|
|
915
915
|
unless type.is_a?(Types::Primitive) && type.integer?
|
|
916
|
-
raise LoweringError
|
|
916
|
+
raise LoweringError.new("format spec ':o' and ':O' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
917
917
|
end
|
|
918
918
|
|
|
919
919
|
if type.signed_integer?
|
|
@@ -924,7 +924,7 @@ module MilkTea
|
|
|
924
924
|
return ["append_ulong_oct", @ctx.types.fetch("ulong")]
|
|
925
925
|
end
|
|
926
926
|
|
|
927
|
-
raise LoweringError
|
|
927
|
+
raise LoweringError.new("format spec ':o' and ':O' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
928
928
|
end
|
|
929
929
|
|
|
930
930
|
def format_string_bin_append_plan(type, uppercase:)
|
|
@@ -934,7 +934,7 @@ module MilkTea
|
|
|
934
934
|
end
|
|
935
935
|
|
|
936
936
|
unless type.is_a?(Types::Primitive) && type.integer?
|
|
937
|
-
raise LoweringError
|
|
937
|
+
raise LoweringError.new("format spec ':b' and ':B' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
938
938
|
end
|
|
939
939
|
|
|
940
940
|
if type.signed_integer?
|
|
@@ -945,7 +945,7 @@ module MilkTea
|
|
|
945
945
|
return ["append_ulong_bin", @ctx.types.fetch("ulong")]
|
|
946
946
|
end
|
|
947
947
|
|
|
948
|
-
raise LoweringError
|
|
948
|
+
raise LoweringError.new("format spec ':b' and ':B' require integer interpolation, got #{type}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
949
949
|
end
|
|
950
950
|
|
|
951
951
|
def mt_format_length_c_name(name)
|
|
@@ -1261,7 +1261,7 @@ module MilkTea
|
|
|
1261
1261
|
end
|
|
1262
1262
|
|
|
1263
1263
|
def materialize_prepared_expression(setup, value, env:, type:, prefix:)
|
|
1264
|
-
raise LoweringError
|
|
1264
|
+
raise LoweringError.new("cannot use void expression inline", line: 0, column: 0, path: @ctx.current_analysis_path) unless value
|
|
1265
1265
|
|
|
1266
1266
|
if value.is_a?(IR::Name)
|
|
1267
1267
|
register_prepared_temp!(env, value.name, value.type, pointer: value.pointer)
|
|
@@ -1316,7 +1316,7 @@ module MilkTea
|
|
|
1316
1316
|
|
|
1317
1317
|
case expression
|
|
1318
1318
|
when AST::AwaitExpr
|
|
1319
|
-
raise LoweringError
|
|
1319
|
+
raise LoweringError.new("await expressions must be lowered in async statement context", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1320
1320
|
when AST::IntegerLiteral
|
|
1321
1321
|
IR::IntegerLiteral.new(value: expression.value, type:)
|
|
1322
1322
|
when AST::CharLiteral
|
|
@@ -1341,7 +1341,7 @@ module MilkTea
|
|
|
1341
1341
|
when AST::StringLiteral
|
|
1342
1342
|
IR::StringLiteral.new(value: expression.value, type:, cstring: expression.cstring)
|
|
1343
1343
|
when AST::FormatString
|
|
1344
|
-
raise LoweringError
|
|
1344
|
+
raise LoweringError.new("unprepared format string reached raw lowering; format strings should be materialized before direct lowering", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1345
1345
|
when AST::BooleanLiteral
|
|
1346
1346
|
IR::BooleanLiteral.new(value: expression.value, type:)
|
|
1347
1347
|
when AST::NullLiteral
|
|
@@ -1352,12 +1352,12 @@ module MilkTea
|
|
|
1352
1352
|
lower_bound_identifier(binding, expected_type:)
|
|
1353
1353
|
elsif @ctx.functions.key?(expression.name)
|
|
1354
1354
|
function_binding = @ctx.functions.fetch(expression.name)
|
|
1355
|
-
raise LoweringError
|
|
1356
|
-
raise LoweringError
|
|
1355
|
+
raise LoweringError.new("generic function #{expression.name} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if function_binding.type_params.any?
|
|
1356
|
+
raise LoweringError.new("foreign function #{expression.name} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_function_binding?(function_binding)
|
|
1357
1357
|
|
|
1358
1358
|
IR::Name.new(name: function_binding_c_name(function_binding, module_name: @ctx.module_name), type: type, pointer: false)
|
|
1359
1359
|
else
|
|
1360
|
-
raise LoweringError
|
|
1360
|
+
raise LoweringError.new("unsupported identifier #{expression.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1361
1361
|
end
|
|
1362
1362
|
when AST::MemberAccess
|
|
1363
1363
|
lower_member_access(expression, env:, type:)
|
|
@@ -1373,7 +1373,7 @@ module MilkTea
|
|
|
1373
1373
|
IR::Index.new(receiver:, index:, type:)
|
|
1374
1374
|
end
|
|
1375
1375
|
when AST::UnaryOp
|
|
1376
|
-
raise LoweringError
|
|
1376
|
+
raise LoweringError.new("propagation expressions must be prepared before direct lowering", line: 0, column: 0, path: @ctx.current_analysis_path) if expression.operator == "?"
|
|
1377
1377
|
|
|
1378
1378
|
operand = lower_expression(expression.operand, env:, expected_type: type)
|
|
1379
1379
|
expanded = lower_vector_unary_op(expression.operator, operand, type)
|
|
@@ -1403,7 +1403,7 @@ module MilkTea
|
|
|
1403
1403
|
type:,
|
|
1404
1404
|
)
|
|
1405
1405
|
when AST::MatchExpr
|
|
1406
|
-
raise LoweringError
|
|
1406
|
+
raise LoweringError.new("match expressions must be prepared before direct lowering", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1407
1407
|
when AST::UnsafeExpr
|
|
1408
1408
|
lower_expression(expression.expression, env:, expected_type: type)
|
|
1409
1409
|
when AST::ProcExpr
|
|
@@ -1444,7 +1444,7 @@ module MilkTea
|
|
|
1444
1444
|
IR::AggregateLiteral.new(type:, fields:)
|
|
1445
1445
|
end
|
|
1446
1446
|
else
|
|
1447
|
-
raise LoweringError
|
|
1447
|
+
raise LoweringError.new("unsupported expression #{expression.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
1448
1448
|
end
|
|
1449
1449
|
end
|
|
1450
1450
|
|
|
@@ -1466,8 +1466,8 @@ module MilkTea
|
|
|
1466
1466
|
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
1467
1467
|
if imported_module.functions.key?(expression.member)
|
|
1468
1468
|
function_binding = imported_module.functions.fetch(expression.member)
|
|
1469
|
-
raise LoweringError
|
|
1470
|
-
raise LoweringError
|
|
1469
|
+
raise LoweringError.new("generic function #{expression.receiver.name}.#{expression.member} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if function_binding.type_params.any?
|
|
1470
|
+
raise LoweringError.new("foreign function #{expression.receiver.name}.#{expression.member} cannot be used as a value", line: 0, column: 0, path: @ctx.current_analysis_path) if foreign_function_binding?(function_binding)
|
|
1471
1471
|
|
|
1472
1472
|
return IR::Name.new(name: function_binding_c_name(function_binding, module_name: imported_module.name), type:, pointer: false)
|
|
1473
1473
|
end
|
|
@@ -1611,7 +1611,7 @@ module MilkTea
|
|
|
1611
1611
|
|
|
1612
1612
|
def lower_soa_indexed_field_access(soa_base, index_expr, field_name, soa_type, env:, type:)
|
|
1613
1613
|
field_type = soa_type.fields[field_name]
|
|
1614
|
-
raise LoweringError
|
|
1614
|
+
raise LoweringError.new("SoA type #{soa_type} has no field #{field_name}", line: 0, column: 0, path: @ctx.current_analysis_path) unless field_type
|
|
1615
1615
|
|
|
1616
1616
|
receiver = lower_expression(soa_base, env:)
|
|
1617
1617
|
index = lower_expression(index_expr, env:)
|
|
@@ -65,7 +65,7 @@ module MilkTea
|
|
|
65
65
|
IR::Name.new(name: items_name, type: items_type, pointer: false),
|
|
66
66
|
pointer_to(boundary_type.element_type),
|
|
67
67
|
)
|
|
68
|
-
raise LoweringError
|
|
68
|
+
raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
|
|
69
69
|
|
|
70
70
|
IR::AggregateLiteral.new(
|
|
71
71
|
type: boundary_type,
|
|
@@ -109,7 +109,7 @@ module MilkTea
|
|
|
109
109
|
item = IR::Member.new(receiver: item, member: "data", type: pointer_to(@ctx.types.fetch("char"))) if item_type == @ctx.types.fetch("str")
|
|
110
110
|
|
|
111
111
|
converted = foreign_identity_projection_expression(item, boundary_element_type)
|
|
112
|
-
raise LoweringError
|
|
112
|
+
raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted
|
|
113
113
|
|
|
114
114
|
converted
|
|
115
115
|
end
|
|
@@ -107,7 +107,7 @@ module MilkTea
|
|
|
107
107
|
return imported_module.types.fetch(parts.last)
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
raise LoweringError
|
|
110
|
+
raise LoweringError.new("unsupported extending target #{type_name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
def lower_function_decl(binding, receiver_type: nil)
|
|
@@ -133,7 +133,7 @@ module MilkTea
|
|
|
133
133
|
def lower_collection_for_stmt(statement, env:, active_defers:, return_type:, allow_return:)
|
|
134
134
|
iterable_type = infer_expression_type(statement.iterable, env:)
|
|
135
135
|
element_type = collection_loop_type(iterable_type)
|
|
136
|
-
raise LoweringError
|
|
136
|
+
raise LoweringError.new("for loop expects start..stop, array[T, N], span[T], or an iterable with iter()/next(), got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless element_type
|
|
137
137
|
iterable_setup, prepared_iterable = prepare_expression_for_inline_lowering(statement.iterable, env:, expected_type: iterable_type)
|
|
138
138
|
binding_type = collection_loop_binding_type(iterable_type, element_type) || element_type
|
|
139
139
|
|
|
@@ -207,7 +207,7 @@ module MilkTea
|
|
|
207
207
|
iterable = statement.iterables[index]
|
|
208
208
|
iterable_type = infer_expression_type(iterable, env:)
|
|
209
209
|
element_type = collection_loop_type(iterable_type)
|
|
210
|
-
raise LoweringError
|
|
210
|
+
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
|
|
211
211
|
|
|
212
212
|
{
|
|
213
213
|
binding:,
|
|
@@ -304,7 +304,7 @@ module MilkTea
|
|
|
304
304
|
def lower_iterator_for_stmt(statement, env:, active_defers:, return_type:, allow_return:)
|
|
305
305
|
iterable_type = infer_expression_type(statement.iterable, env:)
|
|
306
306
|
iterator_info = iterator_loop_info(iterable_type, env:)
|
|
307
|
-
raise LoweringError
|
|
307
|
+
raise LoweringError.new("for loop expects start..stop, array[T, N], span[T], or an iterable with iter()/next(), got #{iterable_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless iterator_info
|
|
308
308
|
|
|
309
309
|
iterable_setup, prepared_iterable = prepare_expression_for_inline_lowering(statement.iterable, env:, expected_type: iterable_type)
|
|
310
310
|
iterator_c_name = fresh_c_temp_name(env, "for_iterator")
|
|
@@ -809,7 +809,7 @@ module MilkTea
|
|
|
809
809
|
if captures.empty?
|
|
810
810
|
worker_body = block_body.dup
|
|
811
811
|
else
|
|
812
|
-
raise LoweringError
|
|
812
|
+
raise LoweringError.new("detach with captured variables is not yet supported; use a global function call or module-level variables", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
813
813
|
end
|
|
814
814
|
|
|
815
815
|
@artifacts.synthetic_functions << IR::Function.new(
|
|
@@ -833,7 +833,7 @@ module MilkTea
|
|
|
833
833
|
|
|
834
834
|
def validate_pfor_no_ref_captures!(captures)
|
|
835
835
|
captures.each do |c|
|
|
836
|
-
raise LoweringError
|
|
836
|
+
raise LoweringError.new("cannot capture '#{c.name}' of type ref across thread boundary — ref values are not safe to share across threads", line: 0, column: 0, path: @ctx.current_analysis_path) if ref_type?(c.type)
|
|
837
837
|
end
|
|
838
838
|
end
|
|
839
839
|
|
|
@@ -844,7 +844,7 @@ module MilkTea
|
|
|
844
844
|
next if idx == other_idx
|
|
845
845
|
next unless other[:capture_names].include?(name)
|
|
846
846
|
|
|
847
|
-
raise LoweringError
|
|
847
|
+
raise LoweringError.new("write conflict in parallel block: '#{name}' is written in spawn block #{idx + 1} and accessed in spawn block #{other_idx + 1}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
848
848
|
end
|
|
849
849
|
end
|
|
850
850
|
end
|
|
@@ -193,7 +193,7 @@ module MilkTea
|
|
|
193
193
|
when AST::BreakStmt, AST::ContinueStmt, AST::PassStmt
|
|
194
194
|
nil
|
|
195
195
|
else
|
|
196
|
-
raise LoweringError
|
|
196
|
+
raise LoweringError.new("unsupported proc capture statement #{statement.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
|
|
@@ -248,7 +248,7 @@ module MilkTea
|
|
|
248
248
|
AST::BooleanLiteral, AST::NullLiteral
|
|
249
249
|
nil
|
|
250
250
|
else
|
|
251
|
-
raise LoweringError
|
|
251
|
+
raise LoweringError.new("unsupported proc capture expression #{expression.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
252
252
|
end
|
|
253
253
|
end
|
|
254
254
|
|
|
@@ -321,7 +321,7 @@ module MilkTea
|
|
|
321
321
|
when Types::Nullable
|
|
322
322
|
[]
|
|
323
323
|
else
|
|
324
|
-
raise LoweringError
|
|
324
|
+
raise LoweringError.new("unsupported proc lifecycle container #{type.class.name}", line: 0, column: 0, path: @ctx.current_analysis_path)
|
|
325
325
|
end
|
|
326
326
|
end
|
|
327
327
|
|