mt-lang 0.3.32 → 0.3.34
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/compile_time.rb +1 -1
- data/lib/milk_tea/core/control_flow/builder.rb +15 -80
- data/lib/milk_tea/core/lowering/declarations.rb +36 -2
- data/lib/milk_tea/core/lowering/expressions.rb +18 -5
- data/lib/milk_tea/core/lowering/functions.rb +11 -0
- data/lib/milk_tea/core/lowering/lowering_context.rb +2 -0
- data/lib/milk_tea/core/lowering/resolve.rb +23 -1
- data/lib/milk_tea/core/lowering/utils.rb +27 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +5 -0
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +15 -0
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +12 -8
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +92 -5
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +4 -0
- data/lib/milk_tea/core/semantic_analyzer.rb +11 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d0786ef5ca9025e069a44b7ea3915199110e1f2397d294ed81122a308c79e2e
|
|
4
|
+
data.tar.gz: 42e3fa0077192377fa7da61cea865fd04e8ef49d66343c71a1bd5e2e1caa8b59
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd4a874279ff48b7d0f1de8baf092e92e01ede8a4c969133855c9dd9c9f061490c11ff29dfc24905466fe1df56d1d53a86a5c156ce1cbe5efeed60d78f5a21e8
|
|
7
|
+
data.tar.gz: 30bb123ddb1939f7694c62dae186152b8f592d78826e7b4aa416c6a010202d07bda5474b72014114d8064b7168ff02b6b7dd252a8b7d007d9b9bcae8b31b4786
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -437,7 +437,7 @@ module MilkTea
|
|
|
437
437
|
resolve_identifier: ->(id) { @variables[id.name] || @checker.evaluate_compile_time_const_value(id, scopes:) },
|
|
438
438
|
resolve_member_access: ->(ma) { @checker.evaluate_compile_time_const_value(ma, scopes:) },
|
|
439
439
|
resolve_type_ref: nil,
|
|
440
|
-
resolve_call:
|
|
440
|
+
resolve_call: ->(call_expr) { resolve_compile_time_call(call_expr, scopes:) },
|
|
441
441
|
)
|
|
442
442
|
end
|
|
443
443
|
return nil unless arg_value
|
|
@@ -56,16 +56,10 @@ module MilkTea
|
|
|
56
56
|
def build_statement(stmt, next_id, break_target:, continue_target:)
|
|
57
57
|
case stmt
|
|
58
58
|
when AST::LocalDecl
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
writes = Set.new
|
|
62
|
-
writes_info = []
|
|
63
|
-
declaration_key = declaration_binding_key(stmt, stmt.name)
|
|
64
|
-
if declaration_key && (stmt.value || @local_decl_without_initializer_writes)
|
|
65
|
-
writes << declaration_key
|
|
66
|
-
writes_info << { name: stmt.name, binding_key: declaration_key, line: stmt.line, column: stmt.column, origin: :declaration }
|
|
67
|
-
end
|
|
59
|
+
reads, reads_info = read_identifiers_with_sites(stmt.value)
|
|
60
|
+
writes, writes_info = local_decl_write_targets(stmt, stmt.name)
|
|
68
61
|
|
|
62
|
+
if stmt.else_body
|
|
69
63
|
success_id = add_linear_node(:local_decl, stmt, next_id, writes:, writes_info:)
|
|
70
64
|
null_entry = build_block(stmt.else_body, next_id, break_target:, continue_target:)
|
|
71
65
|
condition_id = @graph.add_node(
|
|
@@ -80,14 +74,6 @@ module MilkTea
|
|
|
80
74
|
return condition_id
|
|
81
75
|
end
|
|
82
76
|
|
|
83
|
-
reads, reads_info = read_identifiers_with_sites(stmt.value)
|
|
84
|
-
writes = Set.new
|
|
85
|
-
writes_info = []
|
|
86
|
-
declaration_key = declaration_binding_key(stmt, stmt.name)
|
|
87
|
-
if declaration_key && (stmt.value || @local_decl_without_initializer_writes)
|
|
88
|
-
writes << declaration_key
|
|
89
|
-
writes_info << { name: stmt.name, binding_key: declaration_key, line: stmt.line, column: stmt.column, origin: :declaration }
|
|
90
|
-
end
|
|
91
77
|
add_linear_node(:local_decl, stmt, next_id, reads:, reads_info:, writes:, writes_info:)
|
|
92
78
|
when AST::Assignment
|
|
93
79
|
reads, reads_info = read_identifiers_with_sites(stmt.value)
|
|
@@ -213,13 +199,10 @@ module MilkTea
|
|
|
213
199
|
build_block(stmt.body, next_id, break_target:, continue_target:)
|
|
214
200
|
when AST::DeferStmt
|
|
215
201
|
body_entry = build_block(stmt.body, next_id, break_target:, continue_target:)
|
|
216
|
-
expression_reads, expression_reads_info = statement_list_reads_with_sites(stmt.body)
|
|
217
202
|
defer_id = @graph.add_node(
|
|
218
203
|
kind: :defer,
|
|
219
204
|
statement: stmt,
|
|
220
205
|
line: stmt.line,
|
|
221
|
-
reads: expression_reads,
|
|
222
|
-
reads_info: expression_reads_info,
|
|
223
206
|
)
|
|
224
207
|
@graph.add_edge(defer_id, body_entry)
|
|
225
208
|
defer_id
|
|
@@ -315,66 +298,6 @@ module MilkTea
|
|
|
315
298
|
[reads, reads_info]
|
|
316
299
|
end
|
|
317
300
|
|
|
318
|
-
def statement_list_reads_with_sites(statements)
|
|
319
|
-
reads = Set.new
|
|
320
|
-
reads_info = []
|
|
321
|
-
statement_list_read_identifiers(statements, reads, reads_info)
|
|
322
|
-
[reads, reads_info]
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def statement_list_read_identifiers(statements, reads, reads_info)
|
|
326
|
-
Array(statements).each do |statement|
|
|
327
|
-
statement_read_identifiers(statement, reads, reads_info)
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
def statement_read_identifiers(statement, reads, reads_info)
|
|
332
|
-
case statement
|
|
333
|
-
when AST::ExpressionStmt
|
|
334
|
-
read_identifiers(statement.expression, reads, reads_info)
|
|
335
|
-
when AST::DeferStmt
|
|
336
|
-
statement_list_read_identifiers(statement.body, reads, reads_info)
|
|
337
|
-
when AST::LocalDecl
|
|
338
|
-
read_identifiers(statement.value, reads, reads_info)
|
|
339
|
-
statement_list_read_identifiers(statement.else_body, reads, reads_info)
|
|
340
|
-
when AST::Assignment
|
|
341
|
-
read_identifiers(statement.target, reads, reads_info)
|
|
342
|
-
read_identifiers(statement.value, reads, reads_info)
|
|
343
|
-
when AST::ReturnStmt
|
|
344
|
-
read_identifiers(statement.value, reads, reads_info)
|
|
345
|
-
when AST::IfStmt
|
|
346
|
-
statement.branches.each do |branch|
|
|
347
|
-
read_identifiers(branch.condition, reads, reads_info)
|
|
348
|
-
statement_list_read_identifiers(branch.body, reads, reads_info)
|
|
349
|
-
end
|
|
350
|
-
statement_list_read_identifiers(statement.else_body, reads, reads_info)
|
|
351
|
-
when AST::WhileStmt
|
|
352
|
-
read_identifiers(statement.condition, reads, reads_info)
|
|
353
|
-
statement_list_read_identifiers(statement.body, reads, reads_info)
|
|
354
|
-
when AST::ForStmt
|
|
355
|
-
statement.iterables.each { |iterable| read_identifiers(iterable, reads, reads_info) }
|
|
356
|
-
statement_list_read_identifiers(statement.body, reads, reads_info)
|
|
357
|
-
when AST::UnsafeStmt
|
|
358
|
-
statement_list_read_identifiers(statement.body, reads, reads_info)
|
|
359
|
-
when AST::MatchStmt
|
|
360
|
-
read_identifiers(statement.expression, reads, reads_info)
|
|
361
|
-
statement.arms.each do |arm|
|
|
362
|
-
read_identifiers(arm.pattern, reads, reads_info)
|
|
363
|
-
statement_list_read_identifiers(arm.body, reads, reads_info)
|
|
364
|
-
end
|
|
365
|
-
when AST::StaticAssert
|
|
366
|
-
read_identifiers(statement.condition, reads, reads_info)
|
|
367
|
-
read_identifiers(statement.message, reads, reads_info)
|
|
368
|
-
when AST::WhenStmt
|
|
369
|
-
read_identifiers(statement.discriminant, reads, reads_info)
|
|
370
|
-
statement.branches.each do |branch|
|
|
371
|
-
read_identifiers(branch.pattern, reads, reads_info)
|
|
372
|
-
statement_list_read_identifiers(branch.body, reads, reads_info)
|
|
373
|
-
end
|
|
374
|
-
statement_list_read_identifiers(statement.else_body, reads, reads_info)
|
|
375
|
-
end
|
|
376
|
-
end
|
|
377
|
-
|
|
378
301
|
def read_identifiers(expression, names = Set.new, reads_info = [])
|
|
379
302
|
case expression
|
|
380
303
|
when nil
|
|
@@ -582,6 +505,18 @@ module MilkTea
|
|
|
582
505
|
name
|
|
583
506
|
end
|
|
584
507
|
|
|
508
|
+
def local_decl_write_targets(stmt, name)
|
|
509
|
+
writes = Set.new
|
|
510
|
+
writes_info = []
|
|
511
|
+
declaration_key = declaration_binding_key(stmt, name)
|
|
512
|
+
if declaration_key && (stmt.value || @local_decl_without_initializer_writes)
|
|
513
|
+
writes << declaration_key
|
|
514
|
+
writes_info << { name:, binding_key: declaration_key, line: stmt.line, column: stmt.column, origin: :declaration }
|
|
515
|
+
end
|
|
516
|
+
write_targets_from_expression(stmt.value, line: stmt.line, writes:, writes_info:)
|
|
517
|
+
[writes, writes_info]
|
|
518
|
+
end
|
|
519
|
+
|
|
585
520
|
def add_null_test_refinements(cond_id, true_succ, false_succ, condition)
|
|
586
521
|
pairs = null_check_pairs(condition, positive: true)
|
|
587
522
|
return if pairs.empty?
|
|
@@ -26,9 +26,9 @@ module MilkTea
|
|
|
26
26
|
|
|
27
27
|
next if type == Types::BUILTIN_TYPE_META_TYPE
|
|
28
28
|
|
|
29
|
-
if const_value && (decl.value.is_a?(AST::Call) || decl.value.is_a?(AST::Specialization))
|
|
29
|
+
if !const_value.nil? && (decl.value.is_a?(AST::Call) || decl.value.is_a?(AST::Specialization))
|
|
30
30
|
value = lower_const_value_literal(type, const_value)
|
|
31
|
-
elsif const_value && (decl.block_body || decl.value.is_a?(AST::ExpressionList))
|
|
31
|
+
elsif !const_value.nil? && (decl.block_body || decl.value.is_a?(AST::ExpressionList))
|
|
32
32
|
if const_value.is_a?(Array) && const_value.empty? && decl.value.is_a?(AST::ExpressionList) && !decl.value.elements.empty?
|
|
33
33
|
value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
|
|
34
34
|
else
|
|
@@ -38,12 +38,46 @@ module MilkTea
|
|
|
38
38
|
raise LoweringError.new("constant #{decl.name} has no compile-time value", line: decl.line, column: decl.column)
|
|
39
39
|
else
|
|
40
40
|
value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
|
|
41
|
+
if (decl.value.is_a?(AST::Call) || decl.value.is_a?(AST::Specialization)) && static_initializer_ir_has_call?(value)
|
|
42
|
+
raise LoweringError.new("constant #{decl.name} initializer is not a compile-time value", line: decl.line, column: decl.column, path: @ctx.current_analysis_path)
|
|
43
|
+
end
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
IR::Constant.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:, line: decl.line, path: @ctx.current_analysis_path)
|
|
44
47
|
end
|
|
45
48
|
end
|
|
46
49
|
|
|
50
|
+
def static_initializer_ir_has_call?(node)
|
|
51
|
+
case node
|
|
52
|
+
when IR::Call
|
|
53
|
+
true
|
|
54
|
+
when IR::AggregateLiteral
|
|
55
|
+
node.fields.any? { |field| static_initializer_ir_has_call?(field.value) }
|
|
56
|
+
when IR::ArrayLiteral
|
|
57
|
+
node.elements.any? { |element| static_initializer_ir_has_call?(element) }
|
|
58
|
+
when IR::VariantLiteral
|
|
59
|
+
node.fields.any? { |field| static_initializer_ir_has_call?(field.value) }
|
|
60
|
+
when IR::Binary
|
|
61
|
+
static_initializer_ir_has_call?(node.left) || static_initializer_ir_has_call?(node.right)
|
|
62
|
+
when IR::Unary
|
|
63
|
+
static_initializer_ir_has_call?(node.operand)
|
|
64
|
+
when IR::Conditional
|
|
65
|
+
static_initializer_ir_has_call?(node.condition) || static_initializer_ir_has_call?(node.then_expression) || static_initializer_ir_has_call?(node.else_expression)
|
|
66
|
+
when IR::Cast
|
|
67
|
+
static_initializer_ir_has_call?(node.expression)
|
|
68
|
+
when IR::AddressOf
|
|
69
|
+
static_initializer_ir_has_call?(node.expression)
|
|
70
|
+
when IR::Member
|
|
71
|
+
static_initializer_ir_has_call?(node.receiver)
|
|
72
|
+
when IR::Index, IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
|
|
73
|
+
static_initializer_ir_has_call?(node.receiver) || static_initializer_ir_has_call?(node.index)
|
|
74
|
+
when IR::ReinterpretExpr
|
|
75
|
+
static_initializer_ir_has_call?(node.expression)
|
|
76
|
+
else
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
47
81
|
def lower_const_value_literal(type, const_value)
|
|
48
82
|
case const_value
|
|
49
83
|
when Integer
|
|
@@ -1323,10 +1323,10 @@ module MilkTea
|
|
|
1323
1323
|
IR::FloatLiteral.new(value: expression.value, type:)
|
|
1324
1324
|
when AST::SizeofExpr
|
|
1325
1325
|
target_type = resolve_type_ref_with_fallback(expression.type, env:)
|
|
1326
|
-
target_type ? IR::SizeofExpr.new(target_type:, type:) : raise(LoweringError
|
|
1326
|
+
target_type ? IR::SizeofExpr.new(target_type:, type:) : raise(LoweringError.new("size_of argument is not a concrete type", line: expression.line, column: expression.column, path: @ctx.current_analysis_path))
|
|
1327
1327
|
when AST::AlignofExpr
|
|
1328
1328
|
target_type = resolve_type_ref_with_fallback(expression.type, env:)
|
|
1329
|
-
target_type ? IR::AlignofExpr.new(target_type:, type:) : raise(LoweringError
|
|
1329
|
+
target_type ? IR::AlignofExpr.new(target_type:, type:) : raise(LoweringError.new("align_of argument is not a concrete type", line: expression.line, column: expression.column, path: @ctx.current_analysis_path))
|
|
1330
1330
|
when AST::OffsetofExpr
|
|
1331
1331
|
target_type = resolve_type_ref(expression.type)
|
|
1332
1332
|
if !@bypass_sema_type_cache && (precomputed = @ctx.const_values[@ctx.ast.node_ids[expression.object_id]])
|
|
@@ -1348,6 +1348,8 @@ module MilkTea
|
|
|
1348
1348
|
binding = lookup_value(expression.name, env)
|
|
1349
1349
|
if binding
|
|
1350
1350
|
lower_bound_identifier(binding, expected_type:)
|
|
1351
|
+
elsif (value_param = value_param_literal(expression.name, type))
|
|
1352
|
+
value_param
|
|
1351
1353
|
elsif @ctx.functions.key?(expression.name)
|
|
1352
1354
|
function_binding = @ctx.functions.fetch(expression.name)
|
|
1353
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?
|
|
@@ -1699,13 +1701,24 @@ module MilkTea
|
|
|
1699
1701
|
return unless expression
|
|
1700
1702
|
|
|
1701
1703
|
ct_value = compile_time_const_value(expression, env:)
|
|
1702
|
-
if
|
|
1703
|
-
ct_value.is_a?(Types::Union) || ct_value.is_a?(Types::Nullable) ||
|
|
1704
|
-
ct_value.is_a?(Types::StructInstance)
|
|
1704
|
+
if sized_layout_ct_value?(ct_value)
|
|
1705
1705
|
ct_value
|
|
1706
1706
|
end
|
|
1707
1707
|
end
|
|
1708
1708
|
|
|
1709
|
+
def sized_layout_ct_value?(type)
|
|
1710
|
+
case type
|
|
1711
|
+
when Types::Primitive, Types::Struct, Types::StructInstance, Types::Union, Types::Enum, Types::Flags, Types::Variant, Types::Span, Types::StringView, Types::Task, Types::Event, Types::Subscription
|
|
1712
|
+
true
|
|
1713
|
+
when Types::Nullable
|
|
1714
|
+
true
|
|
1715
|
+
when Types::GenericInstance
|
|
1716
|
+
pointer_type?(type) || array_type?(type) || str_buffer_type?(type)
|
|
1717
|
+
else
|
|
1718
|
+
false
|
|
1719
|
+
end
|
|
1720
|
+
end
|
|
1721
|
+
|
|
1709
1722
|
def build_expression_from_qualified_name(qualified_name)
|
|
1710
1723
|
parts = qualified_name.parts
|
|
1711
1724
|
return unless parts.length >= 1
|
|
@@ -117,7 +117,9 @@ module MilkTea
|
|
|
117
117
|
env = empty_env
|
|
118
118
|
parameter_setup = []
|
|
119
119
|
previous_type_substitutions = @ctx.current_type_substitutions
|
|
120
|
+
previous_value_type_params = @ctx.current_value_type_params
|
|
120
121
|
@ctx.current_type_substitutions = binding.type_substitutions
|
|
122
|
+
@ctx.current_value_type_params = resolve_value_type_params(decl.type_params)
|
|
121
123
|
|
|
122
124
|
return lower_async_function_decl(binding, receiver_type:) if binding.async
|
|
123
125
|
|
|
@@ -176,6 +178,15 @@ module MilkTea
|
|
|
176
178
|
)
|
|
177
179
|
ensure
|
|
178
180
|
@ctx.current_type_substitutions = previous_type_substitutions
|
|
181
|
+
@ctx.current_value_type_params = previous_value_type_params
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def resolve_value_type_params(type_params)
|
|
185
|
+
type_params.each_with_object({}) do |type_param, map|
|
|
186
|
+
next unless type_param.is_a?(AST::ValueTypeParam)
|
|
187
|
+
|
|
188
|
+
map[type_param.name] = resolve_type_ref(type_param.type, type_params: current_type_params)
|
|
189
|
+
end
|
|
179
190
|
end
|
|
180
191
|
|
|
181
192
|
def lower_async_function_decl(binding, receiver_type: nil)
|
|
@@ -9,6 +9,7 @@ module MilkTea
|
|
|
9
9
|
attr_accessor :methods, :attributes, :attribute_applications, :implemented_interfaces
|
|
10
10
|
attr_accessor :struct_types, :union_types, :opaque_types
|
|
11
11
|
attr_accessor :current_type_substitutions
|
|
12
|
+
attr_accessor :current_value_type_params
|
|
12
13
|
attr_accessor :resolved_expr_types
|
|
13
14
|
attr_accessor :resolved_call_kinds
|
|
14
15
|
attr_accessor :const_values
|
|
@@ -27,6 +28,7 @@ module MilkTea
|
|
|
27
28
|
@attribute_applications = {}
|
|
28
29
|
@implemented_interfaces = {}
|
|
29
30
|
@current_type_substitutions = nil
|
|
31
|
+
@current_value_type_params = nil
|
|
30
32
|
@resolved_expr_types = {}
|
|
31
33
|
@resolved_call_kinds = {}
|
|
32
34
|
@const_values = {}
|
|
@@ -699,7 +699,7 @@ module MilkTea
|
|
|
699
699
|
end
|
|
700
700
|
|
|
701
701
|
def infer_expression_type(expression, env:, expected_type: nil)
|
|
702
|
-
if !@bypass_sema_type_cache && expected_type.nil? && (id = @ctx.ast.node_ids[expression.object_id]) && (resolved = @ctx.resolved_expr_types[id])
|
|
702
|
+
if !@bypass_sema_type_cache && expected_type.nil? && !expression.is_a?(AST::Identifier) && (id = @ctx.ast.node_ids[expression.object_id]) && (resolved = @ctx.resolved_expr_types[id])
|
|
703
703
|
return resolved
|
|
704
704
|
end
|
|
705
705
|
|
|
@@ -740,6 +740,9 @@ module MilkTea
|
|
|
740
740
|
when AST::Identifier
|
|
741
741
|
binding = lookup_value(expression.name, env)
|
|
742
742
|
return binding[:type] if binding
|
|
743
|
+
if (value_param_type = value_param_declared_type(expression.name))
|
|
744
|
+
return value_param_type
|
|
745
|
+
end
|
|
743
746
|
return function_type_for_name(expression.name) if @ctx.functions.key?(expression.name)
|
|
744
747
|
|
|
745
748
|
raise LoweringError.new("unknown identifier #{expression.name}", line: expression.line, column: expression.column)
|
|
@@ -2437,6 +2440,25 @@ module MilkTea
|
|
|
2437
2440
|
@ctx.current_type_substitutions || {}
|
|
2438
2441
|
end
|
|
2439
2442
|
|
|
2443
|
+
def value_param_substitution(name)
|
|
2444
|
+
substitution = current_type_params[name]
|
|
2445
|
+
substitution.is_a?(Types::LiteralTypeArg) ? substitution : nil
|
|
2446
|
+
end
|
|
2447
|
+
|
|
2448
|
+
def value_param_declared_type(name)
|
|
2449
|
+
return nil unless value_param_substitution(name)
|
|
2450
|
+
|
|
2451
|
+
@ctx.current_value_type_params&.[](name)
|
|
2452
|
+
end
|
|
2453
|
+
|
|
2454
|
+
def value_param_literal(name, expected_type = nil)
|
|
2455
|
+
substitution = value_param_substitution(name)
|
|
2456
|
+
return nil unless substitution && substitution.value.is_a?(Integer)
|
|
2457
|
+
|
|
2458
|
+
type = @ctx.current_value_type_params&.[](name) || expected_type || @ctx.types.fetch("int")
|
|
2459
|
+
IR::IntegerLiteral.new(value: substitution.value, type:)
|
|
2460
|
+
end
|
|
2461
|
+
|
|
2440
2462
|
def resolve_type_ref(type_ref, type_params: current_type_params)
|
|
2441
2463
|
if type_ref.is_a?(AST::FunctionType)
|
|
2442
2464
|
params = type_ref.params.map do |param|
|
|
@@ -321,7 +321,25 @@ module MilkTea
|
|
|
321
321
|
return literal
|
|
322
322
|
end
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
rewritten = rewrite_static_storage_initializer(expression)
|
|
325
|
+
if (imported_analysis = static_storage_imported_analysis(expression))
|
|
326
|
+
with_analysis_context(imported_analysis) do
|
|
327
|
+
lower_expression(rewritten, env:, expected_type: expected_type)
|
|
328
|
+
end
|
|
329
|
+
else
|
|
330
|
+
lower_expression(rewritten, env:, expected_type: expected_type)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def static_storage_imported_analysis(expression)
|
|
335
|
+
return nil unless expression.is_a?(AST::MemberAccess)
|
|
336
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
337
|
+
return nil unless @ctx.imports.key?(expression.receiver.name)
|
|
338
|
+
|
|
339
|
+
imported_module = @ctx.imports.fetch(expression.receiver.name)
|
|
340
|
+
return nil unless imported_module.values[expression.member]&.kind == :const
|
|
341
|
+
|
|
342
|
+
analysis_for_module(imported_module.name)
|
|
325
343
|
end
|
|
326
344
|
|
|
327
345
|
def lower_compile_time_literal(value, type)
|
|
@@ -337,6 +355,14 @@ module MilkTea
|
|
|
337
355
|
if type == @ctx.types.fetch("str") || type == @ctx.types.fetch("cstr")
|
|
338
356
|
return IR::StringLiteral.new(value:, type:, cstring: type == @ctx.types.fetch("cstr"))
|
|
339
357
|
end
|
|
358
|
+
when Array
|
|
359
|
+
return nil unless array_type?(type)
|
|
360
|
+
|
|
361
|
+
element_type = type.arguments.first
|
|
362
|
+
elements = value.map { |element| lower_compile_time_literal(element, element_type) }
|
|
363
|
+
return nil if elements.any?(&:nil?)
|
|
364
|
+
|
|
365
|
+
IR::ArrayLiteral.new(type:, elements:)
|
|
340
366
|
when Hash
|
|
341
367
|
return nil unless type.is_a?(Types::Struct)
|
|
342
368
|
fields = value.map do |name, field_value|
|
|
@@ -31,6 +31,7 @@ module MilkTea
|
|
|
31
31
|
receiver_type = infer_lvalue_receiver(
|
|
32
32
|
expression.receiver,
|
|
33
33
|
scopes:,
|
|
34
|
+
allow_ref_identifier: true,
|
|
34
35
|
allow_pointer_identifier: true,
|
|
35
36
|
require_mutable_pointer: true,
|
|
36
37
|
allow_span_param_identifier: true,
|
|
@@ -333,6 +334,10 @@ module MilkTea
|
|
|
333
334
|
return binding.type
|
|
334
335
|
end
|
|
335
336
|
|
|
337
|
+
if (value_param_type = current_value_type_params[expression.name])
|
|
338
|
+
return value_param_type
|
|
339
|
+
end
|
|
340
|
+
|
|
336
341
|
if @ctx.top_level_functions.key?(expression.name)
|
|
337
342
|
raise_sema_error("generic function #{expression.name} must be called") if @ctx.top_level_functions.fetch(expression.name).type_params.any?
|
|
338
343
|
|
|
@@ -615,6 +615,7 @@ module MilkTea
|
|
|
615
615
|
|
|
616
616
|
previous_type_substitutions = @current_type_substitutions
|
|
617
617
|
previous_specialization_owner = @current_specialization_owner
|
|
618
|
+
previous_value_type_params = @current_value_type_params
|
|
618
619
|
started_check = false
|
|
619
620
|
return if binding.external
|
|
620
621
|
return if @checked_function_bindings[binding.object_id]
|
|
@@ -624,6 +625,7 @@ module MilkTea
|
|
|
624
625
|
started_check = true
|
|
625
626
|
@current_type_substitutions = binding.type_substitutions
|
|
626
627
|
@current_specialization_owner = binding.specialization_owner
|
|
628
|
+
@current_value_type_params = resolve_value_type_params(binding.ast.type_params)
|
|
627
629
|
with_error_node(binding.ast) do
|
|
628
630
|
with_scope(binding.body_params) do |scopes|
|
|
629
631
|
start_local_completion_frame(binding, scopes)
|
|
@@ -678,8 +680,21 @@ module MilkTea
|
|
|
678
680
|
@nullability_flow_result = nil
|
|
679
681
|
@current_type_substitutions = previous_type_substitutions
|
|
680
682
|
@current_specialization_owner = previous_specialization_owner
|
|
683
|
+
@current_value_type_params = previous_value_type_params
|
|
681
684
|
@checking_function_bindings.delete(binding.object_id)
|
|
682
685
|
end
|
|
686
|
+
|
|
687
|
+
def resolve_value_type_params(type_params)
|
|
688
|
+
type_params.each_with_object({}) do |type_param, map|
|
|
689
|
+
next unless type_param.is_a?(AST::ValueTypeParam)
|
|
690
|
+
|
|
691
|
+
map[type_param.name] = resolve_type_ref(
|
|
692
|
+
type_param.type,
|
|
693
|
+
type_params: current_type_params,
|
|
694
|
+
type_param_constraints: current_type_param_constraints,
|
|
695
|
+
)
|
|
696
|
+
end
|
|
697
|
+
end
|
|
683
698
|
end
|
|
684
699
|
end
|
|
685
700
|
end
|
|
@@ -7,6 +7,10 @@ module MilkTea
|
|
|
7
7
|
@current_type_substitutions || {}
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
def current_value_type_params
|
|
11
|
+
@current_value_type_params || {}
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
def current_type_param_constraints
|
|
11
15
|
@current_type_param_constraints || {}
|
|
12
16
|
end
|
|
@@ -463,9 +467,13 @@ module MilkTea
|
|
|
463
467
|
resolve_imported_module_const_value(type_ref.name.parts.first, type_ref.name.parts.last)
|
|
464
468
|
end
|
|
465
469
|
|
|
466
|
-
return
|
|
470
|
+
return if value.nil?
|
|
471
|
+
return Types::LiteralTypeArg.new(value) if value.is_a?(Integer) || value.is_a?(Float)
|
|
472
|
+
return value if value.is_a?(Types::Base)
|
|
467
473
|
|
|
468
|
-
|
|
474
|
+
nil
|
|
475
|
+
rescue SemanticError
|
|
476
|
+
nil
|
|
469
477
|
end
|
|
470
478
|
|
|
471
479
|
def resolve_current_module_const_value(name)
|
|
@@ -657,12 +665,8 @@ module MilkTea
|
|
|
657
665
|
return false unless expression
|
|
658
666
|
|
|
659
667
|
ct_value = evaluate_compile_time_const_value(expression, scopes:)
|
|
660
|
-
if
|
|
661
|
-
|
|
662
|
-
ct_value.is_a?(Types::StructInstance)
|
|
663
|
-
if sized_layout_type?(ct_value)
|
|
664
|
-
return true
|
|
665
|
-
end
|
|
668
|
+
if sized_layout_type?(ct_value)
|
|
669
|
+
return true
|
|
666
670
|
end
|
|
667
671
|
|
|
668
672
|
false
|
|
@@ -184,6 +184,23 @@ module MilkTea
|
|
|
184
184
|
!binding.external && binding.type_params.empty?
|
|
185
185
|
end
|
|
186
186
|
|
|
187
|
+
def predeclare_top_level_consts
|
|
188
|
+
@ctx.ast.declarations.each do |decl|
|
|
189
|
+
next unless decl.is_a?(AST::ConstDecl)
|
|
190
|
+
|
|
191
|
+
@ctx.const_declarations[decl.name] ||= decl
|
|
192
|
+
next if @ctx.top_level_values.key?(decl.name)
|
|
193
|
+
|
|
194
|
+
@ctx.top_level_values[decl.name] = value_binding(
|
|
195
|
+
name: decl.name,
|
|
196
|
+
type: @error_type,
|
|
197
|
+
mutable: false,
|
|
198
|
+
kind: :const,
|
|
199
|
+
)
|
|
200
|
+
@predeclared_const_names << decl.name
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
187
204
|
def finalize_top_level_const_values
|
|
188
205
|
@ctx.const_declarations.each_key { |name| evaluate_top_level_const_value(name) }
|
|
189
206
|
end
|
|
@@ -247,7 +264,7 @@ module MilkTea
|
|
|
247
264
|
kind: binding.kind,
|
|
248
265
|
const_value: value,
|
|
249
266
|
)
|
|
250
|
-
@evaluated_const_values[name] = true
|
|
267
|
+
@evaluated_const_values[name] = true unless value.nil?
|
|
251
268
|
end
|
|
252
269
|
|
|
253
270
|
def evaluate_compile_time_block(statements, scopes: nil)
|
|
@@ -261,6 +278,10 @@ module MilkTea
|
|
|
261
278
|
end
|
|
262
279
|
|
|
263
280
|
def evaluate_compile_time_const_value(expression, scopes: nil)
|
|
281
|
+
if (type_value = evaluate_type_constructor_index_access(expression, scopes:))
|
|
282
|
+
return type_value
|
|
283
|
+
end
|
|
284
|
+
|
|
264
285
|
CompileTime.evaluate(
|
|
265
286
|
expression,
|
|
266
287
|
resolve_identifier: lambda do |identifier_expression|
|
|
@@ -324,6 +345,26 @@ module MilkTea
|
|
|
324
345
|
raise_sema_error(e.message)
|
|
325
346
|
end
|
|
326
347
|
|
|
348
|
+
def evaluate_type_constructor_index_access(expression, scopes:)
|
|
349
|
+
return nil unless expression.is_a?(AST::IndexAccess)
|
|
350
|
+
return nil unless expression.receiver.is_a?(AST::Identifier)
|
|
351
|
+
return nil unless expression.index.is_a?(AST::Identifier)
|
|
352
|
+
return nil unless %w[ptr const_ptr array span own ref].include?(expression.receiver.name)
|
|
353
|
+
|
|
354
|
+
type_ref = AST::TypeRef.new(
|
|
355
|
+
name: AST::QualifiedName.new(parts: [expression.index.name]),
|
|
356
|
+
arguments: [],
|
|
357
|
+
nullable: false,
|
|
358
|
+
)
|
|
359
|
+
specialization = AST::Specialization.new(
|
|
360
|
+
callee: expression.receiver,
|
|
361
|
+
arguments: [AST::TypeArgument.new(value: type_ref)],
|
|
362
|
+
)
|
|
363
|
+
evaluate_type_returning_call(specialization, scopes:)
|
|
364
|
+
rescue SemanticError
|
|
365
|
+
nil
|
|
366
|
+
end
|
|
367
|
+
|
|
327
368
|
def evaluate_compile_time_call(expression, scopes: nil)
|
|
328
369
|
case expression.callee
|
|
329
370
|
when AST::MemberAccess
|
|
@@ -431,9 +472,31 @@ module MilkTea
|
|
|
431
472
|
end
|
|
432
473
|
return fields
|
|
433
474
|
end
|
|
475
|
+
if resolved_type && array_type?(resolved_type)
|
|
476
|
+
values = []
|
|
477
|
+
expression.arguments.each do |argument|
|
|
478
|
+
val = CompileTime.evaluate(argument.value, resolve_identifier: lambda { |id|
|
|
479
|
+
if scopes
|
|
480
|
+
binding = lookup_value(id.name, scopes)
|
|
481
|
+
return binding.const_value unless binding&.const_value.nil?
|
|
482
|
+
end
|
|
483
|
+
resolve_current_module_const_value(id.name)
|
|
484
|
+
}, resolve_member_access: lambda { |ma|
|
|
485
|
+
if (receiver_type = resolve_type_expression(ma.receiver))
|
|
486
|
+
next resolve_enum_member_const_value(receiver_type, ma.member)
|
|
487
|
+
end
|
|
488
|
+
nil
|
|
489
|
+
}, resolve_call: lambda { |inner_call|
|
|
490
|
+
evaluate_compile_time_call(inner_call, scopes:)
|
|
491
|
+
})
|
|
492
|
+
return nil unless val
|
|
493
|
+
values << val
|
|
494
|
+
end
|
|
495
|
+
return values
|
|
496
|
+
end
|
|
434
497
|
func = @ctx.top_level_functions[callee_name]
|
|
435
498
|
if func&.ast&.respond_to?(:const) && func.ast.const
|
|
436
|
-
evaluate_const_function_body(func, expression.arguments, scopes:)
|
|
499
|
+
evaluate_const_function_body(func, expression.arguments, scopes:, type_args: expression.callee.arguments)
|
|
437
500
|
else
|
|
438
501
|
evaluate_type_returning_call(expression, scopes:)
|
|
439
502
|
end
|
|
@@ -453,7 +516,7 @@ module MilkTea
|
|
|
453
516
|
CompileTime::Reflection.core_evaluate_type_returning(
|
|
454
517
|
callee_name, type_args,
|
|
455
518
|
evaluate_value: ->(v) { evaluate_compile_time_const_value(v, scopes:) },
|
|
456
|
-
resolve_type_ref: ->(tr) { resolve_type_ref(tr) },
|
|
519
|
+
resolve_type_ref: ->(tr) { resolve_named_literal_type_argument(tr) || resolve_type_ref(tr) },
|
|
457
520
|
pointer_to: ->(t) { pointer_to(t) },
|
|
458
521
|
const_pointer_to: ->(t) { const_pointer_to(t) },
|
|
459
522
|
top_level_functions: ->(name) { @ctx.top_level_functions[name] },
|
|
@@ -484,7 +547,11 @@ module MilkTea
|
|
|
484
547
|
when AST::IntegerLiteral
|
|
485
548
|
initial_vars[param.name] = arg_value.value
|
|
486
549
|
when AST::TypeRef
|
|
487
|
-
|
|
550
|
+
if (literal = resolve_named_literal_type_argument(arg_value))
|
|
551
|
+
initial_vars[param.name] = literal.value
|
|
552
|
+
else
|
|
553
|
+
initial_vars[param.name] = resolve_type_ref(arg_value)
|
|
554
|
+
end
|
|
488
555
|
else
|
|
489
556
|
return nil
|
|
490
557
|
end
|
|
@@ -498,10 +565,11 @@ module MilkTea
|
|
|
498
565
|
raise_sema_error(e.message)
|
|
499
566
|
end
|
|
500
567
|
|
|
501
|
-
def evaluate_const_function_body(func, arguments, scopes:)
|
|
568
|
+
def evaluate_const_function_body(func, arguments, scopes:, type_args: nil)
|
|
502
569
|
return nil unless func.ast.params.length == arguments.length
|
|
503
570
|
|
|
504
571
|
initial_vars = {}
|
|
572
|
+
bind_const_function_value_type_params(func, type_args, initial_vars)
|
|
505
573
|
func.ast.params.each_with_index do |param, idx|
|
|
506
574
|
arg_expr = arguments[idx].value
|
|
507
575
|
arg_value = if scopes
|
|
@@ -528,6 +596,25 @@ module MilkTea
|
|
|
528
596
|
raise_sema_error(e.message)
|
|
529
597
|
end
|
|
530
598
|
|
|
599
|
+
def bind_const_function_value_type_params(func, type_args, initial_vars)
|
|
600
|
+
value_params = func.ast.type_params.select { |p| p.is_a?(AST::ValueTypeParam) }
|
|
601
|
+
return if value_params.empty? || type_args.nil?
|
|
602
|
+
|
|
603
|
+
value_params.zip(type_args).each do |param, arg|
|
|
604
|
+
arg_value = arg.value
|
|
605
|
+
case arg_value
|
|
606
|
+
when AST::IntegerLiteral
|
|
607
|
+
initial_vars[param.name] = arg_value.value
|
|
608
|
+
when AST::TypeRef
|
|
609
|
+
if (literal = resolve_named_literal_type_argument(arg_value))
|
|
610
|
+
initial_vars[param.name] = literal.value
|
|
611
|
+
else
|
|
612
|
+
initial_vars[param.name] = resolve_type_ref(arg_value)
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
|
|
531
618
|
def evaluate_has_attribute_call(arguments, scopes:)
|
|
532
619
|
target = evaluate_reflection_target_argument(arguments.first.value, scopes:)
|
|
533
620
|
binding = resolve_attribute_name_argument(arguments[1].value)
|
|
@@ -726,6 +726,8 @@ module MilkTea
|
|
|
726
726
|
|
|
727
727
|
def ensure_available_value_name!(name, kind_label: "value", line: nil, column: nil, length: nil)
|
|
728
728
|
ensure_non_reserved_value_type_name!(name, kind_label:, line:, column:, length:)
|
|
729
|
+
return if @predeclared_const_names.delete?(name)
|
|
730
|
+
|
|
729
731
|
raise_sema_error("duplicate value #{name}") if @ctx.top_level_values.key?(name) || @ctx.top_level_functions.key?(name)
|
|
730
732
|
end
|
|
731
733
|
|
|
@@ -762,6 +764,7 @@ module MilkTea
|
|
|
762
764
|
type: type,
|
|
763
765
|
mutable: false,
|
|
764
766
|
kind: :const,
|
|
767
|
+
const_value: @ctx.top_level_values[decl.name]&.const_value,
|
|
765
768
|
)
|
|
766
769
|
rescue SemanticError => e
|
|
767
770
|
collect_structural_error(e)
|
|
@@ -770,6 +773,7 @@ module MilkTea
|
|
|
770
773
|
type: @error_type,
|
|
771
774
|
mutable: false,
|
|
772
775
|
kind: :const,
|
|
776
|
+
const_value: @ctx.top_level_values[decl.name]&.const_value,
|
|
773
777
|
) unless @ctx.top_level_values.key?(decl.name)
|
|
774
778
|
end
|
|
775
779
|
when AST::VarDecl
|
|
@@ -175,6 +175,7 @@ module MilkTea
|
|
|
175
175
|
@mutable_lvalue_argument_identifier_ids = {}
|
|
176
176
|
@editable_receiver_expression_ids = {}
|
|
177
177
|
@preassigned_local_binding_ids = {}
|
|
178
|
+
@predeclared_const_names = Set.new
|
|
178
179
|
@nullability_flow_result = nil
|
|
179
180
|
@unsafe_statement_lines = []
|
|
180
181
|
@callable_value_identifier_sites = {}
|
|
@@ -196,6 +197,7 @@ module MilkTea
|
|
|
196
197
|
run_phase(:resolve_generic_type_param_constraints, requires: [:declare_named_types])
|
|
197
198
|
run_phase(:resolve_type_aliases, requires: [:declare_named_types])
|
|
198
199
|
run_phase(:declare_attributes)
|
|
200
|
+
run_phase(:predeclare_top_level_consts)
|
|
199
201
|
run_phase(:resolve_aggregate_fields, requires: [:resolve_type_aliases, :declare_named_types])
|
|
200
202
|
run_phase(:resolve_enum_members, requires: [:declare_named_types])
|
|
201
203
|
run_phase(:resolve_variant_arms, requires: [:declare_named_types])
|
|
@@ -260,12 +262,16 @@ module MilkTea
|
|
|
260
262
|
when AST::WhenStmt
|
|
261
263
|
body = when_chosen_body(stmt) || []
|
|
262
264
|
body.each { |nested| collect_emit_from_statements([nested]) }
|
|
263
|
-
when AST::ForStmt, AST::WhileStmt
|
|
265
|
+
when AST::ForStmt, AST::WhileStmt
|
|
264
266
|
next unless stmt.inline
|
|
265
267
|
stmt.body&.each { |s| collect_emit_from_statements([s]) }
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
when AST::IfStmt
|
|
269
|
+
next unless stmt.inline
|
|
270
|
+
stmt.branches.each { |branch| collect_emit_from_statements(branch.body) }
|
|
271
|
+
stmt.else_body&.each { |s| collect_emit_from_statements([s]) }
|
|
272
|
+
when AST::MatchStmt
|
|
273
|
+
next unless stmt.inline
|
|
274
|
+
stmt.arms.each { |arm| collect_emit_from_statements(arm.body) }
|
|
269
275
|
end
|
|
270
276
|
end
|
|
271
277
|
end
|
|
@@ -302,6 +308,7 @@ module MilkTea
|
|
|
302
308
|
run_collecting_phase(:resolve_generic_type_param_constraints, requires: [:declare_named_types])
|
|
303
309
|
run_collecting_phase(:resolve_type_aliases, requires: [:declare_named_types])
|
|
304
310
|
run_collecting_phase(:declare_attributes)
|
|
311
|
+
run_collecting_phase(:predeclare_top_level_consts)
|
|
305
312
|
run_collecting_phase(:resolve_aggregate_fields, requires: [:resolve_type_aliases, :declare_named_types])
|
|
306
313
|
run_collecting_phase(:resolve_enum_members, requires: [:declare_named_types])
|
|
307
314
|
run_collecting_phase(:resolve_variant_arms, requires: [:declare_named_types])
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mt-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.34
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -624,7 +624,7 @@ metadata:
|
|
|
624
624
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
625
625
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
626
626
|
post_install_message: |
|
|
627
|
-
Milk Tea 0.3.
|
|
627
|
+
Milk Tea 0.3.34 installed!
|
|
628
628
|
|
|
629
629
|
System requirements:
|
|
630
630
|
- A C compiler (gcc or clang) must be available on PATH
|