mt-lang 0.3.10 → 0.3.11
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 +2 -0
- data/docs/language-design.md +1 -2
- data/docs/language-manual.md +12 -1
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/ast.rb +6 -6
- data/lib/milk_tea/core/lowering/async/normalization.rb +5 -1
- data/lib/milk_tea/core/parser/declarations.rb +7 -7
- data/lib/milk_tea/core/parser/expressions.rb +7 -1
- data/lib/milk_tea/core/parser/statements.rb +8 -0
- data/lib/milk_tea/core/parser/types.rb +4 -4
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +2 -2
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +4 -4
- data/lib/milk_tea/lsp/server/semantic_tokens.rb +64 -0
- data/lib/milk_tea/tooling/cli.rb +10 -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: efa0075ce73ffd0c92161f778399c599c6443e4375194a8bfeda883b3c29ea09
|
|
4
|
+
data.tar.gz: 978ab66cd06f4261edb72629f528c020890250ed7b57bbd75bee8cbe01e7e6a1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0516d11fd07ed4c2db9bfaa4d59735821cfc3245aca280118f87593e7fa1fb2fec3be0c8208efc87b91c4cd79215e3a593602b43e1d9811572fcdcced93c280
|
|
7
|
+
data.tar.gz: 1a27eb0e66b9b15330ae28273b59ddfa430a6e7439811c2ca196b685cb6e8379b56016bb3a6eed60b347582fd013d8ba29f0c7024fbec0c13b67592aff3e0eba
|
data/README.md
CHANGED
|
@@ -30,6 +30,7 @@ Package manifests, build workflow, and run workflow are documented separately in
|
|
|
30
30
|
- External files are the dedicated raw ABI surface, usually for generated or low-level `std.c.*` bindings.
|
|
31
31
|
- Module lookup resolves `a.b.c` to `a/b/c.mt`.
|
|
32
32
|
- Inside a package, the file path relative to `package.source_root` defines the module name; platform-specific files such as `name.linux.mt` still map to module `name`.
|
|
33
|
+
- Circular module imports are supported via forward-declaration bindings and two-pass checking. Cycle members see each other's type declarations in the first pass and full type information in the second pass.
|
|
33
34
|
- In ordinary files, `import` statements appear only at the top.
|
|
34
35
|
- In external files, leading `import` statements are allowed after `external`.
|
|
35
36
|
- Only external files accept `include`, `link`, and `compiler_flag` directives.
|
|
@@ -314,6 +315,7 @@ Rules:
|
|
|
314
315
|
- Compile-time reflection over validated attributes uses `has_attribute`, `attribute_of`, `attribute_arg[T]`, `field_of`, and `callable_of`.
|
|
315
316
|
- `field_of(...)`, `callable_of(...)`, and `attribute_of(...)` produce compile-time handle values with source-visible handle types `field_handle`, `callable_handle`, and `attribute_handle`.
|
|
316
317
|
- The current C backend lowers `packed` / `align(...)` attributes with GNU-style `__attribute__((...))`, so these layout controls currently require a Clang/GCC-family compiler. On Windows that means Clang or GCC-family toolchains such as MinGW; `cl.exe` is not a supported backend for these attributes today. On wasm/browser targets the same feature works through Emscripten `emcc`, which is Clang-based.
|
|
318
|
+
- Keywords and reserved words are accepted as variant arm names, struct/union field names, enum/flags member names, lifetime parameters (`@return`), type parameters (`Box[return]`), and named constructor arguments (`Meta(return = 1)`). Primitive type names (`int`, `str`, `ref`, etc.) remain reserved and cannot be used in these positions.
|
|
317
319
|
|
|
318
320
|
Enum and flags values support the full set of comparison operators (`==`, `!=`, `<`, `<=`, `>`, `>=`) against values of the same enum type and against their backing integer type. Comparisons use the underlying integer backing values. Flags also support bitwise operators (`|`, `&`, `^`, `~`).
|
|
319
321
|
|
data/docs/language-design.md
CHANGED
|
@@ -490,7 +490,7 @@ Milk Tea has first-class compiler support for multithreading. The threading mode
|
|
|
490
490
|
parallel for i in 0..entity_count:
|
|
491
491
|
positions[i] += velocities[i] * dt
|
|
492
492
|
|
|
493
|
-
# Structured fork-join: each
|
|
493
|
+
# Structured fork-join: each statement runs on a separate thread
|
|
494
494
|
parallel:
|
|
495
495
|
textures = load_textures(path)
|
|
496
496
|
sounds = load_sounds(path)
|
|
@@ -501,7 +501,6 @@ Design choices:
|
|
|
501
501
|
- **Structured, not fire-and-forget.** All `parallel for` and `parallel:` blocks are synchronous barriers — the calling thread blocks until all work completes. This guarantees that captured local variables remain alive for the duration and eliminates lifetime concerns without ownership annotations.
|
|
502
502
|
- **Compile-time safety.** `ref[T]` captures are rejected because mutable aliases across thread boundaries create data races. The `parallel:` block enforces single-writer-or-multiple-readers: if one statement writes a variable, no other block may read or write it.
|
|
503
503
|
- **Value capture, pointer-based arrays.** Scalars and spans are captured by value (the span's data pointer still references the original storage). Arrays are captured as pointers to their first element, so writes in the worker affect the original array.
|
|
504
|
-
- **`do` is a keyword.** It is recognized inside `parallel:` blocks to introduce each concurrent unit of work.
|
|
505
504
|
- **Real OS threads via libuv.** Thread dispatch uses `uv_thread_create` / `uv_thread_join`, consistent with `std.thread` and `std.sync`. CPU count is detected at runtime via `uv_cpu_info`. The first chunk runs on the calling thread to avoid unnecessary dispatch when the workload is small.
|
|
506
505
|
- **No forced dependency.** The build system automatically detects `parallel for` and `parallel:` usage via a sema-level flag and links libuv only when needed.
|
|
507
506
|
|
data/docs/language-manual.md
CHANGED
|
@@ -51,6 +51,7 @@ Rules:
|
|
|
51
51
|
- Valid platform filename suffixes are `linux`, `windows`, and `wasm`.
|
|
52
52
|
- The platform suffix is not part of the module name. `import a.b.c` stays the same on every target.
|
|
53
53
|
- Milk Tea does not have a source-level conditional compilation syntax such as `#if`, `#ifdef`, or per-declaration platform attributes.
|
|
54
|
+
- Circular module imports are supported. When two modules import each other, the compiler uses forward-declaration bindings for the first pass and full type-checked bindings for the second pass, enabling cross-module type references and constructors in cycle groups.
|
|
54
55
|
|
|
55
56
|
## 2. Lexical Rules
|
|
56
57
|
|
|
@@ -360,6 +361,17 @@ Compile-time reflection over validated attributes uses `has_attribute`, `attribu
|
|
|
360
361
|
|
|
361
362
|
The current C backend lowers `packed` / `align(...)` attributes with GNU-style `__attribute__((...))`, so these layout controls currently require a Clang/GCC-family compiler. On Windows that means Clang or GCC-family toolchains such as MinGW; `cl.exe` is not a supported backend for these attributes today. On wasm/browser targets the same feature works through Emscripten `emcc`, which is Clang-based.
|
|
362
363
|
|
|
364
|
+
Language-level keywords and reserved words are accepted as:
|
|
365
|
+
- variant arm names (`return(val: int)`, `if(arg: bool)`)
|
|
366
|
+
- struct and union field names (`return: int`, `let: str`)
|
|
367
|
+
- enum and flags member names (`return = 1`, `if = 6`)
|
|
368
|
+
- variant arm payload field names (`execute(return: int)`)
|
|
369
|
+
- lifetime parameter names (`struct Buf[@return]`)
|
|
370
|
+
- type parameter names (`struct Box[return]`, `identity[type]`)
|
|
371
|
+
- named arguments in struct/variant literals (`Meta(return = 1)`)
|
|
372
|
+
|
|
373
|
+
Primitive type names (`int`, `str`, `bool`, `ref`, `ptr`, `span`, `type`, etc.) remain reserved and cannot be used as names.
|
|
374
|
+
|
|
363
375
|
### 3.4a Enum and flags operators
|
|
364
376
|
|
|
365
377
|
Enum and flags values support the full set of comparison operators (`==`, `!=`, `<`, `<=`, `>`, `>=`) against values of the same enum type and against their backing integer type. Comparisons use the underlying integer backing values.
|
|
@@ -746,7 +758,6 @@ parallel:
|
|
|
746
758
|
Rules:
|
|
747
759
|
|
|
748
760
|
- A `parallel:` block must contain at least two statements.
|
|
749
|
-
- `do` is a contextual keyword — only recognized inside `parallel:` blocks, not reserved globally.
|
|
750
761
|
- Each statement must not contain `break`, `continue`, `return`, or `defer`.
|
|
751
762
|
- The compiler enforces single-writer-or-multiple-readers: if a variable is written in one statement, no other block may access it.
|
|
752
763
|
- Captured `ref[T]` values are rejected at compile time.
|
data/lib/milk_tea/base.rb
CHANGED
data/lib/milk_tea/core/ast.rb
CHANGED
|
@@ -153,17 +153,17 @@ module MilkTea
|
|
|
153
153
|
VariantArm = Data.define(:name, :fields, :line, :column) do
|
|
154
154
|
def initialize(name:, fields:, line: nil, column: nil) = super
|
|
155
155
|
end
|
|
156
|
-
MatchArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body) do
|
|
157
|
-
def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil) = super
|
|
156
|
+
MatchArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body, :line, :column) do
|
|
157
|
+
def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil, line: nil, column: nil) = super
|
|
158
158
|
end
|
|
159
159
|
MatchStmt = Data.define(:expression, :arms, :inline, :line, :column, :length) do
|
|
160
160
|
def initialize(expression:, arms:, inline: false, line: nil, column: nil, length: nil) = super
|
|
161
161
|
end
|
|
162
|
-
MatchExprArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :value) do
|
|
163
|
-
def initialize(pattern:, binding_name:, value:, binding_line: nil, binding_column: nil) = super
|
|
162
|
+
MatchExprArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :value, :line, :column) do
|
|
163
|
+
def initialize(pattern:, binding_name:, value:, binding_line: nil, binding_column: nil, line: nil, column: nil) = super
|
|
164
164
|
end
|
|
165
|
-
WhenBranch = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body) do
|
|
166
|
-
def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil) = super
|
|
165
|
+
WhenBranch = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body, :line, :column) do
|
|
166
|
+
def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil, line: nil, column: nil) = super
|
|
167
167
|
end
|
|
168
168
|
WhenStmt = Data.define(:discriminant, :branches, :else_body, :line, :column, :length) do
|
|
169
169
|
def initialize(discriminant:, branches:, else_body:, line: nil, column: nil, length: nil) = super
|
|
@@ -93,7 +93,7 @@ module MilkTea
|
|
|
93
93
|
arms = statement.arms.map do |arm|
|
|
94
94
|
arm_env = duplicate_env(env)
|
|
95
95
|
bind_async_variant_match_arm_env!(arm_env, scrutinee_type, arm)
|
|
96
|
-
AST::MatchArm.new(pattern: arm.pattern, binding_name: arm.binding_name, body: normalize_async_statements(arm.body, counter, arm_env, return_type:))
|
|
96
|
+
AST::MatchArm.new(pattern: arm.pattern, binding_name: arm.binding_name, body: normalize_async_statements(arm.body, counter, arm_env, return_type:), line: arm.line, column: arm.column)
|
|
97
97
|
end
|
|
98
98
|
expr_setup + [AST::MatchStmt.new(expression:, arms:)]
|
|
99
99
|
when AST::WhileStmt
|
|
@@ -307,6 +307,8 @@ module MilkTea
|
|
|
307
307
|
binding_line: arm.binding_line,
|
|
308
308
|
binding_column: arm.binding_column,
|
|
309
309
|
value: normalized_value,
|
|
310
|
+
line: arm.line,
|
|
311
|
+
column: arm.column,
|
|
310
312
|
)]
|
|
311
313
|
end
|
|
312
314
|
|
|
@@ -326,6 +328,8 @@ module MilkTea
|
|
|
326
328
|
binding_line: arm.binding_line,
|
|
327
329
|
binding_column: arm.binding_column,
|
|
328
330
|
body: pattern_setup + value_setup + [AST::Assignment.new(target: AST::Identifier.new(name: temp_name), operator: "=", value: arm.value)],
|
|
331
|
+
line: arm.line,
|
|
332
|
+
column: arm.column,
|
|
329
333
|
)
|
|
330
334
|
end,
|
|
331
335
|
line: expression.line,
|
|
@@ -372,10 +372,10 @@ module MilkTea
|
|
|
372
372
|
break if check(:rbracket)
|
|
373
373
|
|
|
374
374
|
if match(:at)
|
|
375
|
-
name_token =
|
|
375
|
+
name_token = consume_name_allowing_keywords("expected lifetime name after @")
|
|
376
376
|
lifetime_params << "@#{name_token.lexeme}"
|
|
377
377
|
else
|
|
378
|
-
name_token =
|
|
378
|
+
name_token = consume_name_allowing_keywords("expected type parameter name")
|
|
379
379
|
if match(:colon)
|
|
380
380
|
value_type = parse_type_ref
|
|
381
381
|
type_params << AST::ValueTypeParam.new(
|
|
@@ -419,7 +419,7 @@ module MilkTea
|
|
|
419
419
|
|
|
420
420
|
raise error(visibility_token, "public is only allowed on struct events") if visibility == :public
|
|
421
421
|
|
|
422
|
-
field_token =
|
|
422
|
+
field_token = consume_name_allowing_keywords("expected field name")
|
|
423
423
|
field_name = field_token.lexeme
|
|
424
424
|
consume(:colon, "expected ':' after field name")
|
|
425
425
|
field_type = parse_type_ref
|
|
@@ -440,7 +440,7 @@ module MilkTea
|
|
|
440
440
|
name = name_token.lexeme
|
|
441
441
|
c_name = parse_optional_explicit_c_name
|
|
442
442
|
fields = parse_named_block do
|
|
443
|
-
|
|
443
|
+
field_name = consume_name_allowing_keywords("expected field name").lexeme
|
|
444
444
|
consume(:colon, "expected ':' after field name")
|
|
445
445
|
field_type = parse_type_ref
|
|
446
446
|
consume_end_of_statement
|
|
@@ -471,7 +471,7 @@ module MilkTea
|
|
|
471
471
|
members = []
|
|
472
472
|
skip_newlines
|
|
473
473
|
until check(:dedent) || eof?
|
|
474
|
-
member_token =
|
|
474
|
+
member_token = consume_name_allowing_keywords("expected member name")
|
|
475
475
|
member_name = member_token.lexeme
|
|
476
476
|
if match(:equal)
|
|
477
477
|
value = parse_expression
|
|
@@ -493,10 +493,10 @@ module MilkTea
|
|
|
493
493
|
name = name_token.lexeme
|
|
494
494
|
type_params = parse_declaration_type_params
|
|
495
495
|
arms = parse_named_block do
|
|
496
|
-
arm_name =
|
|
496
|
+
arm_name = consume_name_allowing_keywords("expected variant arm name").lexeme
|
|
497
497
|
fields = if match(:lparen)
|
|
498
498
|
parsed = parse_comma_separated_until(:rparen) do
|
|
499
|
-
|
|
499
|
+
field_name = consume_name_allowing_keywords("expected field name").lexeme
|
|
500
500
|
consume(:colon, "expected ':' after field name")
|
|
501
501
|
field_type = parse_type_ref
|
|
502
502
|
AST::Field.new(name: field_name, type: field_type)
|
|
@@ -105,6 +105,8 @@ module MilkTea
|
|
|
105
105
|
binding_line: binding_token&.line,
|
|
106
106
|
binding_column: binding_token&.column,
|
|
107
107
|
value:,
|
|
108
|
+
line: pattern.line,
|
|
109
|
+
column: pattern.column,
|
|
108
110
|
)
|
|
109
111
|
end
|
|
110
112
|
end
|
|
@@ -153,6 +155,8 @@ module MilkTea
|
|
|
153
155
|
binding_line: nil,
|
|
154
156
|
binding_column: nil,
|
|
155
157
|
value: AST::BooleanLiteral.new(value: true),
|
|
158
|
+
line: arm_pattern.line,
|
|
159
|
+
column: arm_pattern.column,
|
|
156
160
|
),
|
|
157
161
|
AST::MatchExprArm.new(
|
|
158
162
|
pattern: AST::Identifier.new(name: "_", line:, column:),
|
|
@@ -160,6 +164,8 @@ module MilkTea
|
|
|
160
164
|
binding_line: nil,
|
|
161
165
|
binding_column: nil,
|
|
162
166
|
value: AST::BooleanLiteral.new(value: false),
|
|
167
|
+
line:,
|
|
168
|
+
column:,
|
|
163
169
|
),
|
|
164
170
|
],
|
|
165
171
|
line:,
|
|
@@ -338,7 +344,7 @@ module MilkTea
|
|
|
338
344
|
end
|
|
339
345
|
|
|
340
346
|
def parse_call_argument
|
|
341
|
-
if check_name && check_next(:equal)
|
|
347
|
+
if (check_name || keyword_token?(peek)) && check_next(:equal)
|
|
342
348
|
name = advance.lexeme
|
|
343
349
|
consume(:equal, "expected '=' after named argument name")
|
|
344
350
|
AST::Argument.new(name:, value: parse_expression)
|
|
@@ -351,6 +351,8 @@ module MilkTea
|
|
|
351
351
|
binding_line: binding_token&.line,
|
|
352
352
|
binding_column: binding_token&.column,
|
|
353
353
|
value:,
|
|
354
|
+
line: pattern.line,
|
|
355
|
+
column: pattern.column,
|
|
354
356
|
)
|
|
355
357
|
end
|
|
356
358
|
else
|
|
@@ -362,6 +364,8 @@ module MilkTea
|
|
|
362
364
|
binding_line: binding_token&.line,
|
|
363
365
|
binding_column: binding_token&.column,
|
|
364
366
|
body:,
|
|
367
|
+
line: pattern.line,
|
|
368
|
+
column: pattern.column,
|
|
365
369
|
)
|
|
366
370
|
end
|
|
367
371
|
end
|
|
@@ -376,6 +380,8 @@ module MilkTea
|
|
|
376
380
|
binding_line: binding_token&.line,
|
|
377
381
|
binding_column: binding_token&.column,
|
|
378
382
|
body: recovered_body,
|
|
383
|
+
line: patterns.first&.line,
|
|
384
|
+
column: patterns.first&.column,
|
|
379
385
|
)] if recovered_body
|
|
380
386
|
|
|
381
387
|
raise
|
|
@@ -615,6 +621,8 @@ module MilkTea
|
|
|
615
621
|
binding_line: binding_token.line,
|
|
616
622
|
binding_column: binding_token.column,
|
|
617
623
|
body:,
|
|
624
|
+
line: pattern.line,
|
|
625
|
+
column: pattern.column,
|
|
618
626
|
)
|
|
619
627
|
skip_newlines
|
|
620
628
|
end
|
|
@@ -92,7 +92,7 @@ module MilkTea
|
|
|
92
92
|
|
|
93
93
|
first_token = peek
|
|
94
94
|
if match(:at)
|
|
95
|
-
lt_token =
|
|
95
|
+
lt_token = consume_name_allowing_keywords("expected lifetime name after @")
|
|
96
96
|
return AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["@#{lt_token.lexeme}"]), arguments: [], nullable: false, lifetime: nil, line: first_token.line, column: first_token.column, length: lt_token.lexeme.length + 1)
|
|
97
97
|
end
|
|
98
98
|
name = parse_qualified_name
|
|
@@ -101,7 +101,7 @@ module MilkTea
|
|
|
101
101
|
if match(:lbracket)
|
|
102
102
|
if check(:at) && name.to_s == "ref"
|
|
103
103
|
match(:at)
|
|
104
|
-
lt_token =
|
|
104
|
+
lt_token = consume_name_allowing_keywords("expected lifetime name after @")
|
|
105
105
|
lifetime = "@#{lt_token.lexeme}"
|
|
106
106
|
consume(:comma, "expected ',' after lifetime in type arguments")
|
|
107
107
|
end
|
|
@@ -167,7 +167,7 @@ module MilkTea
|
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def parse_function_type_param
|
|
170
|
-
name_token =
|
|
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")
|
|
173
173
|
type = parse_type_ref
|
|
@@ -190,7 +190,7 @@ module MilkTea
|
|
|
190
190
|
return [] unless match(:lbracket)
|
|
191
191
|
|
|
192
192
|
params = parse_comma_separated_until(:rbracket) do
|
|
193
|
-
name_token =
|
|
193
|
+
name_token = consume_name_allowing_keywords("expected type parameter name")
|
|
194
194
|
name = name_token.lexeme
|
|
195
195
|
if match(:colon)
|
|
196
196
|
value_type = parse_type_ref
|
|
@@ -208,7 +208,7 @@ module MilkTea
|
|
|
208
208
|
def resolve_type_param_constraints(type_params)
|
|
209
209
|
type_params.each_with_object({}) do |type_param, constraints|
|
|
210
210
|
if type_param.is_a?(AST::ValueTypeParam)
|
|
211
|
-
|
|
211
|
+
ensure_non_reserved_value_type_name!(
|
|
212
212
|
type_param.name,
|
|
213
213
|
kind_label: "type parameter",
|
|
214
214
|
line: type_param.line,
|
|
@@ -218,7 +218,7 @@ module MilkTea
|
|
|
218
218
|
next
|
|
219
219
|
end
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
ensure_non_reserved_value_type_name!(
|
|
222
222
|
type_param.name,
|
|
223
223
|
kind_label: "type parameter",
|
|
224
224
|
line: type_param.line,
|
|
@@ -482,7 +482,7 @@ module MilkTea
|
|
|
482
482
|
raise_sema_error("duplicate field #{decl.name}.#{field.name}") if fields.key?(field.name)
|
|
483
483
|
raise_sema_error("duplicate member #{decl.name}.#{field.name}") if events.key?(field.name)
|
|
484
484
|
unless raw_module?
|
|
485
|
-
|
|
485
|
+
ensure_non_reserved_value_type_name!(
|
|
486
486
|
field.name,
|
|
487
487
|
kind_label: "field #{decl.name}",
|
|
488
488
|
line: field.line || decl.line,
|
|
@@ -576,7 +576,7 @@ module MilkTea
|
|
|
576
576
|
decl.members.each do |member|
|
|
577
577
|
raise_sema_error("duplicate member #{decl.name}.#{member.name}") if member_names.include?(member.name)
|
|
578
578
|
unless raw_module?
|
|
579
|
-
|
|
579
|
+
ensure_non_reserved_value_type_name!(
|
|
580
580
|
member.name,
|
|
581
581
|
kind_label: "member #{decl.name}",
|
|
582
582
|
line: member.line || decl.line,
|
|
@@ -645,7 +645,7 @@ module MilkTea
|
|
|
645
645
|
begin
|
|
646
646
|
raise_sema_error("duplicate arm #{decl.name}.#{arm.name}") if seen_arms.include?(arm.name)
|
|
647
647
|
unless raw_module?
|
|
648
|
-
|
|
648
|
+
ensure_non_reserved_value_type_name!(
|
|
649
649
|
arm.name,
|
|
650
650
|
kind_label: "arm #{decl.name}",
|
|
651
651
|
line: arm.line || decl.line,
|
|
@@ -661,7 +661,7 @@ module MilkTea
|
|
|
661
661
|
begin
|
|
662
662
|
raise_sema_error("duplicate field #{arm.name}.#{field.name}") if seen_fields.include?(field.name)
|
|
663
663
|
unless raw_module?
|
|
664
|
-
|
|
664
|
+
ensure_non_reserved_value_type_name!(
|
|
665
665
|
field.name,
|
|
666
666
|
kind_label: "field #{decl.name}.#{arm.name}",
|
|
667
667
|
line: field.line || decl.line,
|
|
@@ -275,6 +275,12 @@ module MilkTea
|
|
|
275
275
|
end
|
|
276
276
|
|
|
277
277
|
if KEYWORD_TOKEN_TYPES.include?(tok.type)
|
|
278
|
+
return [:typeParameter, []] if keyword_lifetime_or_type_param?(tokens, index)
|
|
279
|
+
return [:type, []] if keyword_type_annotation?(tokens, index)
|
|
280
|
+
return [:enumMember, [:declaration]] if variant_enum_member_declaration?(tokens, index)
|
|
281
|
+
return [:property, [:declaration]] if keyword_field_declaration_token?(tokens, index)
|
|
282
|
+
return [:property, []] if keyword_member_access?(tokens, index)
|
|
283
|
+
return [:parameter, []] if keyword_named_argument_token?(tokens, index)
|
|
278
284
|
return [:keyword, []]
|
|
279
285
|
end
|
|
280
286
|
|
|
@@ -550,6 +556,64 @@ module MilkTea
|
|
|
550
556
|
next_tok&.type == :colon
|
|
551
557
|
end
|
|
552
558
|
|
|
559
|
+
def keyword_field_declaration_token?(tokens, index)
|
|
560
|
+
return false if match_arm_binding_token?(tokens, index)
|
|
561
|
+
return false if destructure_let_binding?(tokens, index)
|
|
562
|
+
|
|
563
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
564
|
+
next_tok&.type == :colon
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def keyword_member_access?(tokens, index)
|
|
568
|
+
prev_index = previous_non_trivia_token_index(tokens, index)
|
|
569
|
+
return false unless prev_index
|
|
570
|
+
|
|
571
|
+
tokens[prev_index].type == :dot
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def keyword_lifetime_or_type_param?(tokens, index)
|
|
575
|
+
prev_index = previous_non_trivia_token_index(tokens, index)
|
|
576
|
+
return false unless prev_index
|
|
577
|
+
|
|
578
|
+
prev_type = tokens[prev_index].type
|
|
579
|
+
return true if prev_type == :at
|
|
580
|
+
return true if prev_type == :lbracket
|
|
581
|
+
return true if prev_type == :comma && inside_type_params?(tokens, prev_index)
|
|
582
|
+
false
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
def inside_type_params?(tokens, comma_index)
|
|
586
|
+
i = comma_index - 1
|
|
587
|
+
while i >= 0
|
|
588
|
+
t = tokens[i]
|
|
589
|
+
break if t.type == :lbracket
|
|
590
|
+
return false if t.type == :newline || t.type == :rbracket || t.type == :lparen
|
|
591
|
+
i -= 1
|
|
592
|
+
end
|
|
593
|
+
return false if i < 0
|
|
594
|
+
|
|
595
|
+
prev = previous_non_trivia_token_index(tokens, i)
|
|
596
|
+
return true if prev && %i[struct variant enum flags function fn proc].include?(tokens[prev].type)
|
|
597
|
+
return true if prev && tokens[prev].type == :rbracket
|
|
598
|
+
return true if prev && tokens[prev].type == :identifier
|
|
599
|
+
|
|
600
|
+
false
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def keyword_named_argument_token?(tokens, index)
|
|
604
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
605
|
+
next_tok&.type == :equal
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def keyword_type_annotation?(tokens, index)
|
|
609
|
+
tok = tokens[index]
|
|
610
|
+
prev_index = previous_non_trivia_token_index(tokens, index)
|
|
611
|
+
return false unless prev_index
|
|
612
|
+
return false unless %i[colon arrow].include?(tokens[prev_index].type)
|
|
613
|
+
|
|
614
|
+
tokens[prev_index].line == tok.line
|
|
615
|
+
end
|
|
616
|
+
|
|
553
617
|
def destructure_let_binding?(tokens, index)
|
|
554
618
|
tok = tokens[index]
|
|
555
619
|
return false unless tok&.type == :identifier
|
data/lib/milk_tea/tooling/cli.rb
CHANGED
|
@@ -1611,6 +1611,7 @@ module MilkTea
|
|
|
1611
1611
|
input_path = nil
|
|
1612
1612
|
theme_path = nil
|
|
1613
1613
|
output_path = nil
|
|
1614
|
+
textmate_only = false
|
|
1614
1615
|
|
|
1615
1616
|
until @argv.empty?
|
|
1616
1617
|
arg = @argv.first
|
|
@@ -1629,6 +1630,9 @@ module MilkTea
|
|
|
1629
1630
|
@err.puts("snapshot: missing value for --output")
|
|
1630
1631
|
return 1
|
|
1631
1632
|
end
|
|
1633
|
+
when "--textmate-only"
|
|
1634
|
+
@argv.shift
|
|
1635
|
+
textmate_only = true
|
|
1632
1636
|
else
|
|
1633
1637
|
if arg.start_with?("-")
|
|
1634
1638
|
@err.puts("snapshot: unknown option #{arg}")
|
|
@@ -1674,10 +1678,12 @@ module MilkTea
|
|
|
1674
1678
|
args.push("-o", output_path) if output_path
|
|
1675
1679
|
|
|
1676
1680
|
semantic_result = nil
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
+
unless textmate_only
|
|
1682
|
+
begin
|
|
1683
|
+
semantic_result = MilkTea::LSP::Server.semantic_tokens_for_path(input_path)
|
|
1684
|
+
rescue => e
|
|
1685
|
+
@err.puts("snapshot: semantic analysis skipped: #{e.message}")
|
|
1686
|
+
end
|
|
1681
1687
|
end
|
|
1682
1688
|
|
|
1683
1689
|
if semantic_result && semantic_result[:entries] && !semantic_result[:entries].empty?
|
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.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -603,7 +603,7 @@ metadata:
|
|
|
603
603
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
604
604
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
605
605
|
post_install_message: |
|
|
606
|
-
Milk Tea 0.3.
|
|
606
|
+
Milk Tea 0.3.11 installed!
|
|
607
607
|
|
|
608
608
|
System requirements:
|
|
609
609
|
- A C compiler (gcc or clang) must be available on PATH
|