mt-lang 0.3.11 → 0.3.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efa0075ce73ffd0c92161f778399c599c6443e4375194a8bfeda883b3c29ea09
4
- data.tar.gz: 978ab66cd06f4261edb72629f528c020890250ed7b57bbd75bee8cbe01e7e6a1
3
+ metadata.gz: bc80c3a3240cbcf4770dd067aa33559e74e3f139322b8fdb757316f3c7faf8af
4
+ data.tar.gz: a623e5ecaa9617aa161a83e96c4cb0e7a75b08855edae27fb56c8ddc47c7cd75
5
5
  SHA512:
6
- metadata.gz: b0516d11fd07ed4c2db9bfaa4d59735821cfc3245aca280118f87593e7fa1fb2fec3be0c8208efc87b91c4cd79215e3a593602b43e1d9811572fcdcced93c280
7
- data.tar.gz: 1a27eb0e66b9b15330ae28273b59ddfa430a6e7439811c2ca196b685cb6e8379b56016bb3a6eed60b347582fd013d8ba29f0c7024fbec0c13b67592aff3e0eba
6
+ metadata.gz: c90aa51a21411fdcfe612f2ded69afdde6e055a012a4e886f5aa9ac69110d39a8bf93a36dde0543d1375a8bfa75ffd2f287eb082833a28b42efe19ab45c62ae6
7
+ data.tar.gz: a87ac20f1228f059e3508818be58e11e5491a90299e56d5ab569ab3ebf1ae3dc1f7ddff8761321754bd2bfc8c520dc9ac3876360714ced2baf6e06a82bbf635d
data/README.md CHANGED
@@ -43,7 +43,7 @@ Blocks are indentation-based:
43
43
  - Tabs are rejected.
44
44
  - Indentation must be a multiple of 4 spaces.
45
45
  - Indentation can increase by only one level at a time.
46
- - Newlines end statements except inside `()` and `[]`, or when the previous physical line ends with a binary operator such as `+`, `and`, or `==`.
46
+ - Newlines end statements except inside `()` and `[]`, or when the previous physical line ends with a binary operator such as `+`, `and`, `==`, or `is`.
47
47
  - Comma-separated lists inside `()` and `[]` accept trailing commas. Prefer them for multiline parameters, arguments, and type lists.
48
48
 
49
49
  Long expressions should usually be wrapped with delimiters, following the same broad shape as Python's implicit line joining:
@@ -71,7 +71,15 @@ let values = 1 ..
71
71
  4
72
72
  ```
73
73
 
74
- Do not rely on starting the next physical line with the operator; wrap the expression in `()` instead if that layout reads better.
74
+ Starting a physical line with an operator is a hard parse error (`operator '<op>' cannot start a statement`). Continue by ending the previous line with the operator, or wrap the expression in `()` if that layout reads better. The continuation operator set is closed: `+` `-` `*` `/` `%`, `|` `&` `^`, `<<` `>>`, `==` `!=` `<` `<=` `>` `>=`, `and` `or` `is`, and `..`. Member-access chains that exceed one line wrap in `()` with leading dots:
75
+
76
+ ```mt
77
+ let total = (
78
+ values.iter()
79
+ .filter(pred)
80
+ .fold(0, add)
81
+ )
82
+ ```
75
83
 
76
84
  Comments:
77
85
 
@@ -315,7 +323,7 @@ Rules:
315
323
  - Compile-time reflection over validated attributes uses `has_attribute`, `attribute_of`, `attribute_arg[T]`, `field_of`, and `callable_of`.
316
324
  - `field_of(...)`, `callable_of(...)`, and `attribute_of(...)` produce compile-time handle values with source-visible handle types `field_handle`, `callable_handle`, and `attribute_handle`.
317
325
  - 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.
326
+ - 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]`), named constructor arguments (`Meta(return = 1)`), and named tuple fields (`(return = 1, let = 2)`). Primitive type names (`int`, `str`, `ref`, etc.) remain reserved and cannot be used in these positions.
319
327
 
320
328
  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 (`|`, `&`, `^`, `~`).
