mt-lang 0.3.24 → 0.3.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/bindings/attribute_binding.rb +51 -49
- data/lib/milk_tea/core/bindings/function_binding.rb +3 -1
- data/lib/milk_tea/core/bindings/module_binding.rb +42 -40
- data/lib/milk_tea/core/bindings/value_binding.rb +16 -14
- data/lib/milk_tea/core/bindings.rb +4 -9
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +11 -11
- data/lib/milk_tea/core/c_backend/expressions.rb +11 -11
- data/lib/milk_tea/core/c_backend/feature_detection.rb +15 -19
- data/lib/milk_tea/core/c_backend/format_helpers.rb +1 -1
- data/lib/milk_tea/core/c_backend/reinterpret.rb +10 -10
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1 -1
- data/lib/milk_tea/core/c_backend/statements.rb +20 -20
- data/lib/milk_tea/core/c_backend/type_declaration.rb +4 -4
- data/lib/milk_tea/core/c_backend/type_system.rb +1 -1
- data/lib/milk_tea/core/c_backend.rb +3 -3
- data/lib/milk_tea/core/compile_time.rb +41 -70
- data/lib/milk_tea/core/control_flow/builder.rb +3 -3
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +1 -1
- data/lib/milk_tea/core/control_flow/graph.rb +1 -1
- data/lib/milk_tea/core/control_flow/termination.rb +1 -1
- data/lib/milk_tea/core/cst.rb +16 -0
- data/lib/milk_tea/core/flow_scope.rb +13 -0
- data/lib/milk_tea/core/lexer/character_classes.rb +2 -2
- data/lib/milk_tea/core/lexer/format_strings.rb +5 -5
- data/lib/milk_tea/core/lexer/heredocs.rb +6 -6
- data/lib/milk_tea/core/lexer/indentation.rb +4 -4
- data/lib/milk_tea/core/lexer/numbers.rb +1 -1
- data/lib/milk_tea/core/lexer/strings.rb +4 -4
- data/lib/milk_tea/core/lexer/symbols.rb +3 -3
- data/lib/milk_tea/core/lexer/trivia.rb +4 -4
- data/lib/milk_tea/core/lexer.rb +17 -17
- data/lib/milk_tea/core/lowering/async/analysis.rb +210 -208
- data/lib/milk_tea/core/lowering/async/async_lowering.rb +1406 -0
- data/lib/milk_tea/core/lowering/async/frame_builder.rb +615 -613
- data/lib/milk_tea/core/lowering/async/normalization.rb +410 -408
- data/lib/milk_tea/core/lowering/block.rb +982 -980
- data/lib/milk_tea/core/lowering/calls.rb +1360 -1358
- data/lib/milk_tea/core/lowering/declarations.rb +175 -173
- data/lib/milk_tea/core/lowering/dyn.rb +171 -169
- data/lib/milk_tea/core/lowering/events.rb +946 -944
- data/lib/milk_tea/core/lowering/expressions.rb +1514 -1512
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +180 -178
- data/lib/milk_tea/core/lowering/functions.rb +186 -184
- data/lib/milk_tea/core/lowering/loops.rb +1004 -1002
- data/lib/milk_tea/core/lowering/lowering_context.rb +1 -1
- data/lib/milk_tea/core/lowering/proc.rb +355 -353
- data/lib/milk_tea/core/lowering/resolve.rb +2127 -2125
- data/lib/milk_tea/core/lowering/scans.rb +162 -168
- data/lib/milk_tea/core/lowering/str_buffer.rb +104 -102
- data/lib/milk_tea/core/lowering/utils.rb +964 -963
- data/lib/milk_tea/core/lowering.rb +22 -22
- data/lib/milk_tea/core/module_binder.rb +1 -1
- data/lib/milk_tea/core/module_loader.rb +2 -2
- data/lib/milk_tea/core/parser/attributes.rb +1 -1
- data/lib/milk_tea/core/parser/blocks.rb +2 -2
- data/lib/milk_tea/core/parser/declarations.rb +15 -15
- data/lib/milk_tea/core/parser/expressions.rb +20 -20
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser/statements.rb +3 -3
- data/lib/milk_tea/core/parser/types.rb +4 -4
- data/lib/milk_tea/core/parser.rb +39 -21
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +6 -6
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +5 -5
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +2 -2
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +37 -37
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +7 -7
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +59 -59
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +3 -3
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +12 -12
- data/lib/milk_tea/core/types/layout.rb +3 -1
- data/lib/milk_tea/core/types/visitor.rb +351 -349
- data/lib/milk_tea/core.rb +0 -2
- data/lib/milk_tea/tooling/cli/commands/bindgen.rb +1 -1
- data/lib/milk_tea/tooling/cli/commands/check.rb +5 -5
- data/lib/milk_tea/tooling/cli/commands/debug.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/deps.rb +1 -1
- data/lib/milk_tea/tooling/cli/commands/emit_c.rb +2 -2
- data/lib/milk_tea/tooling/cli/commands/format.rb +6 -6
- data/lib/milk_tea/tooling/cli/commands/lint.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/lower.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/parse.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/test.rb +3 -3
- data/lib/milk_tea/tooling/cli/commands/toolchain.rb +1 -1
- data/lib/milk_tea/tooling/cli.rb +22 -34
- data/lib/milk_tea/tooling/linter/flow_rules.rb +3 -3
- metadata +4 -5
- data/lib/milk_tea/core/cst_builder.rb +0 -19
- data/lib/milk_tea/core/lowering/async/lowering.rb +0 -1404
- data/lib/milk_tea/core/token_stream.rb +0 -30
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
# .imports imported module bindings
|
|
11
11
|
# .types Hash[name → Types::Base]
|
|
12
12
|
# .interfaces Hash[name → InterfaceBinding|GenericInterfaceBinding]
|
|
13
|
-
# .attributes Hash[name → AttributeBinding]
|
|
13
|
+
# .attributes Hash[name → Bindings::AttributeBinding]
|
|
14
14
|
# .attribute_applications Hash[...]
|
|
15
|
-
# .values Hash[name → ValueBinding]
|
|
16
|
-
# .functions Hash[name → FunctionBinding]
|
|
17
|
-
# .methods Hash[type → Hash[name → FunctionBinding]]
|
|
15
|
+
# .values Hash[name → Bindings::ValueBinding]
|
|
16
|
+
# .functions Hash[name → Bindings::FunctionBinding]
|
|
17
|
+
# .methods Hash[type → Hash[name → Bindings::FunctionBinding]]
|
|
18
18
|
# .implemented_interfaces Hash[type → Set[InterfaceBinding]]
|
|
19
19
|
# .resolved_expr_types Hash[expression.object_id → Types::Base]
|
|
20
20
|
# .uses_parallel_for bool
|
|
@@ -30,7 +30,7 @@ require_relative "lowering/events"
|
|
|
30
30
|
require_relative "lowering/functions"
|
|
31
31
|
require_relative "lowering/async/analysis"
|
|
32
32
|
require_relative "lowering/async/normalization"
|
|
33
|
-
require_relative "lowering/async/
|
|
33
|
+
require_relative "lowering/async/async_lowering"
|
|
34
34
|
require_relative "lowering/async/frame_builder"
|
|
35
35
|
require_relative "lowering/block"
|
|
36
36
|
require_relative "lowering/proc"
|
|
@@ -61,7 +61,7 @@ module MilkTea
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
module Lowering
|
|
65
65
|
def self.lower(program)
|
|
66
66
|
lowerer = Lowerer.new(program)
|
|
67
67
|
ir_program, _modules, _synths = lowerer.lower_and_assemble
|
|
@@ -90,25 +90,25 @@ module MilkTea
|
|
|
90
90
|
attr_accessor :bypass_sema_type_cache
|
|
91
91
|
attr_reader :recorded_expr_types
|
|
92
92
|
|
|
93
|
-
include
|
|
94
|
-
include
|
|
95
|
-
include
|
|
96
|
-
include
|
|
97
|
-
include
|
|
98
|
-
include
|
|
99
|
-
include
|
|
100
|
-
include
|
|
101
|
-
include
|
|
102
|
-
include
|
|
103
|
-
include
|
|
104
|
-
include
|
|
105
|
-
include
|
|
106
|
-
include
|
|
107
|
-
include
|
|
93
|
+
include Lowering::Scans
|
|
94
|
+
include Lowering::Declarations
|
|
95
|
+
include Lowering::Events
|
|
96
|
+
include Lowering::Functions
|
|
97
|
+
include Lowering::Async
|
|
98
|
+
include Lowering::Block
|
|
99
|
+
include Lowering::Proc
|
|
100
|
+
include Lowering::Loops
|
|
101
|
+
include Lowering::Expressions
|
|
102
|
+
include Lowering::Calls
|
|
103
|
+
include Lowering::ForeignCstr
|
|
104
|
+
include Lowering::StrBuffer
|
|
105
|
+
include Lowering::Resolve
|
|
106
|
+
include Lowering::Dyn
|
|
107
|
+
include Lowering::Utils
|
|
108
108
|
|
|
109
109
|
def initialize(program)
|
|
110
110
|
@program = program
|
|
111
|
-
@ctx =
|
|
111
|
+
@ctx = LoweringContext.new
|
|
112
112
|
@artifacts = Artifacts.new
|
|
113
113
|
@synthetic_proc_counter = 0
|
|
114
114
|
@parallel_for_counter = 0
|
|
@@ -44,7 +44,7 @@ module MilkTea
|
|
|
44
44
|
methods, private_methods = exported_methods(analysis, types)
|
|
45
45
|
implemented_interfaces, private_implemented_interfaces = exported_interface_implementations(analysis, types, interfaces)
|
|
46
46
|
|
|
47
|
-
ModuleBinding.new(
|
|
47
|
+
Bindings::ModuleBinding.new(
|
|
48
48
|
name: analysis.module_name,
|
|
49
49
|
types:,
|
|
50
50
|
type_declarations:,
|
|
@@ -651,7 +651,7 @@ module MilkTea
|
|
|
651
651
|
full_binding.types.reject { |name, _| fw_binding.types.key?(name) }
|
|
652
652
|
)
|
|
653
653
|
|
|
654
|
-
@forward_bindings[resolved_path] = ModuleBinding.new(
|
|
654
|
+
@forward_bindings[resolved_path] = Bindings::ModuleBinding.new(
|
|
655
655
|
name: full_binding.name,
|
|
656
656
|
types: merged_types,
|
|
657
657
|
type_declarations: full_binding.type_declarations,
|
|
@@ -699,7 +699,7 @@ module MilkTea
|
|
|
699
699
|
end
|
|
700
700
|
end
|
|
701
701
|
|
|
702
|
-
ModuleBinding.new(
|
|
702
|
+
Bindings::ModuleBinding.new(
|
|
703
703
|
name: module_name, types:, type_declarations: {},
|
|
704
704
|
interfaces: {}, attributes: {}, attribute_applications: {},
|
|
705
705
|
values: {}, functions: {}, methods: {},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
|
|
4
|
+
class Parser
|
|
5
5
|
module Blocks
|
|
6
6
|
def parse_block
|
|
7
7
|
consume(:colon, "expected ':' before block")
|
|
@@ -51,7 +51,7 @@ module MilkTea
|
|
|
51
51
|
statements
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def
|
|
54
|
+
def parse_recoverable_block(&block)
|
|
55
55
|
consume(:colon, "expected ':' before block")
|
|
56
56
|
consume(:newline, "expected newline before block")
|
|
57
57
|
consume(:indent, "expected indented block")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
|
|
4
|
+
class Parser
|
|
5
5
|
module Declarations
|
|
6
6
|
def parse_import
|
|
7
7
|
line = previous.line
|
|
@@ -375,9 +375,9 @@ module MilkTea
|
|
|
375
375
|
name = name_token.lexeme
|
|
376
376
|
lifetime_params, type_params = parse_struct_decl_params
|
|
377
377
|
implements = parse_implements_clause
|
|
378
|
-
c_name =
|
|
378
|
+
c_name = parse_optional_c_name
|
|
379
379
|
packed, alignment = parse_struct_layout_attributes(attributes) if attributes.any?
|
|
380
|
-
members =
|
|
380
|
+
members = parse_recoverable_block do
|
|
381
381
|
parse_struct_member
|
|
382
382
|
end
|
|
383
383
|
fields = members.filter_map { |kind, member| member if kind == :field }
|
|
@@ -462,8 +462,8 @@ module MilkTea
|
|
|
462
462
|
line = previous.line
|
|
463
463
|
name_token = consume_name("expected union name")
|
|
464
464
|
name = name_token.lexeme
|
|
465
|
-
c_name =
|
|
466
|
-
fields =
|
|
465
|
+
c_name = parse_optional_c_name
|
|
466
|
+
fields = parse_recoverable_block do
|
|
467
467
|
field_name = consume_name_allowing_keywords("expected field name").lexeme
|
|
468
468
|
consume(:colon, "expected ':' after field name")
|
|
469
469
|
field_type = parse_type_ref
|
|
@@ -473,7 +473,7 @@ module MilkTea
|
|
|
473
473
|
AST::UnionDecl.new(name:, c_name:, fields:, visibility:, attributes:, line:, column: name_token.column)
|
|
474
474
|
end
|
|
475
475
|
|
|
476
|
-
def
|
|
476
|
+
def parse_optional_c_name
|
|
477
477
|
return nil unless match(:equal)
|
|
478
478
|
|
|
479
479
|
consume(:cstring, "expected C string literal after '='").literal
|
|
@@ -516,7 +516,7 @@ module MilkTea
|
|
|
516
516
|
name_token = consume_name("expected variant name")
|
|
517
517
|
name = name_token.lexeme
|
|
518
518
|
type_params = parse_declaration_type_params
|
|
519
|
-
arms =
|
|
519
|
+
arms = parse_recoverable_block do
|
|
520
520
|
arm_name = consume_name_allowing_keywords("expected variant arm name").lexeme
|
|
521
521
|
fields = if match(:lparen)
|
|
522
522
|
parsed = parse_comma_separated_until(:rparen) do
|
|
@@ -554,7 +554,7 @@ module MilkTea
|
|
|
554
554
|
name_token = consume_name("expected interface name")
|
|
555
555
|
name = name_token.lexeme
|
|
556
556
|
type_params = parse_declaration_type_params
|
|
557
|
-
methods =
|
|
557
|
+
methods = parse_recoverable_block do
|
|
558
558
|
method_attributes = parse_attribute_applications
|
|
559
559
|
parse_interface_method_decl(attributes: method_attributes)
|
|
560
560
|
end
|
|
@@ -566,7 +566,7 @@ module MilkTea
|
|
|
566
566
|
type_name = parse_type_ref
|
|
567
567
|
receiver_type_param_names = extending_target_type_param_names(type_name)
|
|
568
568
|
methods = with_type_param_names(receiver_type_param_names) do
|
|
569
|
-
|
|
569
|
+
parse_recoverable_block do
|
|
570
570
|
method_attributes = parse_attribute_applications
|
|
571
571
|
parse_method_def(attributes: method_attributes)
|
|
572
572
|
end
|
|
@@ -588,7 +588,7 @@ module MilkTea
|
|
|
588
588
|
end
|
|
589
589
|
if value.name.parts.length == 1 && value.arguments.empty? && !value.nullable
|
|
590
590
|
name = value.name.parts.first
|
|
591
|
-
nested_names << name unless
|
|
591
|
+
nested_names << name unless known_type_context_name?(name)
|
|
592
592
|
end
|
|
593
593
|
nested_names
|
|
594
594
|
when AST::FunctionType, AST::ProcType
|
|
@@ -613,7 +613,7 @@ module MilkTea
|
|
|
613
613
|
end
|
|
614
614
|
|
|
615
615
|
def parse_method_def(attributes: [])
|
|
616
|
-
visibility, _visibility_token, async, kind, line, name_token =
|
|
616
|
+
visibility, _visibility_token, async, kind, line, name_token = parse_method_head
|
|
617
617
|
name = name_token.lexeme
|
|
618
618
|
type_params, params, return_type, body = parse_callable_signature
|
|
619
619
|
AST::MethodDef.new(name:, type_params:, params:, return_type:, body:, kind:, visibility:, async:, attributes:, line:, column: name_token.column)
|
|
@@ -628,7 +628,7 @@ module MilkTea
|
|
|
628
628
|
end
|
|
629
629
|
|
|
630
630
|
def parse_interface_method_decl(attributes: [])
|
|
631
|
-
visibility, visibility_token, async, kind, line, name_token =
|
|
631
|
+
visibility, visibility_token, async, kind, line, name_token = parse_method_head
|
|
632
632
|
raise error(visibility_token, "public is not allowed on interface methods") if visibility == :public
|
|
633
633
|
|
|
634
634
|
name = name_token.lexeme
|
|
@@ -641,7 +641,7 @@ module MilkTea
|
|
|
641
641
|
AST::InterfaceMethodDecl.new(name:, params:, return_type:, kind:, async:, attributes:, line:, column: name_token.column)
|
|
642
642
|
end
|
|
643
643
|
|
|
644
|
-
def
|
|
644
|
+
def parse_method_head
|
|
645
645
|
visibility, visibility_token = parse_visibility
|
|
646
646
|
async = match(:async)
|
|
647
647
|
kind = parse_method_kind
|
|
@@ -679,7 +679,7 @@ module MilkTea
|
|
|
679
679
|
params = parse_params
|
|
680
680
|
return_type = match(:arrow) ? parse_type_ref : nil
|
|
681
681
|
if allow_body
|
|
682
|
-
body =
|
|
682
|
+
body = parse_block_body_with_recovery
|
|
683
683
|
else
|
|
684
684
|
consume_end_of_statement
|
|
685
685
|
end
|
|
@@ -688,7 +688,7 @@ module MilkTea
|
|
|
688
688
|
[type_params, params, return_type, body]
|
|
689
689
|
end
|
|
690
690
|
|
|
691
|
-
def
|
|
691
|
+
def parse_block_body_with_recovery
|
|
692
692
|
parse_block
|
|
693
693
|
rescue ParseError => e
|
|
694
694
|
raise unless @recovery_errors
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
|
|
4
|
+
class Parser
|
|
5
5
|
module Expressions
|
|
6
6
|
def parse_expression
|
|
7
7
|
return parse_if_expression if match(:if)
|
|
@@ -231,7 +231,7 @@ module MilkTea
|
|
|
231
231
|
|
|
232
232
|
def try_parse_prefix_cast_expression
|
|
233
233
|
saved_current = @current
|
|
234
|
-
return nil unless check_name &&
|
|
234
|
+
return nil unless check_name && known_type_context_name?(peek.lexeme)
|
|
235
235
|
|
|
236
236
|
start_token = peek
|
|
237
237
|
expression = nil
|
|
@@ -253,7 +253,7 @@ module MilkTea
|
|
|
253
253
|
expression = parse_unary
|
|
254
254
|
AST::PrefixCast.new(target_type:, expression:, line: start_token.line, column: start_token.column)
|
|
255
255
|
rescue ParseError => e
|
|
256
|
-
raise e if
|
|
256
|
+
raise e if diagnostic_hint_error?(e)
|
|
257
257
|
|
|
258
258
|
nil
|
|
259
259
|
ensure
|
|
@@ -324,7 +324,7 @@ module MilkTea
|
|
|
324
324
|
|
|
325
325
|
AST::Specialization.new(callee: expression, arguments:)
|
|
326
326
|
rescue ParseError => e
|
|
327
|
-
raise e if
|
|
327
|
+
raise e if diagnostic_hint_error?(e)
|
|
328
328
|
|
|
329
329
|
@current = saved_current
|
|
330
330
|
nil
|
|
@@ -344,7 +344,7 @@ module MilkTea
|
|
|
344
344
|
end
|
|
345
345
|
|
|
346
346
|
def parse_call_argument
|
|
347
|
-
if (check_name ||
|
|
347
|
+
if (check_name || keyword?(peek)) && check_next(:equal)
|
|
348
348
|
name = advance.lexeme
|
|
349
349
|
consume(:equal, "expected '=' after named argument name")
|
|
350
350
|
AST::Argument.new(name:, value: parse_expression)
|
|
@@ -355,15 +355,15 @@ module MilkTea
|
|
|
355
355
|
|
|
356
356
|
def parse_primary
|
|
357
357
|
if match(:size_of)
|
|
358
|
-
|
|
358
|
+
parse_sizeof_expression
|
|
359
359
|
elsif match(:align_of)
|
|
360
|
-
|
|
360
|
+
parse_alignof_expression
|
|
361
361
|
elsif match(:offset_of)
|
|
362
|
-
|
|
362
|
+
parse_offsetof_expression
|
|
363
363
|
elsif match(:members_of) || match(:attributes_of) || match(:field_of) || match(:callable_of) || match(:attribute_of) || match(:has_attribute) || match(:attribute_arg) || match(:fields_of)
|
|
364
364
|
AST::Identifier.new(name: previous.lexeme, line: previous.line, column: previous.column)
|
|
365
365
|
elsif match(:proc)
|
|
366
|
-
|
|
366
|
+
parse_proc_expression
|
|
367
367
|
elsif match_name
|
|
368
368
|
AST::Identifier.new(name: previous.lexeme, line: previous.line, column: previous.column)
|
|
369
369
|
elsif match(:integer)
|
|
@@ -394,7 +394,7 @@ module MilkTea
|
|
|
394
394
|
elsif match(:lparen)
|
|
395
395
|
line = previous.line
|
|
396
396
|
column = previous.column
|
|
397
|
-
first = if (check_name ||
|
|
397
|
+
first = if (check_name || keyword?(peek)) && check_next(:equal)
|
|
398
398
|
name_token = advance
|
|
399
399
|
consume(:equal, "expected '=' after named tuple field")
|
|
400
400
|
AST::Argument.new(name: name_token.lexeme, value: parse_expression)
|
|
@@ -404,7 +404,7 @@ module MilkTea
|
|
|
404
404
|
if match(:comma)
|
|
405
405
|
elements = [first]
|
|
406
406
|
loop do
|
|
407
|
-
if (check_name ||
|
|
407
|
+
if (check_name || keyword?(peek)) && check_next(:equal)
|
|
408
408
|
name_token = advance
|
|
409
409
|
consume(:equal, "expected '=' after named tuple field")
|
|
410
410
|
value = parse_expression
|
|
@@ -421,7 +421,7 @@ module MilkTea
|
|
|
421
421
|
consume(:rparen, "expected ')' after expression")
|
|
422
422
|
first
|
|
423
423
|
end
|
|
424
|
-
elsif
|
|
424
|
+
elsif keyword?(peek)
|
|
425
425
|
advance
|
|
426
426
|
AST::Identifier.new(name: previous.lexeme, line: previous.line, column: previous.column)
|
|
427
427
|
else
|
|
@@ -444,9 +444,9 @@ module MilkTea
|
|
|
444
444
|
AST::StringLiteral.new(lexeme:, value:, cstring: all_cstring)
|
|
445
445
|
end
|
|
446
446
|
|
|
447
|
-
def
|
|
447
|
+
def parse_proc_expression
|
|
448
448
|
consume(:lparen, "expected '(' after proc")
|
|
449
|
-
params = parse_comma_separated_until(:rparen) {
|
|
449
|
+
params = parse_comma_separated_until(:rparen) { parse_callable_type_param }
|
|
450
450
|
|
|
451
451
|
consume(:rparen, "expected ')' after proc parameters")
|
|
452
452
|
consume(:arrow, "expected '->' after proc parameters")
|
|
@@ -463,21 +463,21 @@ module MilkTea
|
|
|
463
463
|
AST::ProcExpr.new(params:, return_type:, body:)
|
|
464
464
|
end
|
|
465
465
|
|
|
466
|
-
def
|
|
466
|
+
def parse_sizeof_expression
|
|
467
467
|
consume(:lparen, "expected '(' after size_of")
|
|
468
468
|
type = parse_type_ref
|
|
469
469
|
consume(:rparen, "expected ')' after size_of type")
|
|
470
470
|
AST::SizeofExpr.new(type:)
|
|
471
471
|
end
|
|
472
472
|
|
|
473
|
-
def
|
|
473
|
+
def parse_alignof_expression
|
|
474
474
|
consume(:lparen, "expected '(' after align_of")
|
|
475
475
|
type = parse_type_ref
|
|
476
476
|
consume(:rparen, "expected ')' after align_of type")
|
|
477
477
|
AST::AlignofExpr.new(type:)
|
|
478
478
|
end
|
|
479
479
|
|
|
480
|
-
def
|
|
480
|
+
def parse_offsetof_expression
|
|
481
481
|
consume(:lparen, "expected '(' after offset_of")
|
|
482
482
|
type = parse_type_ref
|
|
483
483
|
consume(:comma, "expected ',' after offset_of type")
|
|
@@ -581,7 +581,7 @@ module MilkTea
|
|
|
581
581
|
expression.is_a?(AST::Identifier) && %w[array reinterpret span zero ptr const_ptr own ref adapt equal hash order simd SoA].include?(expression.name)
|
|
582
582
|
end
|
|
583
583
|
|
|
584
|
-
def
|
|
584
|
+
def diagnostic_hint_error?(error)
|
|
585
585
|
error.message.include?("did you mean T<-expr?")
|
|
586
586
|
end
|
|
587
587
|
|
|
@@ -598,7 +598,7 @@ module MilkTea
|
|
|
598
598
|
|
|
599
599
|
def specialization_call_target?(expression, arguments, call_arguments)
|
|
600
600
|
if expression.is_a?(AST::Identifier) && %w[default zero].include?(expression.name) &&
|
|
601
|
-
!
|
|
601
|
+
!known_type_context_name?(expression.name) && !generic_callable_specialization_target?(expression)
|
|
602
602
|
return false
|
|
603
603
|
end
|
|
604
604
|
|
|
@@ -643,7 +643,7 @@ module MilkTea
|
|
|
643
643
|
when AST::FunctionType, AST::TupleType
|
|
644
644
|
true
|
|
645
645
|
when AST::TypeRef
|
|
646
|
-
|
|
646
|
+
known_type_context_name?(value.name.parts.first)
|
|
647
647
|
else
|
|
648
648
|
false
|
|
649
649
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
|
|
4
|
+
class Parser
|
|
5
5
|
module Statements
|
|
6
6
|
def check_inline_stmt_start?
|
|
7
7
|
return false unless check(:inline)
|
|
@@ -363,7 +363,7 @@ module MilkTea
|
|
|
363
363
|
binding_token.lexeme
|
|
364
364
|
end
|
|
365
365
|
|
|
366
|
-
if
|
|
366
|
+
if match_arm_expression_form?
|
|
367
367
|
consume(:colon, "expected ':' after match expression arm pattern")
|
|
368
368
|
value = parse_expression
|
|
369
369
|
finish_expression_statement(value)
|
|
@@ -410,7 +410,7 @@ module MilkTea
|
|
|
410
410
|
raise
|
|
411
411
|
end
|
|
412
412
|
|
|
413
|
-
def
|
|
413
|
+
def match_arm_expression_form?
|
|
414
414
|
check(:colon) && @current + 1 < @tokens.length && @tokens[@current + 1].type != :newline
|
|
415
415
|
end
|
|
416
416
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
|
-
|
|
4
|
+
class Parser
|
|
5
5
|
module Types
|
|
6
6
|
def parse_params(allow_variadic: false)
|
|
7
7
|
parse_parameter_list(allow_variadic:) { parse_param }
|
|
@@ -63,7 +63,7 @@ module MilkTea
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def parse_foreign_param
|
|
66
|
-
mode = if
|
|
66
|
+
mode = if foreign_param_mode_start?
|
|
67
67
|
advance.type
|
|
68
68
|
else
|
|
69
69
|
:plain
|
|
@@ -158,7 +158,7 @@ module MilkTea
|
|
|
158
158
|
|
|
159
159
|
def parse_callable_type_ref(keyword:, param_context:)
|
|
160
160
|
consume(:lparen, "expected '(' after #{keyword}")
|
|
161
|
-
params = parse_comma_separated_until(:rparen) {
|
|
161
|
+
params = parse_comma_separated_until(:rparen) { parse_callable_type_param }
|
|
162
162
|
|
|
163
163
|
consume(:rparen, "expected ')' after #{param_context}")
|
|
164
164
|
consume(:arrow, "expected '->' after #{param_context}")
|
|
@@ -166,7 +166,7 @@ module MilkTea
|
|
|
166
166
|
yield params, return_type
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
def
|
|
169
|
+
def parse_callable_type_param
|
|
170
170
|
name_token = consume_name_allowing_keywords("expected function type parameter name")
|
|
171
171
|
name = name_token.lexeme
|
|
172
172
|
consume(:colon, "expected ':' after function type parameter name")
|
data/lib/milk_tea/core/parser.rb
CHANGED
|
@@ -33,6 +33,24 @@ module MilkTea
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
class SyntaxTokenStream
|
|
37
|
+
def initialize(tokens)
|
|
38
|
+
@tokens = tokens
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def [](index)
|
|
42
|
+
@tokens[index]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def length
|
|
46
|
+
@tokens.length
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def to_a
|
|
50
|
+
@tokens
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
36
54
|
class Parser
|
|
37
55
|
ParseRecoveryResult = Data.define(:ast, :errors) do
|
|
38
56
|
def initialize(ast:, errors: []) = super
|
|
@@ -40,13 +58,13 @@ module MilkTea
|
|
|
40
58
|
|
|
41
59
|
ParseContext = Data.define(:known_type_names, :known_import_aliases, :known_generic_callable_names, :current_type_param_names)
|
|
42
60
|
|
|
43
|
-
include
|
|
44
|
-
include
|
|
45
|
-
include
|
|
46
|
-
include
|
|
47
|
-
include
|
|
48
|
-
include
|
|
49
|
-
include
|
|
61
|
+
include Blocks
|
|
62
|
+
include Recovery
|
|
63
|
+
include Types
|
|
64
|
+
include Attributes
|
|
65
|
+
include Expressions
|
|
66
|
+
include Declarations
|
|
67
|
+
include Statements
|
|
50
68
|
|
|
51
69
|
def self.parse(source = nil, path: nil, tokens: nil)
|
|
52
70
|
token_stream = tokens || Lexer.lex(source, path: path)
|
|
@@ -106,7 +124,7 @@ module MilkTea
|
|
|
106
124
|
directives = []
|
|
107
125
|
declarations = []
|
|
108
126
|
|
|
109
|
-
if
|
|
127
|
+
if at_external_file?
|
|
110
128
|
advance
|
|
111
129
|
module_line = previous.line
|
|
112
130
|
module_kind = :raw_module
|
|
@@ -150,7 +168,7 @@ module MilkTea
|
|
|
150
168
|
AST.assign_node_ids(AST::SourceFile.new(module_name:, module_kind:, imports:, directives:, declarations:, line: module_line))
|
|
151
169
|
end
|
|
152
170
|
|
|
153
|
-
def
|
|
171
|
+
def at_external_file?
|
|
154
172
|
return false unless check(:external)
|
|
155
173
|
|
|
156
174
|
next_token = @tokens[@current + 1]
|
|
@@ -188,7 +206,7 @@ module MilkTea
|
|
|
188
206
|
end
|
|
189
207
|
|
|
190
208
|
def consume_name(message)
|
|
191
|
-
if
|
|
209
|
+
if keyword?(peek)
|
|
192
210
|
name_role = message.sub(/\A(?:expected|required)\s+/, "")
|
|
193
211
|
clearer_message = if name_role == message
|
|
194
212
|
message
|
|
@@ -204,14 +222,14 @@ module MilkTea
|
|
|
204
222
|
def consume_name_allowing_keywords(message)
|
|
205
223
|
if check(:identifier)
|
|
206
224
|
advance
|
|
207
|
-
elsif
|
|
225
|
+
elsif keyword?(peek)
|
|
208
226
|
advance
|
|
209
227
|
else
|
|
210
228
|
raise error(peek, message)
|
|
211
229
|
end
|
|
212
230
|
end
|
|
213
231
|
|
|
214
|
-
def
|
|
232
|
+
def keyword?(token)
|
|
215
233
|
token && Token::KEYWORDS.key?(token.lexeme)
|
|
216
234
|
end
|
|
217
235
|
|
|
@@ -288,7 +306,7 @@ module MilkTea
|
|
|
288
306
|
items
|
|
289
307
|
end
|
|
290
308
|
|
|
291
|
-
def
|
|
309
|
+
def foreign_param_mode_start?
|
|
292
310
|
return false unless %i[out in inout consuming].include?(peek.type)
|
|
293
311
|
|
|
294
312
|
@tokens[@current + 1]&.type == :identifier
|
|
@@ -298,7 +316,7 @@ module MilkTea
|
|
|
298
316
|
token&.type == :identifier && BUILTIN_ATTRIBUTE_NAME_LEXEMES.include?(token.lexeme)
|
|
299
317
|
end
|
|
300
318
|
|
|
301
|
-
def
|
|
319
|
+
def known_type_context_name?(name)
|
|
302
320
|
@known_type_names.key?(name) || @known_import_aliases.key?(name) || @current_type_param_names.include?(name)
|
|
303
321
|
end
|
|
304
322
|
|
|
@@ -348,7 +366,7 @@ module MilkTea
|
|
|
348
366
|
if depth.zero?
|
|
349
367
|
name_token = @tokens[index + 1]
|
|
350
368
|
type_param_token = @tokens[index + 2]
|
|
351
|
-
if
|
|
369
|
+
if identifier_token?(name_token) && type_param_token&.type == :lbracket
|
|
352
370
|
@known_generic_callable_names[name_token.lexeme] = true
|
|
353
371
|
end
|
|
354
372
|
end
|
|
@@ -356,7 +374,7 @@ module MilkTea
|
|
|
356
374
|
if depth.zero? && @tokens[index + 1]&.type == :function
|
|
357
375
|
name_token = @tokens[index + 2]
|
|
358
376
|
type_param_token = @tokens[index + 3]
|
|
359
|
-
if
|
|
377
|
+
if identifier_token?(name_token) && type_param_token&.type == :lbracket
|
|
360
378
|
@known_generic_callable_names[name_token.lexeme] = true
|
|
361
379
|
end
|
|
362
380
|
end
|
|
@@ -364,14 +382,14 @@ module MilkTea
|
|
|
364
382
|
if depth.zero? && @tokens[index + 1]&.type == :function
|
|
365
383
|
name_token = @tokens[index + 2]
|
|
366
384
|
type_param_token = @tokens[index + 3]
|
|
367
|
-
if
|
|
385
|
+
if identifier_token?(name_token) && type_param_token&.type == :lbracket
|
|
368
386
|
@known_generic_callable_names[name_token.lexeme] = true
|
|
369
387
|
end
|
|
370
388
|
end
|
|
371
389
|
when :struct, :union, :enum, :flags, :opaque, :type, :variant
|
|
372
390
|
if depth.zero?
|
|
373
391
|
name_token = @tokens[index + 1]
|
|
374
|
-
@known_type_names[name_token.lexeme] = true if
|
|
392
|
+
@known_type_names[name_token.lexeme] = true if identifier_token?(name_token)
|
|
375
393
|
end
|
|
376
394
|
end
|
|
377
395
|
|
|
@@ -387,11 +405,11 @@ module MilkTea
|
|
|
387
405
|
token = @tokens[cursor]
|
|
388
406
|
if token.type == :as
|
|
389
407
|
alias_token = @tokens[cursor + 1]
|
|
390
|
-
@known_import_aliases[alias_token.lexeme] = true if
|
|
408
|
+
@known_import_aliases[alias_token.lexeme] = true if identifier_token?(alias_token)
|
|
391
409
|
return cursor
|
|
392
410
|
end
|
|
393
411
|
|
|
394
|
-
last_part = token.lexeme if
|
|
412
|
+
last_part = token.lexeme if identifier_token?(token)
|
|
395
413
|
cursor += 1
|
|
396
414
|
end
|
|
397
415
|
|
|
@@ -399,7 +417,7 @@ module MilkTea
|
|
|
399
417
|
cursor
|
|
400
418
|
end
|
|
401
419
|
|
|
402
|
-
def
|
|
420
|
+
def identifier_token?(token)
|
|
403
421
|
token&.type == :identifier
|
|
404
422
|
end
|
|
405
423
|
|