mt-lang 0.2.22 → 0.3.0
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/README.md +24 -1
- data/docs/index.html +2 -1
- data/docs/language-design.md +2 -0
- data/docs/language-manual.md +16 -1
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/ast.rb +2 -2
- data/lib/milk_tea/core/c_backend/expressions.rb +11 -0
- data/lib/milk_tea/core/c_backend/type_collectors.rb +49 -0
- data/lib/milk_tea/core/c_backend/type_declaration.rb +7 -0
- data/lib/milk_tea/core/c_backend/type_system.rb +12 -0
- data/lib/milk_tea/core/c_backend.rb +8 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +4 -0
- data/lib/milk_tea/core/compile_time.rb +16 -0
- data/lib/milk_tea/core/ir.rb +1 -0
- data/lib/milk_tea/core/keywords.rb +1 -1
- data/lib/milk_tea/core/lowering/block.rb +48 -16
- data/lib/milk_tea/core/lowering/calls.rb +75 -1
- data/lib/milk_tea/core/lowering/declarations.rb +7 -0
- data/lib/milk_tea/core/lowering/expressions.rb +39 -8
- data/lib/milk_tea/core/lowering/functions.rb +1 -1
- data/lib/milk_tea/core/lowering/resolve.rb +70 -5
- data/lib/milk_tea/core/lowering/utils.rb +26 -0
- data/lib/milk_tea/core/module_binder.rb +4 -0
- data/lib/milk_tea/core/parser/expressions.rb +11 -3
- data/lib/milk_tea/core/parser/statements.rb +2 -2
- data/lib/milk_tea/core/parser/types.rb +8 -1
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +97 -4
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +52 -2
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +7 -0
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +40 -0
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +11 -0
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +21 -4
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +23 -0
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +37 -0
- data/lib/milk_tea/core/types/layout.rb +7 -0
- data/lib/milk_tea/core/types/predicates.rb +44 -3
- data/lib/milk_tea/core/types/registry.rb +4 -0
- data/lib/milk_tea/core/types/types.rb +42 -0
- data/lib/milk_tea/core/types/visitor.rb +2 -0
- data/lib/milk_tea/lsp/server/completion.rb +1 -1
- data/lib/milk_tea/lsp/server/hover.rb +8 -1
- data/std/raylib.mt +14 -14
- metadata +2 -2
|
@@ -86,7 +86,7 @@ module MilkTea
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
begin
|
|
89
|
-
return resolve_type_ref_for_analysis(type_name, analysis)
|
|
89
|
+
return method_dispatch_receiver_type(resolve_type_ref_for_analysis(type_name, analysis))
|
|
90
90
|
rescue LoweringError => error
|
|
91
91
|
receiver_type_param_names = methods_receiver_type_argument_names!(type_name)
|
|
92
92
|
raise error if receiver_type_param_names.empty?
|
|
@@ -99,6 +99,9 @@ module MilkTea
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def lower_array_to_span_expression(expression, target_type)
|
|
102
|
+
array_type = expression.type
|
|
103
|
+
array_type = referenced_type(array_type) if ref_type?(array_type)
|
|
104
|
+
|
|
102
105
|
IR::AggregateLiteral.new(
|
|
103
106
|
type: target_type,
|
|
104
107
|
fields: [
|
|
@@ -115,7 +118,7 @@ module MilkTea
|
|
|
115
118
|
),
|
|
116
119
|
IR::AggregateField.new(
|
|
117
120
|
name: "len",
|
|
118
|
-
value: IR::IntegerLiteral.new(value: array_length(
|
|
121
|
+
value: IR::IntegerLiteral.new(value: array_length(array_type), type: @ctx.types.fetch("ptr_uint")),
|
|
119
122
|
),
|
|
120
123
|
],
|
|
121
124
|
)
|
|
@@ -549,6 +552,8 @@ module MilkTea
|
|
|
549
552
|
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
550
553
|
end
|
|
551
554
|
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
555
|
+
when :simd_lane_with
|
|
556
|
+
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: resolved_receiver_type)]
|
|
552
557
|
end
|
|
553
558
|
end
|
|
554
559
|
|
|
@@ -571,6 +576,13 @@ module MilkTea
|
|
|
571
576
|
return [atomic_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
572
577
|
end
|
|
573
578
|
|
|
579
|
+
if (simd_method = simd_method_kind(resolved_receiver_type, callee.member))
|
|
580
|
+
ret = case simd_method
|
|
581
|
+
when :simd_lane_with then resolved_receiver_type
|
|
582
|
+
end
|
|
583
|
+
return [simd_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
584
|
+
end
|
|
585
|
+
|
|
574
586
|
field_receiver_type = infer_field_receiver_type(callee.receiver, env:)
|
|
575
587
|
if array_type?(field_receiver_type) && callee.member == "as_span"
|
|
576
588
|
return [:array_as_span, nil, callee.receiver, Types::Registry.span(array_element_type(field_receiver_type))]
|
|
@@ -592,6 +604,11 @@ module MilkTea
|
|
|
592
604
|
return [:array, nil, nil, array_type]
|
|
593
605
|
end
|
|
594
606
|
|
|
607
|
+
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "simd"
|
|
608
|
+
simd_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["simd"]), arguments: callee.arguments, nullable: false))
|
|
609
|
+
return [:simd, nil, nil, simd_type]
|
|
610
|
+
end
|
|
611
|
+
|
|
595
612
|
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "span"
|
|
596
613
|
span_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: callee.arguments, nullable: false))
|
|
597
614
|
return [:struct_literal, nil, nil, span_type]
|
|
@@ -663,7 +680,7 @@ module MilkTea
|
|
|
663
680
|
|
|
664
681
|
if (type_ref = type_ref_from_specialization(callee))
|
|
665
682
|
specialized_type = resolve_type_ref(type_ref)
|
|
666
|
-
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion)
|
|
683
|
+
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
667
684
|
end
|
|
668
685
|
|
|
669
686
|
raise LoweringError, "unsupported specialization callee"
|
|
@@ -838,7 +855,7 @@ module MilkTea
|
|
|
838
855
|
:reinterpret, :zero, :hash, :equal, :order,
|
|
839
856
|
:dyn_method
|
|
840
857
|
callee_type.return_type
|
|
841
|
-
when :struct_literal, :struct_with, :array, :variant_arm_ctor, :adapt
|
|
858
|
+
when :struct_literal, :struct_with, :array, :simd, :variant_arm_ctor, :adapt
|
|
842
859
|
callee_type
|
|
843
860
|
when :ref_of
|
|
844
861
|
argument_type = infer_expression_type(expression.arguments.fetch(0).value, env:)
|
|
@@ -867,7 +884,8 @@ module MilkTea
|
|
|
867
884
|
receiver_type.element_type
|
|
868
885
|
end
|
|
869
886
|
Types::Registry.nullable(Types::Registry.generic_instance("ptr", [elem_type]))
|
|
870
|
-
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_store, :atomic_compare_exchange
|
|
887
|
+
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_store, :atomic_compare_exchange,
|
|
888
|
+
:simd_lane_with
|
|
871
889
|
callee_type.return_type
|
|
872
890
|
else
|
|
873
891
|
raise LoweringError, "unsupported call kind #{kind}"
|
|
@@ -1794,12 +1812,16 @@ module MilkTea
|
|
|
1794
1812
|
@lowerer = lowerer
|
|
1795
1813
|
end
|
|
1796
1814
|
|
|
1815
|
+
def types
|
|
1816
|
+
@lowerer.instance_variable_get(:@ctx).types
|
|
1817
|
+
end
|
|
1818
|
+
|
|
1797
1819
|
def evaluate_compile_time_const_value(expression, scopes: nil)
|
|
1798
1820
|
@lowerer.send(:compile_time_const_value, expression, env: @lowerer.send(:empty_env))
|
|
1799
1821
|
end
|
|
1800
1822
|
|
|
1801
1823
|
def top_level_function(name)
|
|
1802
|
-
@lowerer.instance_variable_get(:@ctx.functions
|
|
1824
|
+
@lowerer.instance_variable_get(:@ctx).functions&.[](name)
|
|
1803
1825
|
end
|
|
1804
1826
|
|
|
1805
1827
|
def raise_sema_error(message)
|
|
@@ -2185,6 +2207,46 @@ module MilkTea
|
|
|
2185
2207
|
raise LoweringError, "cannot use method #{binding.name} with receiver #{receiver_type}"
|
|
2186
2208
|
end
|
|
2187
2209
|
end
|
|
2210
|
+
when Types::Span
|
|
2211
|
+
return {} unless receiver_type.is_a?(Types::Span)
|
|
2212
|
+
|
|
2213
|
+
substitutions = {}
|
|
2214
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2215
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2216
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2217
|
+
raise LoweringError, "cannot use method #{binding.name} with receiver #{receiver_type}"
|
|
2218
|
+
end
|
|
2219
|
+
substitutions
|
|
2220
|
+
when Types::Task
|
|
2221
|
+
return {} unless receiver_type.is_a?(Types::Task)
|
|
2222
|
+
|
|
2223
|
+
substitutions = {}
|
|
2224
|
+
if declared_receiver_type.result_type.is_a?(Types::TypeVar)
|
|
2225
|
+
substitutions[declared_receiver_type.result_type.name] = receiver_type.result_type
|
|
2226
|
+
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
2227
|
+
raise LoweringError, "cannot use method #{binding.name} with receiver #{receiver_type}"
|
|
2228
|
+
end
|
|
2229
|
+
substitutions
|
|
2230
|
+
when Types::SoA
|
|
2231
|
+
return {} unless receiver_type.is_a?(Types::SoA)
|
|
2232
|
+
|
|
2233
|
+
substitutions = {}
|
|
2234
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2235
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2236
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2237
|
+
raise LoweringError, "cannot use method #{binding.name} with receiver #{receiver_type}"
|
|
2238
|
+
end
|
|
2239
|
+
substitutions
|
|
2240
|
+
when Types::Simd
|
|
2241
|
+
return {} unless receiver_type.is_a?(Types::Simd)
|
|
2242
|
+
|
|
2243
|
+
substitutions = {}
|
|
2244
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
2245
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
2246
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
2247
|
+
raise LoweringError, "cannot use method #{binding.name} with receiver #{receiver_type}"
|
|
2248
|
+
end
|
|
2249
|
+
substitutions
|
|
2188
2250
|
else
|
|
2189
2251
|
{}
|
|
2190
2252
|
end
|
|
@@ -2393,6 +2455,9 @@ module MilkTea
|
|
|
2393
2455
|
elsif name == "SoA"
|
|
2394
2456
|
validate_generic_type!(name, args)
|
|
2395
2457
|
Types::Registry.soa(args.fetch(0), count: args.fetch(1).value)
|
|
2458
|
+
elsif name == "simd"
|
|
2459
|
+
validate_generic_type!(name, args)
|
|
2460
|
+
Types::Registry.simd(args.fetch(0), lane_count: args.fetch(1).value)
|
|
2396
2461
|
else
|
|
2397
2462
|
validate_generic_type!(name, args)
|
|
2398
2463
|
args = [type_ref.lifetime] + args if name == "ref" && type_ref.lifetime
|
|
@@ -9,6 +9,14 @@ module MilkTea
|
|
|
9
9
|
range_expr?(expression)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
def lower_range_match_condition(range_pattern, scrutinee_ir, bool_type, env:)
|
|
13
|
+
start_ir = lower_expression(range_pattern.start_expr, env:, expected_type: nil)
|
|
14
|
+
end_ir = lower_expression(range_pattern.end_expr, env:, expected_type: nil)
|
|
15
|
+
ge = IR::Binary.new(operator: ">=", left: scrutinee_ir, right: start_ir, type: bool_type)
|
|
16
|
+
le = IR::Binary.new(operator: "<=", left: scrutinee_ir, right: end_ir, type: bool_type)
|
|
17
|
+
IR::Binary.new(operator: "and", left: ge, right: le, type: bool_type)
|
|
18
|
+
end
|
|
19
|
+
|
|
12
20
|
def range_start_of(iterable)
|
|
13
21
|
iterable.start_expr
|
|
14
22
|
end
|
|
@@ -80,6 +88,10 @@ module MilkTea
|
|
|
80
88
|
type.arguments[1].is_a?(Types::LiteralTypeArg)
|
|
81
89
|
end
|
|
82
90
|
|
|
91
|
+
def simd_type?(type)
|
|
92
|
+
type.is_a?(Types::Simd)
|
|
93
|
+
end
|
|
94
|
+
|
|
83
95
|
def array_element_type(type)
|
|
84
96
|
return unless array_type?(type)
|
|
85
97
|
|
|
@@ -321,6 +333,10 @@ module MilkTea
|
|
|
321
333
|
return receiver_type.element_type
|
|
322
334
|
end
|
|
323
335
|
|
|
336
|
+
if simd_type?(receiver_type)
|
|
337
|
+
return receiver_type.element_type
|
|
338
|
+
end
|
|
339
|
+
|
|
324
340
|
if pointer_type?(receiver_type)
|
|
325
341
|
return pointee_type(receiver_type)
|
|
326
342
|
end
|
|
@@ -417,6 +433,16 @@ module MilkTea
|
|
|
417
433
|
if type == @ctx.types.fetch("str") || type == @ctx.types.fetch("cstr")
|
|
418
434
|
return IR::StringLiteral.new(value:, type:, cstring: type == @ctx.types.fetch("cstr"))
|
|
419
435
|
end
|
|
436
|
+
when Hash
|
|
437
|
+
return nil unless type.is_a?(Types::Struct)
|
|
438
|
+
fields = value.map do |name, field_value|
|
|
439
|
+
field_type = type.field(name)
|
|
440
|
+
return nil unless field_type
|
|
441
|
+
lowered = lower_compile_time_literal(field_value, field_type)
|
|
442
|
+
return nil unless lowered
|
|
443
|
+
IR::AggregateField.new(name:, value: lowered)
|
|
444
|
+
end
|
|
445
|
+
return IR::AggregateLiteral.new(type:, fields:)
|
|
420
446
|
end
|
|
421
447
|
|
|
422
448
|
nil
|
|
@@ -145,6 +145,10 @@ module MilkTea
|
|
|
145
145
|
return true if receiver_type.is_a?(Types::Matrix)
|
|
146
146
|
return true if receiver_type.is_a?(Types::Quaternion)
|
|
147
147
|
return true if receiver_type.is_a?(Types::SoA)
|
|
148
|
+
return true if receiver_type.is_a?(Types::Simd)
|
|
149
|
+
return true if receiver_type.is_a?(Types::Span)
|
|
150
|
+
return true if receiver_type.is_a?(Types::Task)
|
|
151
|
+
return true if receiver_type.is_a?(Types::Dyn)
|
|
148
152
|
return true if exported_types.value?(receiver_type)
|
|
149
153
|
return true if imported_receiver_type?(receiver_type, analysis.imports)
|
|
150
154
|
return exported_method_receiver?(receiver_type.base, analysis, exported_types) if receiver_type.is_a?(Types::Nullable)
|
|
@@ -56,14 +56,22 @@ module MilkTea
|
|
|
56
56
|
arms
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
def parse_match_arm_pattern
|
|
60
|
+
pattern = parse_bitwise_xor
|
|
61
|
+
return pattern unless (pattern.is_a?(AST::IntegerLiteral) || pattern.is_a?(AST::CharLiteral)) && match(:dot_dot)
|
|
62
|
+
|
|
63
|
+
end_expr = parse_bitwise_xor
|
|
64
|
+
AST::RangeExpr.new(start_expr: pattern, end_expr:, line: previous.line, column: previous.column)
|
|
65
|
+
end
|
|
66
|
+
|
|
59
67
|
def parse_match_expression_arm
|
|
60
68
|
patterns = []
|
|
61
69
|
if match(:else)
|
|
62
70
|
patterns << AST::Identifier.new(name: "_", line: previous.line, column: previous.column)
|
|
63
71
|
else
|
|
64
|
-
patterns <<
|
|
72
|
+
patterns << parse_match_arm_pattern
|
|
65
73
|
while match(:pipe)
|
|
66
|
-
patterns <<
|
|
74
|
+
patterns << parse_match_arm_pattern
|
|
67
75
|
end
|
|
68
76
|
end
|
|
69
77
|
binding_token = nil
|
|
@@ -550,7 +558,7 @@ module MilkTea
|
|
|
550
558
|
end
|
|
551
559
|
|
|
552
560
|
def builtin_specialization_target?(expression)
|
|
553
|
-
expression.is_a?(AST::Identifier) && %w[array reinterpret span zero ptr const_ptr own ref adapt equal hash order].include?(expression.name)
|
|
561
|
+
expression.is_a?(AST::Identifier) && %w[array reinterpret span zero ptr const_ptr own ref adapt equal hash order simd SoA].include?(expression.name)
|
|
554
562
|
end
|
|
555
563
|
|
|
556
564
|
def parse_diagnostic_hint?(error)
|
|
@@ -332,9 +332,9 @@ module MilkTea
|
|
|
332
332
|
if match(:else)
|
|
333
333
|
patterns << AST::Identifier.new(name: "_", line: previous.line, column: previous.column)
|
|
334
334
|
else
|
|
335
|
-
patterns <<
|
|
335
|
+
patterns << parse_match_arm_pattern
|
|
336
336
|
while match(:pipe)
|
|
337
|
-
patterns <<
|
|
337
|
+
patterns << parse_match_arm_pattern
|
|
338
338
|
end
|
|
339
339
|
end
|
|
340
340
|
binding_name = if match(:as)
|
|
@@ -46,8 +46,9 @@ module MilkTea
|
|
|
46
46
|
raise error(name_token, "expected ':' and parameter type") unless match(:colon)
|
|
47
47
|
|
|
48
48
|
param_type = parse_type_ref
|
|
49
|
+
default_value = parse_param_default_value
|
|
49
50
|
|
|
50
|
-
AST::Param.new(name: name_token.lexeme, type: param_type, line: name_token.line, column: name_token.column)
|
|
51
|
+
AST::Param.new(name: name_token.lexeme, type: param_type, line: name_token.line, column: name_token.column, default_value:)
|
|
51
52
|
rescue ParseError => e
|
|
52
53
|
raise unless @recovery_errors
|
|
53
54
|
|
|
@@ -57,6 +58,12 @@ module MilkTea
|
|
|
57
58
|
AST::Param.new(name: param_name, type: error_type, line: name_token&.line || 1, column: name_token&.column || 1)
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
def parse_param_default_value
|
|
62
|
+
return nil unless match(:equal)
|
|
63
|
+
|
|
64
|
+
parse_expression
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
def parse_foreign_param
|
|
61
68
|
mode = if foreign_param_qualifier_mode?
|
|
62
69
|
advance.type
|
|
@@ -53,6 +53,24 @@ module MilkTea
|
|
|
53
53
|
struct_type
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
def check_simd_construction(simd_type, arguments, scopes:)
|
|
57
|
+
raise_sema_error("simd construction requires exactly #{simd_type.lane_count} positional arguments, got #{arguments.length}") unless arguments.length == simd_type.lane_count
|
|
58
|
+
raise_sema_error("simd construction does not accept named arguments") if arguments.any?(&:name)
|
|
59
|
+
|
|
60
|
+
element_type = simd_type.element_type
|
|
61
|
+
arguments.each do |argument|
|
|
62
|
+
actual_type = infer_expression(argument.value, scopes:, expected_type: element_type)
|
|
63
|
+
ensure_assignable!(
|
|
64
|
+
actual_type,
|
|
65
|
+
element_type,
|
|
66
|
+
"simd lane expects #{element_type}, got #{actual_type}",
|
|
67
|
+
expression: argument.value,
|
|
68
|
+
contextual_int_to_float: contextual_int_to_float_target?(element_type),
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
simd_type
|
|
72
|
+
end
|
|
73
|
+
|
|
56
74
|
def check_struct_with_call(struct_type, _receiver_expression, arguments, scopes:)
|
|
57
75
|
check_aggregate_field_arguments(struct_type, arguments, scopes:, context: "struct.with()")
|
|
58
76
|
struct_type
|
|
@@ -584,6 +602,27 @@ module MilkTea
|
|
|
584
602
|
end
|
|
585
603
|
end
|
|
586
604
|
|
|
605
|
+
def check_simd_method_call(kind, receiver_type, _receiver, arguments, scopes:)
|
|
606
|
+
raise_sema_error("simd methods do not support named arguments") if arguments.any?(&:name)
|
|
607
|
+
|
|
608
|
+
case kind
|
|
609
|
+
when :simd_lane_with
|
|
610
|
+
raise_sema_error("with expects exactly 2 arguments, got #{arguments.length}") unless arguments.length == 2
|
|
611
|
+
|
|
612
|
+
index_arg = arguments[0].value
|
|
613
|
+
index_type = infer_expression(index_arg, scopes:)
|
|
614
|
+
raise_sema_error("with index must be an integer, got #{index_type}") unless index_type.integer?
|
|
615
|
+
|
|
616
|
+
value_type = infer_expression(arguments[1].value, scopes:, expected_type: receiver_type.element_type)
|
|
617
|
+
ensure_assignable!(
|
|
618
|
+
value_type,
|
|
619
|
+
receiver_type.element_type,
|
|
620
|
+
"with expects lane value of type #{receiver_type.element_type}, got #{value_type}",
|
|
621
|
+
)
|
|
622
|
+
receiver_type
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
|
|
587
626
|
def event_listener_type(event_type)
|
|
588
627
|
params = []
|
|
589
628
|
params << Types::Registry.parameter("value", event_type.payload_type) if event_type.payload_type
|
|
@@ -620,6 +659,12 @@ module MilkTea
|
|
|
620
659
|
ATOMIC_METHOD_KINDS[name]
|
|
621
660
|
end
|
|
622
661
|
|
|
662
|
+
def simd_method_kind(receiver_type, name)
|
|
663
|
+
return unless simd_type?(receiver_type)
|
|
664
|
+
|
|
665
|
+
SIMD_METHOD_KINDS[name]
|
|
666
|
+
end
|
|
667
|
+
|
|
623
668
|
def check_atomic_method_call(kind, receiver_type, receiver, arguments, scopes:)
|
|
624
669
|
elem_type = atomic_element_type(receiver_type)
|
|
625
670
|
raise_sema_error("atomic methods do not support named arguments") if arguments.any?(&:name)
|
|
@@ -740,10 +785,14 @@ module MilkTea
|
|
|
740
785
|
end
|
|
741
786
|
|
|
742
787
|
def check_function_call(binding, arguments, scopes:)
|
|
743
|
-
arguments = canonicalize_call_arguments(arguments, binding.type.params, binding.name)
|
|
788
|
+
arguments = canonicalize_call_arguments(arguments, binding.type.params, binding.name, binding)
|
|
789
|
+
fill_positional_defaults!(arguments, binding)
|
|
790
|
+
|
|
744
791
|
expected_params = binding.type.params
|
|
745
|
-
|
|
746
|
-
|
|
792
|
+
required_count = count_required_params(binding)
|
|
793
|
+
variadic = binding.type.is_a?(Types::Function) && binding.type.variadic
|
|
794
|
+
unless variadic ? arguments.length >= required_count : arguments.length <= expected_params.length && arguments.length >= required_count
|
|
795
|
+
raise_sema_error(arity_error_message(binding.type, binding.name, arguments.length, required_count:))
|
|
747
796
|
end
|
|
748
797
|
|
|
749
798
|
expected_params.each_with_index do |parameter, index|
|
|
@@ -963,7 +1012,7 @@ module MilkTea
|
|
|
963
1012
|
resolve_interface_ref(interface_ref)
|
|
964
1013
|
end
|
|
965
1014
|
|
|
966
|
-
def canonicalize_call_arguments(arguments, params, context_name)
|
|
1015
|
+
def canonicalize_call_arguments(arguments, params, context_name, binding = nil)
|
|
967
1016
|
return arguments unless arguments.any?(&:name)
|
|
968
1017
|
|
|
969
1018
|
named_seen = false
|
|
@@ -985,8 +1034,52 @@ module MilkTea
|
|
|
985
1034
|
end
|
|
986
1035
|
end
|
|
987
1036
|
|
|
1037
|
+
fill_parameter_defaults!(by_position, params, binding, context_name)
|
|
1038
|
+
|
|
988
1039
|
by_position.reject(&:nil?)
|
|
989
1040
|
end
|
|
1041
|
+
|
|
1042
|
+
def fill_parameter_defaults!(by_position, params, binding, context_name)
|
|
1043
|
+
return unless binding
|
|
1044
|
+
|
|
1045
|
+
ast_params = binding.ast.params
|
|
1046
|
+
return unless ast_params.any? { |p| p.respond_to?(:default_value) && p.default_value }
|
|
1047
|
+
|
|
1048
|
+
params.each_with_index do |param, idx|
|
|
1049
|
+
next unless by_position[idx].nil?
|
|
1050
|
+
next unless idx < ast_params.length
|
|
1051
|
+
|
|
1052
|
+
ast_param = ast_params[idx]
|
|
1053
|
+
next unless ast_param.respond_to?(:default_value) && ast_param.default_value
|
|
1054
|
+
|
|
1055
|
+
by_position[idx] = AST::Argument.new(name: nil, value: ast_param.default_value)
|
|
1056
|
+
end
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
def fill_positional_defaults!(arguments, binding)
|
|
1060
|
+
return unless binding.ast.params.any? { |p| p.respond_to?(:default_value) && p.default_value }
|
|
1061
|
+
|
|
1062
|
+
ast_params = binding.ast.params
|
|
1063
|
+
while arguments.length < ast_params.length
|
|
1064
|
+
ast_param = ast_params[arguments.length]
|
|
1065
|
+
if ast_param.respond_to?(:default_value) && ast_param.default_value
|
|
1066
|
+
arguments << AST::Argument.new(name: nil, value: ast_param.default_value)
|
|
1067
|
+
else
|
|
1068
|
+
break
|
|
1069
|
+
end
|
|
1070
|
+
end
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
def count_required_params(binding)
|
|
1074
|
+
return binding.type.params.length unless binding.ast.params.any? { |p| p.respond_to?(:default_value) && p.default_value }
|
|
1075
|
+
|
|
1076
|
+
seen_default = false
|
|
1077
|
+
binding.ast.params.count do |p|
|
|
1078
|
+
has_default = p.respond_to?(:default_value) && p.default_value
|
|
1079
|
+
seen_default = true if has_default
|
|
1080
|
+
!has_default && !seen_default
|
|
1081
|
+
end
|
|
1082
|
+
end
|
|
990
1083
|
end
|
|
991
1084
|
end
|
|
992
1085
|
end
|
|
@@ -446,6 +446,10 @@ module MilkTea
|
|
|
446
446
|
return receiver_type.element_type
|
|
447
447
|
end
|
|
448
448
|
|
|
449
|
+
if simd_type?(receiver_type)
|
|
450
|
+
return receiver_type.element_type
|
|
451
|
+
end
|
|
452
|
+
|
|
449
453
|
if array_type?(receiver_type) && !unsafe_context? && !addressable_storage_expression?(expression.receiver, scopes:)
|
|
450
454
|
raise_sema_error("safe array indexing requires an addressable array value; bind it to a local first")
|
|
451
455
|
end
|
|
@@ -489,6 +493,10 @@ module MilkTea
|
|
|
489
493
|
|
|
490
494
|
operand_type
|
|
491
495
|
when "~"
|
|
496
|
+
if simd_type?(operand_type)
|
|
497
|
+
raise_sema_error("operator ~ on simd requires integer element type, got #{operand_type.element_type}") unless operand_type.element_type.integer?
|
|
498
|
+
return operand_type
|
|
499
|
+
end
|
|
492
500
|
raise_sema_error("operator ~ requires an integer or flags operand, got #{operand_type}") unless bitwise_type?(operand_type)
|
|
493
501
|
|
|
494
502
|
operand_type
|
|
@@ -596,6 +604,9 @@ module MilkTea
|
|
|
596
604
|
ensure_assignable!(right_type, @ctx.types.fetch("bool"), "operator #{expression.operator} requires bool operands")
|
|
597
605
|
@ctx.types.fetch("bool")
|
|
598
606
|
when "|", "&", "^"
|
|
607
|
+
simd_result = simd_bitwise_result(left_type, right_type)
|
|
608
|
+
return simd_result if simd_result
|
|
609
|
+
|
|
599
610
|
# For Flags/Enum types, the operands must match and be bitwise-capable.
|
|
600
611
|
unless left_type == right_type && (bitwise_type?(left_type) || left_type.is_a?(Types::Flags))
|
|
601
612
|
raise_sema_error("operator #{expression.operator} requires matching integer or flags types, got #{left_type} and #{right_type}")
|
|
@@ -626,6 +637,9 @@ module MilkTea
|
|
|
626
637
|
|
|
627
638
|
result_type
|
|
628
639
|
when "%"
|
|
640
|
+
simd_result = simd_mod_result(left_type, right_type)
|
|
641
|
+
return simd_result if simd_result
|
|
642
|
+
|
|
629
643
|
result_type = common_integer_type(left_type, right_type)
|
|
630
644
|
unless result_type
|
|
631
645
|
raise_sema_error("operator % requires compatible integer types, got #{left_type} and #{right_type}")
|
|
@@ -633,6 +647,9 @@ module MilkTea
|
|
|
633
647
|
|
|
634
648
|
result_type
|
|
635
649
|
when "<<", ">>"
|
|
650
|
+
simd_result = simd_shift_result(left_type, right_type)
|
|
651
|
+
return simd_result if simd_result
|
|
652
|
+
|
|
636
653
|
unless left_type.is_a?(Types::Primitive) && left_type.integer? && right_type.is_a?(Types::Primitive) && right_type.integer?
|
|
637
654
|
raise_sema_error("operator #{expression.operator} requires integer operands, got #{left_type} and #{right_type}")
|
|
638
655
|
end
|
|
@@ -787,8 +804,26 @@ module MilkTea
|
|
|
787
804
|
next
|
|
788
805
|
end
|
|
789
806
|
|
|
807
|
+
if arm.pattern.is_a?(AST::RangeExpr)
|
|
808
|
+
start_val = arm.pattern.start_expr
|
|
809
|
+
end_val = arm.pattern.end_expr
|
|
810
|
+
unless (start_val.is_a?(AST::IntegerLiteral) || start_val.is_a?(AST::CharLiteral)) &&
|
|
811
|
+
(end_val.is_a?(AST::IntegerLiteral) || end_val.is_a?(AST::CharLiteral))
|
|
812
|
+
raise_sema_error("range match arm bounds must be integer or char literals, got #{start_val.class.name}..#{end_val.class.name}")
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
raise_sema_error("range match arm start #{start_val.value} must be <= end #{end_val.value}") if start_val.value > end_val.value
|
|
816
|
+
|
|
817
|
+
range_key = [start_val.value, end_val.value]
|
|
818
|
+
raise_sema_error("duplicate match arm range #{range_key[0]}..#{range_key[1]}") if covered_values.key?(range_key)
|
|
819
|
+
|
|
820
|
+
covered_values[range_key] = true
|
|
821
|
+
arm_entries << [infer_match_expression_arm_value(arm, scopes:, expected_type:), arm.value]
|
|
822
|
+
next
|
|
823
|
+
end
|
|
824
|
+
|
|
790
825
|
unless arm.pattern.is_a?(AST::IntegerLiteral) || arm.pattern.is_a?(AST::CharLiteral)
|
|
791
|
-
raise_sema_error("match arm for integer scrutinee must be an integer literal, char literal, or _, got #{arm.pattern.class.name}")
|
|
826
|
+
raise_sema_error("match arm for integer scrutinee must be an integer literal, char literal, range, or _, got #{arm.pattern.class.name}")
|
|
792
827
|
end
|
|
793
828
|
|
|
794
829
|
value = arm.pattern.value
|
|
@@ -1049,8 +1084,12 @@ module MilkTea
|
|
|
1049
1084
|
check_event_method_call(callable_kind, receiver, expression.arguments, scopes:)
|
|
1050
1085
|
when :atomic_load, :atomic_store, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_compare_exchange
|
|
1051
1086
|
check_atomic_method_call(callable_kind, callable, receiver, expression.arguments, scopes:)
|
|
1087
|
+
when :simd_lane_with
|
|
1088
|
+
check_simd_method_call(callable_kind, callable, receiver, expression.arguments, scopes:)
|
|
1052
1089
|
when :struct
|
|
1053
1090
|
check_aggregate_construction(callable, expression.arguments, scopes:)
|
|
1091
|
+
when :simd
|
|
1092
|
+
check_simd_construction(callable, expression.arguments, scopes:)
|
|
1054
1093
|
when :struct_with
|
|
1055
1094
|
check_struct_with_call(callable, receiver, expression.arguments, scopes:)
|
|
1056
1095
|
when :variant_arm_ctor
|
|
@@ -1435,6 +1474,10 @@ module MilkTea
|
|
|
1435
1474
|
return [atomic_method, method_receiver_type, callee.receiver]
|
|
1436
1475
|
end
|
|
1437
1476
|
|
|
1477
|
+
if (simd_method = simd_method_kind(method_receiver_type, callee.member))
|
|
1478
|
+
return [simd_method, method_receiver_type, callee.receiver]
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1438
1481
|
field_receiver_type = infer_field_receiver_type(callee.receiver, scopes:)
|
|
1439
1482
|
if array_type?(field_receiver_type) && callee.member == "as_span"
|
|
1440
1483
|
return [:array_as_span, field_receiver_type, callee.receiver]
|
|
@@ -1467,6 +1510,13 @@ module MilkTea
|
|
|
1467
1510
|
return [:array, array_type, nil]
|
|
1468
1511
|
end
|
|
1469
1512
|
|
|
1513
|
+
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "simd"
|
|
1514
|
+
raise_sema_error("simd requires exactly two type arguments") unless callee.arguments.length == 2
|
|
1515
|
+
|
|
1516
|
+
simd_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["simd"]), arguments: callee.arguments, nullable: false))
|
|
1517
|
+
return [:simd, simd_type, nil]
|
|
1518
|
+
end
|
|
1519
|
+
|
|
1470
1520
|
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "span"
|
|
1471
1521
|
raise_sema_error("span requires exactly one type argument") unless callee.arguments.length == 1
|
|
1472
1522
|
|
|
@@ -1526,7 +1576,7 @@ module MilkTea
|
|
|
1526
1576
|
|
|
1527
1577
|
if (type_ref = type_ref_from_specialization(callee))
|
|
1528
1578
|
specialized_type = resolve_type_ref(type_ref)
|
|
1529
|
-
return [:struct, specialized_type, nil] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion)
|
|
1579
|
+
return [:struct, specialized_type, nil] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
1530
1580
|
end
|
|
1531
1581
|
|
|
1532
1582
|
raise_sema_error("unsupported callable specialization #{describe_expression(callee)}")
|
|
@@ -85,6 +85,7 @@ module MilkTea
|
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
public_params = []
|
|
88
|
+
any_default = false
|
|
88
89
|
decl.params.each do |param|
|
|
89
90
|
begin
|
|
90
91
|
ensure_non_reserved_primitive_name!(param.name, kind_label: "parameter", line: param.respond_to?(:line) ? param.line : decl.line, column: param.respond_to?(:column) ? param.column : nil)
|
|
@@ -94,6 +95,12 @@ module MilkTea
|
|
|
94
95
|
validate_parameter_proc_type!(type, function_name: decl.name, parameter_name: param.name, external:, foreign:)
|
|
95
96
|
raise_sema_error("parameter #{param.name} of #{decl.name} must pass event storage through ref[...] or pointers, got #{type}") if noncopyable_event_storage_type?(type)
|
|
96
97
|
|
|
98
|
+
has_default = param.respond_to?(:default_value) && param.default_value
|
|
99
|
+
raise_sema_error("external function #{decl.name} cannot have default parameter values") if external && has_default
|
|
100
|
+
raise_sema_error("foreign function #{decl.name} cannot have default parameter values") if foreign && has_default
|
|
101
|
+
raise_sema_error("default parameter #{param.name} of #{decl.name} must appear after required parameters") if !has_default && any_default
|
|
102
|
+
any_default = true if has_default
|
|
103
|
+
|
|
97
104
|
if external && array_type?(type)
|
|
98
105
|
raise_sema_error("external function #{decl.name} cannot take array parameters")
|
|
99
106
|
end
|
|
@@ -45,6 +45,46 @@ module MilkTea
|
|
|
45
45
|
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
|
+
when Types::Span
|
|
49
|
+
return {} unless receiver_type.is_a?(Types::Span)
|
|
50
|
+
|
|
51
|
+
substitutions = {}
|
|
52
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
53
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
54
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
55
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
56
|
+
end
|
|
57
|
+
substitutions
|
|
58
|
+
when Types::Task
|
|
59
|
+
return {} unless receiver_type.is_a?(Types::Task)
|
|
60
|
+
|
|
61
|
+
substitutions = {}
|
|
62
|
+
if declared_receiver_type.result_type.is_a?(Types::TypeVar)
|
|
63
|
+
substitutions[declared_receiver_type.result_type.name] = receiver_type.result_type
|
|
64
|
+
elsif declared_receiver_type.result_type != receiver_type.result_type
|
|
65
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
66
|
+
end
|
|
67
|
+
substitutions
|
|
68
|
+
when Types::SoA
|
|
69
|
+
return {} unless receiver_type.is_a?(Types::SoA)
|
|
70
|
+
|
|
71
|
+
substitutions = {}
|
|
72
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
73
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
74
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
75
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
76
|
+
end
|
|
77
|
+
substitutions
|
|
78
|
+
when Types::Simd
|
|
79
|
+
return {} unless receiver_type.is_a?(Types::Simd)
|
|
80
|
+
|
|
81
|
+
substitutions = {}
|
|
82
|
+
if declared_receiver_type.element_type.is_a?(Types::TypeVar)
|
|
83
|
+
substitutions[declared_receiver_type.element_type.name] = receiver_type.element_type
|
|
84
|
+
elsif declared_receiver_type.element_type != receiver_type.element_type
|
|
85
|
+
raise_sema_error("cannot use method #{binding.name} with receiver #{receiver_type}")
|
|
86
|
+
end
|
|
87
|
+
substitutions
|
|
48
88
|
else
|
|
49
89
|
{}
|
|
50
90
|
end
|