321
329
 
@@ -869,9 +877,9 @@ Core modules in `std/`:
869
877
 
870
878
  - `std.linear_algebra` — extends native vector/matrix/quaternion types with `dot`, `cross`, `length`, `normalized`, `lerp`, `identity`, `transpose`, `conjugate` (pure Mt, no C dependency beyond `std.math` for `sqrt`)
871
879
  - `std.graph.Graph[T]` — adjacency-list graph with `add_node`, `add_edge`, `has_edge`, `remove_edge`, `neighbors`, `bfs`, `dfs`, `toposort`; directed or undirected; `compile()` converts to CSR-based `DenseGraph[T]` for O(degree) neighbor iteration
872
- - `std.str` — extends `str` with `byte_at`, `equal`, `starts_with`, `ends_with`, `find_substring`, `is_valid_utf8`, `slice`, `to_cstr`, `hash`, `order`
880
+ - `std.str` — extends `str` with `byte_at`, `equal`, `starts_with`, `ends_with`, `find_substring`, `is_valid_utf8`, `slice`, `to_cstr`, `hash`, `order`; also provides C-string conversion helpers (`cstr_len`, `cstr_as_str`, `chars_as_str`, `nullable_cstr_as_str`)
873
881
  - `std.hash` — extends the primitive integer types (`byte`/`ubyte`/`short`/`ushort`/`int`/`uint`/`long`/`ulong`/`ptr_int`/`ptr_uint`), `bool`, `float`, `double`, and `char` with canonical `hash`/`equal`/`order` hooks; import once to use primitives as Map/Set/BinaryHeap/OrderedMap keys (`str` keys come from `std.str`). Also provides generic `hash_struct[T]`, `equal_struct[T]`, `order_struct[T]` that dispatch each field through its own canonical hook via `field.type` (content-correct, including `str` and nested-struct fields).
874
- - `std.cstring` — C string helpers (`cstr_len`, `cstr_as_str`)
882
+ - `std.cstring` — low-level byte and C-string helpers (`copy_bytes`, `move_bytes`, `set_bytes`, `compare_bytes`, `find_byte`, `length`, `compare`, `compare_prefix`, `find_char`, `find_last_char`, `find_substring`)
875
883
  - `std.math` — `sqrt`, `sin`, `cos`, `abs`, `pow`, etc. via C math
876
884
  - `std.encoding` — UTF-8 validation (`is_valid_utf8`, `utf8_codepoint_count`, `decode_utf8_codepoint`, `utf8_overlong_check`)
877
885
  - `std.string.String` — growable owned UTF-8 text
@@ -1113,6 +1121,7 @@ Current compiler rejects:
1113
1121
  - range expressions are restricted to `for`-loop iterables and range-index assignment targets
1114
1122
  - functions, methods, generic functions, and variant arms must be called — they are not usable as bare values
1115
1123
  - `read(...)` of a raw pointer requires `unsafe`
1124
+ - a statement cannot begin with a binary operator (including `+`, `-`, `and`, `or`, `is`, `..`); continuation requires ending the previous line with the operator or wrapping in `()`
1116
1125
 
1117
1126
  ### Control flow restrictions
1118
1127
 
@@ -1163,11 +1172,12 @@ mtc build <path> # Build only (emit C, compile, link, --no-cache to
1163
1172
  mtc run <path> # Build and execute (--no-cache to build and run without cache)
1164
1173
  mtc debug <file.mt> # Print debug info (tokens, AST, facts, bindings, diagnostics)
1165
1174
  mtc emit-c <path> # Emit generated C to stdout
1166
- mtc format <path> # Format sources in place (--check for dry-run)
1175
+ mtc format <path> # Format source to stdout (--write rewrites in place, --check verifies)
1167
1176
  mtc lint <path> # Run linter (--fix to apply fixes, --select/--ignore to filter)
1168
1177
  mtc test <path> # Discover and run @[test] functions (--timeout, --mem, --jobs)
1169
1178
  mtc new <name> # Scaffold a new package (package.toml + src/main.mt)
1170
1179
  mtc cache status # Show build cache stats
1180
+ mtc cache purge # Remove the entire build cache
1171
1181
  mtc lex <file.mt> # Print lexer token stream
1172
1182
  mtc parse <path> # Print parsed AST
1173
1183
  mtc lower <path> # Print lowered IR
@@ -1185,10 +1195,10 @@ mtc deps publish <path> # Publish a package to the local registry
1185
1195
  mtc deps fetch <path> # Materialize cache-backed sources
1186
1196
  ```
1187
1197
 
1188
- Run a pre-built module (no compilation):
1198
+ Resolve a module by name, build it, and run it:
1189
1199
 
1190
1200
  ```
1191
- mtc run-module <module> # Run compiled module by name (e.g. std.fmt.bench)
1201
+ mtc run-module <module> # Resolve, build, and run a module by name (e.g. std.http.server)
1192
1202
  ```
1193
1203
 
1194
1204
  Toolchain maintenance:
@@ -1199,9 +1209,19 @@ mtc toolchain doctor # Diagnose toolchain setup
1199
1209
  mtc toolchain tools # List available native tools
1200
1210
  ```
1201
1211
 
1212
+ Tooling and editors:
1213
+
1214
+ ```
1215
+ mtc bindgen <header.h> # Generate an external binding module from a C header
1216
+ mtc snapshot <path> # Render a highlighted HTML snapshot of a source file
1217
+ mtc lsp # Start the Language Server Protocol server
1218
+ mtc dap # Start the Debug Adapter Protocol server
1219
+ mtc docs [--open] [--port P] # Serve the local documentation site
1220
+ ```
1221
+
1202
1222
  Build and run commands support `--profile`, `--platform`, `--cc`, `--keep-c`, `--locked`, `--frozen`, and `-I` include paths. Dependency-locked flows support `--locked` (use package.lock) and `--frozen` (require current package.lock).
1203
1223
 
1204
- Global options work with any command (before or after the subcommand, up to a `--` separator): `-h`/`--help` (also `mtc help <command>` for command-specific help), `-V`/`--version`, `-q`/`--quiet` (suppress informational output), `-v`/`--verbose` (per-file progress), and `--color auto|always|never`. Generate shell completions with `mtc completions bash|zsh|fish`. Timing breakdowns use `--timings` (on `format`, `lint`, `build`, `run`, `test`); `lint` reports warnings with per-file progress.
1224
+ Global options work with any command (before or after the subcommand, up to a `--` separator): `-h`/`--help` (also `mtc help <command>` for command-specific help), `-V`/`--version`, `-q`/`--quiet` (suppress informational output), `-v`/`--verbose` (per-file progress), and `--color auto|always|never`. Generate shell completions with `mtc completions bash|zsh|fish`. Timing breakdowns use `--timings` (on `format` and `lint`); `lint` reports warnings with per-file progress.
1205
1225
 
1206
1226
  Diagnostic output uses standard compiler format (file:line:column with source context, error codes, and caret highlighting):
1207
1227
 
data/docs/index.html CHANGED
@@ -343,7 +343,7 @@ function main() -> int:
343
343
  <tr><td><code>mtc check &lt;path&gt;</code></td><td>Type-check + lint; reports all diagnostics sorted by line</td></tr>
344
344
  <tr><td><code>mtc run &lt;path&gt;</code></td><td>Build and execute</td></tr>
345
345
  <tr><td><code>mtc build &lt;path&gt;</code></td><td>Build only (emit C, compile, link)</td></tr>
346
- <tr><td><code>mtc format &lt;path&gt;</code></td><td>Format sources in place (<code>--check</code> for dry-run)</td></tr>
346
+ <tr><td><code>mtc format &lt;path&gt;</code></td><td>Format source to stdout (<code>--write</code> rewrites in place, <code>--check</code> verifies)</td></tr>
347
347
  <tr><td><code>mtc lint &lt;path&gt;</code></td><td>Run linter (<code>--fix</code> to apply fixes)</td></tr>
348
348
  <tr><td><code>mtc test &lt;path&gt;</code></td><td>Discover and run <code>@[test]</code> functions</td></tr>
349
349
  <tr><td><code>mtc new &lt;name&gt;</code></td><td>Scaffold a new package</td></tr>
@@ -403,6 +403,7 @@ void main_Vec2_scale(main_Vec2* this, float factor) {
403
403
  <pre><code>## ── Imports ──────────────────────────────────────────────────────────
404
404
  import std.stdio as io
405
405
  import std.hash
406
+ import std.str
406
407
  import std.vec
407
408
  import std.map
408
409
  import std.math
@@ -888,6 +889,7 @@ import mylib.utils</code></pre>
888
889
  <li>Indentation must be a multiple of <strong>4 spaces</strong></li>
889
890
  <li>Indentation increases by <strong>one level at a time</strong></li>
890
891
  <li>Newlines end statements except inside <code>()</code> and <code>[]</code>, or when the previous line ends with a binary operator</li>
892
+ <li>Starting a line with an operator is a hard parse error (<code>operator '&lt;op&gt;' cannot start a statement</code>); continuation is signaled by ending the previous line with the operator, never by starting the next one with it</li>
891
893
  </ul>
892
894
 
893
895
  <div class="code-wrap">
@@ -902,7 +904,16 @@ let total = (
902
904
  ## Also accepted: operator-led continuation.
903
905
  let total = subtotal +
904
906
  tax -
905
- discount</code></pre>
907
+ discount
908
+
909
+ ## The continuation operator set is closed:
910
+ ## + - * / % | &amp; ^ &lt;&lt; &gt;&gt; == != &lt; &lt;= &gt; &gt;= and or is ..
911
+ ## Member-access chains exceeding one line wrap in () with leading dots:
912
+ let total = (
913
+ values.iter()
914
+ .filter(pred)
915
+ .fold(0, add)
916
+ )</code></pre>
906
917
  </div>
907
918
 
908
919
  <h3>Naming Conventions</h3>
@@ -1733,14 +1744,16 @@ let sized = name[32]</code></pre>
1733
1744
  <tr><th>Precedence</th><th>Operators</th></tr>
1734
1745
  <tr><td>1 (lowest)</td><td><code>or</code></td></tr>
1735
1746
  <tr><td>2</td><td><code>and</code></td></tr>
1736
- <tr><td>3</td><td><code>|</code></td></tr>
1737
- <tr><td>4</td><td><code>^</code></td></tr>
1738
- <tr><td>5</td><td><code>&amp;</code></td></tr>
1739
- <tr><td>6</td><td><code>==</code> <code>!=</code></td></tr>
1740
- <tr><td>7</td><td><code>&lt;</code> <code>&lt;=</code> <code>&gt;</code> <code>&gt;=</code></td></tr>
1741
- <tr><td>8</td><td><code>&lt;&lt;</code> <code>&gt;&gt;</code></td></tr>
1742
- <tr><td>9</td><td><code>+</code> <code>-</code></td></tr>
1743
- <tr><td>10 (highest)</td><td><code>*</code> <code>/</code> <code>%</code></td></tr>
1747
+ <tr><td>3</td><td><code>not</code> (unary prefix)</td></tr>
1748
+ <tr><td>4</td><td><code>is</code></td></tr>
1749
+ <tr><td>5</td><td><code>|</code></td></tr>
1750
+ <tr><td>6</td><td><code>^</code></td></tr>
1751
+ <tr><td>7</td><td><code>&amp;</code></td></tr>
1752
+ <tr><td>8</td><td><code>==</code> <code>!=</code></td></tr>
1753
+ <tr><td>9</td><td><code>&lt;</code> <code>&lt;=</code> <code>&gt;</code> <code>&gt;=</code></td></tr>
1754
+ <tr><td>10</td><td><code>&lt;&lt;</code> <code>&gt;&gt;</code></td></tr>
1755
+ <tr><td>11</td><td><code>+</code> <code>-</code></td></tr>
1756
+ <tr><td>12 (highest)</td><td><code>*</code> <code>/</code> <code>%</code></td></tr>
1744
1757
  </table>
1745
1758
  </div>
1746
1759
 
@@ -2169,7 +2182,7 @@ function attach(window: ref[Window]) -> Result[void, EventError]:
2169
2182
  <tr><td><code>std.spatial</code></td><td><code>SpatialGrid[T]</code></td><td>&mdash;</td><td>Uniform spatial hash grid (returns Vec)</td></tr>
2170
2183
  <tr><td><code>std.ring_buffer</code></td><td><code>RingBuffer[T]</code></td><td>Mutable <code>ptr[T]?</code></td><td>Fixed-capacity circular buffer</td></tr>
2171
2184
  <tr><td><code>std.sparse_set</code></td><td><code>SparseSet[T]</code></td><td>Mutable <code>ptr[T]?</code></td><td>O(1) insert/remove; dense iteration</td></tr>
2172
- <tr><td><code>std.lru_cache</code></td><td><code>LruCache[K,V]</code></td><td><code>entries()</code></td><td>Capacity-bounded LRU eviction map</td></tr>
2185
+ <tr><td><code>std.lru_cache</code></td><td><code>LruCache[K,V]</code></td><td><code>iter()</code> → <code>linked_map.Entries[K, V]</code></td><td>Capacity-bounded LRU eviction map</td></tr>
2173
2186
  </table>
2174
2187
  </div>
2175
2188
 
@@ -2236,7 +2249,7 @@ function attach(window: ref[Window]) -> Result[void, EventError]:
2236
2249
  <tr><td><code>mtc lint &lt;path&gt;</code></td><td>Run linter (<code>--fix</code>, <code>--select</code>, <code>--ignore</code>)</td></tr>
2237
2250
  <tr><td><code>mtc test &lt;path&gt;</code></td><td>Discover and run <code>@[test]</code> functions</td></tr>
2238
2251
  <tr><td><code>mtc new &lt;name&gt;</code></td><td>Scaffold a new package (<code>package.toml</code> + <code>src/main.mt</code>)</td></tr>
2239
- <tr><td><code>mtc run-module &lt;module&gt;</code></td><td>Run a pre-built module by name</td></tr>
2252
+ <tr><td><code>mtc run-module &lt;module&gt;</code></td><td>Resolve a module by name, build it, and run it</td></tr>
2240
2253
  <tr><td><code>mtc completions &lt;shell&gt;</code></td><td>Print a bash/zsh/fish completion script</td></tr>
2241
2254
  </table>
2242
2255
  </div>
@@ -2263,10 +2276,22 @@ function attach(window: ref[Window]) -> Result[void, EventError]:
2263
2276
  <tr><td><code>mtc toolchain doctor</code></td><td>Diagnose toolchain setup</td></tr>
2264
2277
  <tr><td><code>mtc toolchain tools</code></td><td>List available native tools</td></tr>
2265
2278
  <tr><td><code>mtc cache status</code></td><td>Show build cache stats</td></tr>
2279
+ <tr><td><code>mtc cache purge</code></td><td>Remove the entire build cache</td></tr>
2266
2280
  <tr><td><code>mtc docs [--open] [--port PORT]</code></td><td>Start a local HTTP server serving the language reference</td></tr>
2267
2281
  </table>
2268
2282
  </div>
2269
2283
 
2284
+ <h3>Tooling</h3>
2285
+ <div class="table-wrap">
2286
+ <table class="attr-table">
2287
+ <tr><th>Command</th><th>Description</th></tr>
2288
+ <tr><td><code>mtc bindgen &lt;header.h&gt;</code></td><td>Generate an external binding module from a C header</td></tr>
2289
+ <tr><td><code>mtc snapshot &lt;path&gt;</code></td><td>Render a highlighted HTML snapshot of a source file</td></tr>
2290
+ <tr><td><code>mtc lsp</code></td><td>Start the Language Server Protocol server (editor IntelliSense)</td></tr>
2291
+ <tr><td><code>mtc dap</code></td><td>Start the Debug Adapter Protocol server (debugging)</td></tr>
2292
+ </table>
2293
+ </div>
2294
+
2270
2295
  <h3>Build Flags</h3>
2271
2296
  <p>Build and run commands support: <code>--profile</code>, <code>--platform</code>, <code>--cc</code>, <code>--keep-c</code>, <code>--locked</code>, <code>--frozen</code>, and <code>-I</code> include paths.</p>
2272
2297
 
@@ -2385,6 +2410,7 @@ import std.math # intentionally available for downstream</code></pre>
2385
2410
  <li>Enum and flags values do not implicitly coerce to backing integers</li>
2386
2411
  <li><code>+</code> does not support <code>str</code>/<code>cstr</code> concatenation</li>
2387
2412
  <li><code>==</code> and <code>!=</code> not supported on struct types; use <code>equal[T]</code></li>
2413
+ <li>A statement cannot begin with a binary operator (including <code>+</code>, <code>-</code>, <code>and</code>, <code>or</code>, <code>is</code>, <code>..</code>); continuation requires ending the previous line with the operator or wrapping in <code>()</code></li>
2388
2414
  <li>Bare function and method names are not usable as values (cannot be assigned or passed without calling). Use <code>fn(...)</code> function pointer types or <code>proc(...)</code> closures for callable values.</li>
2389
2415
  </ul>
2390
2416
 
@@ -88,6 +88,7 @@ The compile-time evaluation surface is described in [Compile-Time Evaluation](co
88
88
  - Newlines terminate statements.
89
89
  - Newlines inside `()` and `[]` do not terminate statements.
90
90
  - A physical line that ends with a binary operator also continues onto the next line.
91
+ - A physical line that begins with an operator is a hard parse error; continuation is signaled by ending the previous line with the operator, never by starting the next one with it.
91
92
  - Tabs are illegal in source files; indentation is 4 spaces.
92
93
  - Trailing commas are allowed in multiline call arguments and aggregate literals. The linter additionally flags a redundant trailing comma in a call-argument list (`trailing-list-comma` hint); aggregate and array literals keep them for diff-friendliness.
93
94
  - Comments use `#`.
@@ -83,7 +83,17 @@ let total = subtotal +
83
83
  discount
84
84
  ```
85
85
 
86
- Starting a new physical line with the operator is not part of the supported source contract; wrap in `()` instead if that layout is clearer.
86
+ The continuation operator set is closed: `+` `-` `*` `/` `%`, `|` `&` `^`, `<<` `>>`, `==` `!=` `<` `<=` `>` `>=`, `and` `or` `is`, and `..`. Assignment operators and unary `not` are excluded — wrap in `()` when a break is needed there.
87
+
88
+ Starting a new physical line with an operator is a hard error (`operator '<op>' cannot start a statement`); end the previous line with the operator, or wrap the expression in `()` if that layout is clearer. Member-access chains that exceed one line wrap in `()` with leading dots:
89
+
90
+ ```mt
91
+ let total = (
92
+ values.iter()
93
+ .filter(pred)
94
+ .fold(0, add)
95
+ )
96
+ ```
87
97
 
88
98
  ### 2.2 Comments
89
99
 
@@ -369,6 +379,7 @@ Language-level keywords and reserved words are accepted as:
369
379
  - lifetime parameter names (`struct Buf[@return]`)
370
380
  - type parameter names (`struct Box[return]`, `identity[type]`)
371
381
  - named arguments in struct/variant literals (`Meta(return = 1)`)
382
+ - named tuple fields (`(return = 1, let = 2)`)
372
383
 
373
384
  Primitive type names (`int`, `str`, `bool`, `ref`, `ptr`, `span`, `type`, etc.) remain reserved and cannot be used as names.
374
385
 
data/lib/milk_tea/base.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "pathname"
4
4
 
5
5
  module MilkTea
6
- VERSION = "0.3.11"
6
+ VERSION = "0.3.12"
7
7
 
8
8
  def self.root
9
9
  @root ||= Pathname.new(File.expand_path("../..", __dir__))
@@ -42,15 +42,7 @@ module MilkTea
42
42
  link opaque public static_assert struct type union var variant extending event
43
43
  ].freeze
44
44
 
45
- LINE_CONTINUATION_OPERATORS = %i[
46
- dot_dot
47
- plus minus star slash percent
48
- pipe amp caret
49
- or and
50
- equal_equal bang_equal
51
- less less_equal greater greater_equal
52
- shift_left shift_right
53
- ].freeze
45
+ LINE_CONTINUATION_OPERATORS = Token::LINE_CONTINUATION_OPERATORS
54
46
 
55
47
  THREE_CHAR_TOKENS = {
56
48
  "..." => :ellipsis,
@@ -358,7 +350,7 @@ module MilkTea
358
350
  newline_start = line_offset + line.length
359
351
  newline_end = has_newline ? (newline_start + 1) : newline_start
360
352
  if @grouping_depth.zero?
361
- if LINE_CONTINUATION_OPERATORS.include?(@tokens.last&.type)
353
+ if Token::LINE_CONTINUATION_OPERATORS.include?(@tokens.last&.type)
362
354
  @continuation_pending = true
363
355
  else
364
356
  @tokens << token(:newline, "\n", nil, line_number, line.length + 1, start_offset: newline_start, end_offset: newline_end)
@@ -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 && check_next(:equal)
397
+ first = if (check_name || keyword_token?(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 && check_next(:equal)
407
+ if (check_name || keyword_token?(peek)) && check_next(:equal)
408
408
  name_token = advance
409
409
  consume(:equal, "expected '=' after named tuple field")
410
410
  value = parse_expression
@@ -35,7 +35,18 @@ module MilkTea
35
35
  check(:when)
36
36
  end
37
37
 
38
+ def reject_operator_statement_start!
39
+ return unless Token::LINE_START_OPERATOR_TYPES.include?(peek.type)
40
+
41
+ operator = peek.lexeme
42
+ raise error(
43
+ peek,
44
+ "operator '#{operator}' cannot start a statement; end the previous line with it or wrap the expression in ( )"
45
+ )
46
+ end
47
+
38
48
  def parse_statement
49
+ reject_operator_statement_start!
39
50
  if match(:let)
40
51
  parse_local_decl(:let)
41
52
  elsif match(:var)
@@ -314,6 +314,12 @@ module MilkTea
314
314
  expanded_declarations.grep(AST::AttributeDecl).each do |decl|
315
315
  with_error_node(decl) do
316
316
  raise_sema_error("duplicate attribute #{decl.name}") if @ctx.attributes.key?(decl.name)
317
+ ensure_non_reserved_value_type_name!(
318
+ decl.name,
319
+ kind_label: "attribute",
320
+ line: decl.line,
321
+ column: decl.column,
322
+ )
317
323
 
318
324
  params = []
319
325
  seen = {}
@@ -463,6 +469,15 @@ module MilkTea
463
469
  {}
464
470
  end
465
471
  decl.lifetime_params.each do |lt|
472
+ raw_name = lt.delete_prefix("@")
473
+ unless raw_module?
474
+ ensure_non_reserved_value_type_name!(
475
+ raw_name,
476
+ kind_label: "lifetime parameter #{decl.name}",
477
+ line: decl.line,
478
+ column: decl.column,
479
+ )
480
+ end
466
481
  type_params[lt] = Types::LifetimeRef.new(lt)
467
482
  end if decl.respond_to?(:lifetime_params)
468
483
  type_param_constraints = struct_type.is_a?(Types::GenericStructDefinition) ? struct_type.type_param_constraints : {}
@@ -528,7 +543,7 @@ module MilkTea
528
543
  raise_sema_error("duplicate event #{decl.name}.#{event_decl.name}") if events.key?(event_decl.name)
529
544
  raise_sema_error("duplicate member #{decl.name}.#{event_decl.name}") if fields.key?(event_decl.name)
530
545
  unless raw_module?
531
- ensure_non_reserved_type_binding_name!(
546
+ ensure_non_reserved_value_type_name!(
532
547
  event_decl.name,
533
548
  kind_label: "event #{decl.name}",
534
549
  line: event_decl.line,
@@ -811,6 +826,14 @@ module MilkTea
811
826
  fields = {}
812
827
  nested.fields.each do |field|
813
828
  raise_sema_error("duplicate field #{qualified_name}.#{field.name}") if fields.key?(field.name)
829
+ unless raw_module?
830
+ ensure_non_reserved_value_type_name!(
831
+ field.name,
832
+ kind_label: "field #{qualified_name}",
833
+ line: field.line || nested.line,
834
+ column: field.column,
835
+ )
836
+ end
814
837
  begin
815
838
  field_type = resolve_type_ref(field.type, type_params:, type_param_constraints:, nested_types: nested_scope)
816
839
  validate_stored_ref_type!(field_type, "field #{qualified_name}.#{field.name}")
@@ -824,6 +847,14 @@ module MilkTea
824
847
  nested_events = {}
825
848
  nested.events.each do |event_decl|
826
849
  raise_sema_error("duplicate event #{qualified_name}.#{event_decl.name}") if nested_events.key?(event_decl.name)
850
+ unless raw_module?
851
+ ensure_non_reserved_value_type_name!(
852
+ event_decl.name,
853
+ kind_label: "event #{qualified_name}",
854
+ line: event_decl.line,
855
+ column: event_decl.column,
856
+ )
857
+ end
827
858
  begin
828
859
  nested_events[event_decl.name] = resolve_event_decl_type(event_decl, type_params:, type_param_constraints:, owner_type_name: qualified_name, nested_types: nested_scope)
829
860
  rescue SemanticError => e
@@ -11,6 +11,23 @@ module MilkTea
11
11
  amp_equal pipe_equal caret_equal shift_left_equal shift_right_equal
12
12
  ].freeze
13
13
 
14
+ # Operator token types that may never begin a statement. A statement
15
+ # that spans multiple lines must end the previous line with one of
16
+ # LINE_CONTINUATION_OPERATORS or wrap the expression in ( ) — it must
17
+ # never start the next line with an operator.
18
+ LINE_START_OPERATOR_TYPES = %i[
19
+ dot_dot plus minus star slash percent
20
+ pipe amp caret tilde
21
+ or and is
22
+ equal_equal bang_equal
23
+ less less_equal greater greater_equal
24
+ shift_left shift_right
25
+ ].freeze
26
+
27
+ # Binary operators that continue a statement when they end a physical
28
+ # line. Unary-only `~` is excluded because it has no left operand.
29
+ LINE_CONTINUATION_OPERATORS = (LINE_START_OPERATOR_TYPES - [:tilde]).freeze
30
+
14
31
  def assignment?
15
32
  ASSIGNMENT_TYPES.include?(type)
16
33
  end
@@ -111,7 +111,7 @@ module MilkTea
111
111
  line: type_param.line,
112
112
  column: type_param.column,
113
113
  kind_label:,
114
- reserved_names: RESERVED_TYPE_BINDING_NAMES,
114
+ reserved_names: RESERVED_VALUE_TYPE_NAMES,
115
115
  )
116
116
  end
117
117
  end
@@ -150,7 +150,19 @@ module MilkTea
150
150
  column: statement.column,
151
151
  var: statement.kind == :var
152
152
  )
153
- with_scope { visit_statement_list(statement.else_body) } if statement.else_body
153
+ if statement.else_body || statement.else_binding
154
+ with_scope do
155
+ if statement.else_binding
156
+ declare_local(
157
+ statement.else_binding.name,
158
+ statement.else_binding.line,
159
+ column: statement.else_binding.column,
160
+ var: false
161
+ )
162
+ end
163
+ visit_statement_list(statement.else_body) if statement.else_body
164
+ end
165
+ end
154
166
  check_redundant_type_annotation(statement)
155
167
  flag_redundant_widening_cast(statement.value) if statement.type && statement.value
156
168
  record_ptr_candidate(statement)
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.11
4
+ version: 0.3.12
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.11 installed!
606
+ Milk Tea 0.3.12 installed!
607
607
 
608
608
  System requirements:
609
609
  - A C compiler (gcc or clang) must be available on PATH