mt-lang 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/AUTHORS +3 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +82 -0
- data/LICENSE +21 -0
- data/README.md +1208 -0
- data/Rakefile +332 -0
- data/bin/mtc +8 -0
- data/bin/profile-mtc-checks +133 -0
- data/bin/tracy-profiler +0 -0
- data/docs/build-guide.md +536 -0
- data/docs/index.html +2778 -0
- data/docs/language-design.md +1519 -0
- data/docs/language-manual.md +1534 -0
- data/lib/milk_tea/base.rb +49 -0
- data/lib/milk_tea/bindings/bindgen/ast_parser.rb +398 -0
- data/lib/milk_tea/bindings/bindgen/declaration.rb +319 -0
- data/lib/milk_tea/bindings/bindgen/emitter.rb +387 -0
- data/lib/milk_tea/bindings/bindgen/overrides.rb +134 -0
- data/lib/milk_tea/bindings/bindgen/type_mapper.rb +622 -0
- data/lib/milk_tea/bindings/bindgen.rb +207 -0
- data/lib/milk_tea/bindings/cli.rb +121 -0
- data/lib/milk_tea/bindings/imported_bindings/defaults.rb +210 -0
- data/lib/milk_tea/bindings/imported_bindings/generator.rb +1114 -0
- data/lib/milk_tea/bindings/imported_bindings/method_source.rb +190 -0
- data/lib/milk_tea/bindings/imported_bindings/naming.rb +286 -0
- data/lib/milk_tea/bindings/imported_bindings.rb +215 -0
- data/lib/milk_tea/bindings/opengl_registry.rb +547 -0
- data/lib/milk_tea/bindings/raw_bindings/defaults.rb +1338 -0
- data/lib/milk_tea/bindings/raw_bindings.rb +269 -0
- data/lib/milk_tea/bindings/steamworks.rb +629 -0
- data/lib/milk_tea/bindings/upstream_sources.rb +352 -0
- data/lib/milk_tea/bindings/vendored_box2d.rb +79 -0
- data/lib/milk_tea/bindings/vendored_c_library.rb +322 -0
- data/lib/milk_tea/bindings/vendored_cjson.rb +52 -0
- data/lib/milk_tea/bindings/vendored_flecs.rb +78 -0
- data/lib/milk_tea/bindings/vendored_glfw.rb +77 -0
- data/lib/milk_tea/bindings/vendored_libuv.rb +75 -0
- data/lib/milk_tea/bindings/vendored_pcre2.rb +84 -0
- data/lib/milk_tea/bindings/vendored_raylib.rb +131 -0
- data/lib/milk_tea/bindings/vendored_sdl3.rb +78 -0
- data/lib/milk_tea/bindings/vendored_steamworks.rb +71 -0
- data/lib/milk_tea/bindings/vendored_tool.rb +71 -0
- data/lib/milk_tea/bindings/vendored_tools.rb +23 -0
- data/lib/milk_tea/bindings/vendored_tracy.rb +37 -0
- data/lib/milk_tea/bindings.rb +23 -0
- data/lib/milk_tea/core/ast.rb +311 -0
- data/lib/milk_tea/core/async_runtime_installer.rb +28 -0
- data/lib/milk_tea/core/binding_types.rb +18 -0
- data/lib/milk_tea/core/bindings/attribute_binding.rb +58 -0
- data/lib/milk_tea/core/bindings/function_binding.rb +5 -0
- data/lib/milk_tea/core/bindings/module_binding.rb +58 -0
- data/lib/milk_tea/core/bindings/value_binding.rb +21 -0
- data/lib/milk_tea/core/c_backend/aggregate_utils.rb +103 -0
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +412 -0
- data/lib/milk_tea/core/c_backend/expressions.rb +468 -0
- data/lib/milk_tea/core/c_backend/feature_detection.rb +483 -0
- data/lib/milk_tea/core/c_backend/reachability.rb +398 -0
- data/lib/milk_tea/core/c_backend/reinterpret.rb +226 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1080 -0
- data/lib/milk_tea/core/c_backend/statements.rb +563 -0
- data/lib/milk_tea/core/c_backend/type_collectors.rb +1545 -0
- data/lib/milk_tea/core/c_backend/type_declaration.rb +223 -0
- data/lib/milk_tea/core/c_backend/type_system.rb +345 -0
- data/lib/milk_tea/core/c_backend.rb +287 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +79 -0
- data/lib/milk_tea/core/compile_time/const_eval.rb +187 -0
- data/lib/milk_tea/core/compile_time.rb +329 -0
- data/lib/milk_tea/core/control_flow/builder.rb +582 -0
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +143 -0
- data/lib/milk_tea/core/control_flow/dataflow.rb +74 -0
- data/lib/milk_tea/core/control_flow/definite_assignment.rb +79 -0
- data/lib/milk_tea/core/control_flow/graph.rb +90 -0
- data/lib/milk_tea/core/control_flow/liveness.rb +24 -0
- data/lib/milk_tea/core/control_flow/nullability_flow.rb +43 -0
- data/lib/milk_tea/core/control_flow/reachability.rb +22 -0
- data/lib/milk_tea/core/control_flow/termination.rb +31 -0
- data/lib/milk_tea/core/control_flow.rb +34 -0
- data/lib/milk_tea/core/cst.rb +48 -0
- data/lib/milk_tea/core/cst_builder.rb +19 -0
- data/lib/milk_tea/core/ir.rb +85 -0
- data/lib/milk_tea/core/keywords.rb +97 -0
- data/lib/milk_tea/core/lexer/character_classes.rb +60 -0
- data/lib/milk_tea/core/lexer/format_strings.rb +225 -0
- data/lib/milk_tea/core/lexer/heredocs.rb +199 -0
- data/lib/milk_tea/core/lexer/indentation.rb +62 -0
- data/lib/milk_tea/core/lexer/numbers.rb +96 -0
- data/lib/milk_tea/core/lexer/recovery.rb +32 -0
- data/lib/milk_tea/core/lexer/strings.rb +167 -0
- data/lib/milk_tea/core/lexer/symbols.rb +71 -0
- data/lib/milk_tea/core/lexer/trivia.rb +53 -0
- data/lib/milk_tea/core/lexer.rb +430 -0
- data/lib/milk_tea/core/lowering/artifacts.rb +26 -0
- data/lib/milk_tea/core/lowering/async/analysis.rb +245 -0
- data/lib/milk_tea/core/lowering/async/lowering.rb +1399 -0
- data/lib/milk_tea/core/lowering/async/normalization.rb +459 -0
- data/lib/milk_tea/core/lowering/async.rb +714 -0
- data/lib/milk_tea/core/lowering/block.rb +1052 -0
- data/lib/milk_tea/core/lowering/calls.rb +1565 -0
- data/lib/milk_tea/core/lowering/declarations.rb +214 -0
- data/lib/milk_tea/core/lowering/dyn.rb +206 -0
- data/lib/milk_tea/core/lowering/events.rb +1054 -0
- data/lib/milk_tea/core/lowering/expressions.rb +1645 -0
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +206 -0
- data/lib/milk_tea/core/lowering/functions.rb +242 -0
- data/lib/milk_tea/core/lowering/loops.rb +1087 -0
- data/lib/milk_tea/core/lowering/lowering_context.rb +80 -0
- data/lib/milk_tea/core/lowering/proc.rb +419 -0
- data/lib/milk_tea/core/lowering/resolve.rb +2516 -0
- data/lib/milk_tea/core/lowering/scans.rb +220 -0
- data/lib/milk_tea/core/lowering/str_buffer.rb +125 -0
- data/lib/milk_tea/core/lowering/utils.rb +1453 -0
- data/lib/milk_tea/core/lowering.rb +378 -0
- data/lib/milk_tea/core/module_binder.rb +181 -0
- data/lib/milk_tea/core/module_loader/errors.rb +21 -0
- data/lib/milk_tea/core/module_loader.rb +479 -0
- data/lib/milk_tea/core/module_path_resolver.rb +153 -0
- data/lib/milk_tea/core/module_roots.rb +88 -0
- data/lib/milk_tea/core/parser/attributes.rb +71 -0
- data/lib/milk_tea/core/parser/blocks.rb +119 -0
- data/lib/milk_tea/core/parser/declarations.rb +749 -0
- data/lib/milk_tea/core/parser/expressions.rb +624 -0
- data/lib/milk_tea/core/parser/recovery.rb +131 -0
- data/lib/milk_tea/core/parser/statements.rb +756 -0
- data/lib/milk_tea/core/parser/types.rb +271 -0
- data/lib/milk_tea/core/parser.rb +400 -0
- data/lib/milk_tea/core/prelude_installer.rb +29 -0
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +917 -0
- data/lib/milk_tea/core/pretty_printer/base_formatter.rb +87 -0
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +300 -0
- data/lib/milk_tea/core/pretty_printer.rb +17 -0
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +314 -0
- data/lib/milk_tea/core/semantic_analyzer/attributes.rb +184 -0
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +992 -0
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1735 -0
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +355 -0
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +155 -0
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +354 -0
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +383 -0
- data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +78 -0
- data/lib/milk_tea/core/semantic_analyzer/module_context.rb +35 -0
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +1438 -0
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +421 -0
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +1308 -0
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +588 -0
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +307 -0
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +851 -0
- data/lib/milk_tea/core/semantic_analyzer.rb +327 -0
- data/lib/milk_tea/core/token.rb +26 -0
- data/lib/milk_tea/core/token_stream.rb +30 -0
- data/lib/milk_tea/core/types/layout.rb +243 -0
- data/lib/milk_tea/core/types/predicates.rb +609 -0
- data/lib/milk_tea/core/types/registry.rb +83 -0
- data/lib/milk_tea/core/types/types.rb +1696 -0
- data/lib/milk_tea/core/types/visitor.rb +442 -0
- data/lib/milk_tea/core.rb +25 -0
- data/lib/milk_tea/dap/backends/lldb_dap.rb +158 -0
- data/lib/milk_tea/dap/protocol.rb +58 -0
- data/lib/milk_tea/dap/server/breakpoints.rb +66 -0
- data/lib/milk_tea/dap/server/debug_map.rb +291 -0
- data/lib/milk_tea/dap/server/handlers.rb +374 -0
- data/lib/milk_tea/dap/server/launch.rb +261 -0
- data/lib/milk_tea/dap/server/lldb_backend.rb +380 -0
- data/lib/milk_tea/dap/server/pause_diagnostics.rb +109 -0
- data/lib/milk_tea/dap/server/utilities.rb +160 -0
- data/lib/milk_tea/dap/server/wire.rb +55 -0
- data/lib/milk_tea/dap/server.rb +131 -0
- data/lib/milk_tea/dap/session.rb +152 -0
- data/lib/milk_tea/dap.rb +6 -0
- data/lib/milk_tea/lsp/dependency_resolution.rb +52 -0
- data/lib/milk_tea/lsp/diagnostics.rb +611 -0
- data/lib/milk_tea/lsp/protocol.rb +104 -0
- data/lib/milk_tea/lsp/server/call_hierarchy.rb +274 -0
- data/lib/milk_tea/lsp/server/code_actions.rb +446 -0
- data/lib/milk_tea/lsp/server/code_lens.rb +97 -0
- data/lib/milk_tea/lsp/server/completion.rb +1099 -0
- data/lib/milk_tea/lsp/server/configuration.rb +167 -0
- data/lib/milk_tea/lsp/server/debug_info.rb +45 -0
- data/lib/milk_tea/lsp/server/definition.rb +779 -0
- data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +239 -0
- data/lib/milk_tea/lsp/server/execute_command.rb +25 -0
- data/lib/milk_tea/lsp/server/folding_range.rb +153 -0
- data/lib/milk_tea/lsp/server/formatting.rb +575 -0
- data/lib/milk_tea/lsp/server/hover.rb +1465 -0
- data/lib/milk_tea/lsp/server/inlay_hints.rb +204 -0
- data/lib/milk_tea/lsp/server/lifecycle.rb +234 -0
- data/lib/milk_tea/lsp/server/linked_editing_range.rb +43 -0
- data/lib/milk_tea/lsp/server/on_type_formatting.rb +73 -0
- data/lib/milk_tea/lsp/server/progress.rb +47 -0
- data/lib/milk_tea/lsp/server/references.rb +433 -0
- data/lib/milk_tea/lsp/server/rename.rb +598 -0
- data/lib/milk_tea/lsp/server/selection_range.rb +130 -0
- data/lib/milk_tea/lsp/server/semantic_tokens.rb +1745 -0
- data/lib/milk_tea/lsp/server/signature_help.rb +200 -0
- data/lib/milk_tea/lsp/server/text_documents.rb +125 -0
- data/lib/milk_tea/lsp/server/type_hierarchy.rb +167 -0
- data/lib/milk_tea/lsp/server/utilities.rb +520 -0
- data/lib/milk_tea/lsp/server.rb +415 -0
- data/lib/milk_tea/lsp/workspace/analysis.rb +209 -0
- data/lib/milk_tea/lsp/workspace/caches.rb +260 -0
- data/lib/milk_tea/lsp/workspace/collection.rb +98 -0
- data/lib/milk_tea/lsp/workspace/definition_index.rb +184 -0
- data/lib/milk_tea/lsp/workspace/dependency_graph.rb +282 -0
- data/lib/milk_tea/lsp/workspace/store.rb +154 -0
- data/lib/milk_tea/lsp/workspace/utilities.rb +490 -0
- data/lib/milk_tea/lsp/workspace.rb +127 -0
- data/lib/milk_tea/lsp.rb +13 -0
- data/lib/milk_tea/packages/atomic_write.rb +63 -0
- data/lib/milk_tea/packages/dependency_solver.rb +194 -0
- data/lib/milk_tea/packages/graph.rb +139 -0
- data/lib/milk_tea/packages/lock.rb +421 -0
- data/lib/milk_tea/packages/manager_cli.rb +485 -0
- data/lib/milk_tea/packages/manifest.rb +356 -0
- data/lib/milk_tea/packages/manifest_editor.rb +134 -0
- data/lib/milk_tea/packages/registry_metadata_provider.rb +34 -0
- data/lib/milk_tea/packages/registry_store.rb +420 -0
- data/lib/milk_tea/packages/services.rb +41 -0
- data/lib/milk_tea/packages/source_cache.rb +71 -0
- data/lib/milk_tea/packages/source_fetcher.rb +124 -0
- data/lib/milk_tea/packages/source_resolver.rb +389 -0
- data/lib/milk_tea/packages/version.rb +164 -0
- data/lib/milk_tea/packages.rb +16 -0
- data/lib/milk_tea/tooling/asset_pack.rb +141 -0
- data/lib/milk_tea/tooling/build.rb +1124 -0
- data/lib/milk_tea/tooling/build_cache.rb +240 -0
- data/lib/milk_tea/tooling/cli.rb +2688 -0
- data/lib/milk_tea/tooling/cst_formatter.rb +13 -0
- data/lib/milk_tea/tooling/debug_info_formatter.rb +456 -0
- data/lib/milk_tea/tooling/debug_map.rb +248 -0
- data/lib/milk_tea/tooling/docs_app.rb +369 -0
- data/lib/milk_tea/tooling/error_formatter.rb +86 -0
- data/lib/milk_tea/tooling/formatter.rb +787 -0
- data/lib/milk_tea/tooling/linter/doc_tags.rb +212 -0
- data/lib/milk_tea/tooling/linter/fix_engine.rb +237 -0
- data/lib/milk_tea/tooling/linter/flow_rules.rb +380 -0
- data/lib/milk_tea/tooling/linter/imports_platform.rb +841 -0
- data/lib/milk_tea/tooling/linter/release_rules.rb +744 -0
- data/lib/milk_tea/tooling/linter/reserved_names.rb +199 -0
- data/lib/milk_tea/tooling/linter/rules.rb +593 -0
- data/lib/milk_tea/tooling/linter/source_helpers.rb +407 -0
- data/lib/milk_tea/tooling/linter/trailing_comma.rb +139 -0
- data/lib/milk_tea/tooling/linter/visitors.rb +1286 -0
- data/lib/milk_tea/tooling/linter.rb +798 -0
- data/lib/milk_tea/tooling/project_scaffold.rb +82 -0
- data/lib/milk_tea/tooling/public/css/docs.css +166 -0
- data/lib/milk_tea/tooling/public/js/docs.js +94 -0
- data/lib/milk_tea/tooling/run.rb +408 -0
- data/lib/milk_tea/tooling/templates/wasm_shell.html +48 -0
- data/lib/milk_tea/tooling/toolchain_cli.rb +157 -0
- data/lib/milk_tea/tooling/views/404.erb +7 -0
- data/lib/milk_tea/tooling/views/index.erb +87 -0
- data/lib/milk_tea/tooling/views/layout.erb +69 -0
- data/lib/milk_tea/tooling/views/module.erb +97 -0
- data/lib/milk_tea/tooling/views/stdlib.erb +21 -0
- data/lib/milk_tea/tooling.rb +20 -0
- data/lib/milk_tea.rb +8 -0
- metadata +426 -0
data/README.md
ADDED
|
@@ -0,0 +1,1208 @@
|
|
|
1
|
+
# Milk Tea
|
|
2
|
+
|
|
3
|
+
This README is the primary, implementation-focused language reference for the project.
|
|
4
|
+
It is the preferred first entry point for getting to know the language.
|
|
5
|
+
|
|
6
|
+
If this file conflicts with `docs/language-manual.md`, the manual wins.
|
|
7
|
+
`docs/language-design.md` is for design direction and rationale, not the authoritative implementation spec.
|
|
8
|
+
|
|
9
|
+
Package manifests, build workflow, and run workflow are documented separately in `docs/build-guide.md`.
|
|
10
|
+
|
|
11
|
+
## 1. File Kinds And Layout
|
|
12
|
+
|
|
13
|
+
- Source files use the `.mt` extension.
|
|
14
|
+
- Ordinary files are the normal source form. They have no module header; module identity is inferred from the file path.
|
|
15
|
+
- Raw ABI binding files use a leading `external` header.
|
|
16
|
+
- External files are the dedicated raw ABI surface, usually for generated or low-level `std.c.*` bindings.
|
|
17
|
+
- Module lookup resolves `a.b.c` to `a/b/c.mt`.
|
|
18
|
+
- 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`.
|
|
19
|
+
- In ordinary files, `import` statements appear only at the top.
|
|
20
|
+
- In external files, leading `import` statements are allowed after `external`.
|
|
21
|
+
- Only external files accept `include`, `link`, and `compiler_flag` directives.
|
|
22
|
+
- After those imports and directives, external files stay narrow: they contain raw ABI declarations, not ordinary module logic.
|
|
23
|
+
|
|
24
|
+
Blocks are indentation-based:
|
|
25
|
+
|
|
26
|
+
- `:` starts a block.
|
|
27
|
+
- Indentation must be spaces only.
|
|
28
|
+
- Tabs are rejected.
|
|
29
|
+
- Indentation must be a multiple of 4 spaces.
|
|
30
|
+
- Indentation can increase by only one level at a time.
|
|
31
|
+
- Newlines end statements except inside `()` and `[]`, or when the previous physical line ends with a binary operator such as `+`, `and`, or `==`.
|
|
32
|
+
- Comma-separated lists inside `()` and `[]` accept trailing commas. Prefer them for multiline parameters, arguments, and type lists.
|
|
33
|
+
|
|
34
|
+
Long expressions should usually be wrapped with delimiters, following the same broad shape as Python's implicit line joining:
|
|
35
|
+
|
|
36
|
+
```mt
|
|
37
|
+
let total = (
|
|
38
|
+
subtotal
|
|
39
|
+
+ tax
|
|
40
|
+
- discount
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Milk Tea also accepts operator-led continuation when the previous line ends with a binary operator:
|
|
45
|
+
|
|
46
|
+
```mt
|
|
47
|
+
let total = subtotal +
|
|
48
|
+
tax -
|
|
49
|
+
discount
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This also applies to range expressions:
|
|
53
|
+
|
|
54
|
+
```mt
|
|
55
|
+
let values = 1 ..
|
|
56
|
+
4
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Do not rely on starting the next physical line with the operator; wrap the expression in `()` instead if that layout reads better.
|
|
60
|
+
|
|
61
|
+
Comments:
|
|
62
|
+
|
|
63
|
+
- `#` starts a line comment.
|
|
64
|
+
- `##` starts documentation comments attached to the next declaration if no blank line intervenes.
|
|
65
|
+
|
|
66
|
+
## 2. Literals And Tokens
|
|
67
|
+
|
|
68
|
+
Supported literals:
|
|
69
|
+
|
|
70
|
+
- integers: `42`, `0xff`, `0b1010`, `_` separators allowed. Integer type suffixes: `42u` (`uint`), `0xFFub` (`ubyte`), `100z` (`ptr_uint`), `7i` (`int`), `-1l` (`long`), etc.
|
|
71
|
+
- floats: `3.14`, `1.2e-3`, `1.0f` (float suffix), `1.0d` (double suffix)
|
|
72
|
+
- character: `'a'`, `'\n'`, `'\t'`, `'\\'`, `'\''`, `'\0'`, `'\x41'`. Type is `ubyte`. Escape sequences: `\n`, `\r`, `\t`, `\\`, `\'`, `\"`, `\0` (null byte), `\xNN` (hex byte).
|
|
73
|
+
- booleans: `true`, `false`
|
|
74
|
+
- string: `"hello"` -> `str`
|
|
75
|
+
- cstring: `c"hello"` -> `cstr`
|
|
76
|
+
- heredoc string: `<<-TAG ... TAG`
|
|
77
|
+
- heredoc cstring: `c<<-TAG ... TAG`
|
|
78
|
+
- format string: `f"count=#{count}"`
|
|
79
|
+
- `null`, including typed forms like `null[ptr[char]]` when context does not determine the target type
|
|
80
|
+
|
|
81
|
+
Common punctuation and operators:
|
|
82
|
+
|
|
83
|
+
- delimiters: `(` `)` `[` `]`
|
|
84
|
+
- access and separators: `:` `,` `.`
|
|
85
|
+
- type markers: `->` `?`
|
|
86
|
+
- arithmetic: `+ - * / %`
|
|
87
|
+
- bitwise: `~ & | ^ << >>`
|
|
88
|
+
- comparison: `== != < <= > >=`
|
|
89
|
+
- assignment: `= += -= *= /= %= &= |= ^= <<= >>=`
|
|
90
|
+
- variadic marker: `...`
|
|
91
|
+
- word operators: `and`, `or`, `not`
|
|
92
|
+
- pattern test: `is` — desugars to `match` expression for variant arm membership test
|
|
93
|
+
|
|
94
|
+
## 3. Top-Level Declarations
|
|
95
|
+
|
|
96
|
+
Supported top-level declarations:
|
|
97
|
+
|
|
98
|
+
- `const` (expression form and block-bodied form with `->`)
|
|
99
|
+
- `const function` — compile-time-evaluable function, callable from compile-time and runtime
|
|
100
|
+
- `var`
|
|
101
|
+
- `type`
|
|
102
|
+
- `attribute`
|
|
103
|
+
- `interface`
|
|
104
|
+
- `struct`
|
|
105
|
+
- `union`
|
|
106
|
+
- `variant`
|
|
107
|
+
- `enum`
|
|
108
|
+
- `flags`
|
|
109
|
+
- `opaque`
|
|
110
|
+
- `extending`
|
|
111
|
+
- `function`
|
|
112
|
+
- `async function`
|
|
113
|
+
- `external function`
|
|
114
|
+
- `foreign function`
|
|
115
|
+
- `event`
|
|
116
|
+
- `static_assert(...)`
|
|
117
|
+
- `emit` — compile-time code generation inside `const function` or `inline` bodies
|
|
118
|
+
- `when` (compile-time conditional; may appear at module level or inside function bodies)
|
|
119
|
+
|
|
120
|
+
File-kind note:
|
|
121
|
+
|
|
122
|
+
- Ordinary files may use the full declaration surface above.
|
|
123
|
+
- External files are intentionally narrower: after optional imports and directives, they allow only `const`, `type`, `struct`, `union`, `enum`, `flags`, `opaque`, and `external function`. External files cannot declare new attributes, but supported attribute applications such as `@[packed]` and `@[align(...)]` may still appear on declarations that accept them.
|
|
124
|
+
- `event` declarations are not allowed in external files.
|
|
125
|
+
|
|
126
|
+
Visibility:
|
|
127
|
+
|
|
128
|
+
- `public` is allowed on exportable ordinary declarations.
|
|
129
|
+
- `public` is rejected on `extending` blocks.
|
|
130
|
+
- `public` is rejected on ordinary `external` declarations and `static_assert`.
|
|
131
|
+
- In external files, declarations are implicitly exported and `public` is rejected.
|
|
132
|
+
|
|
133
|
+
## 4. Variables And Guards
|
|
134
|
+
|
|
135
|
+
- `const` requires an explicit type and initializer. A block-bodied form `const NAME -> TYPE:` followed by an indented block is also supported; the block is evaluated at compile time and must end with a `return`.
|
|
136
|
+
- Top-level `var` requires an explicit type. Its initializer is optional but must be static-storage-safe when present.
|
|
137
|
+
- Local `let` is immutable.
|
|
138
|
+
- Local `var` is mutable.
|
|
139
|
+
- A local declaration without an initializer requires an explicit type and must be zero-initializable.
|
|
140
|
+
|
|
141
|
+
Guard form:
|
|
142
|
+
|
|
143
|
+
```mt
|
|
144
|
+
let value = maybe_value else:
|
|
145
|
+
return 1
|
|
146
|
+
|
|
147
|
+
var runtime = maybe_runtime else:
|
|
148
|
+
return 1
|
|
149
|
+
|
|
150
|
+
let parsed = parse(input) else as error:
|
|
151
|
+
return error
|
|
152
|
+
|
|
153
|
+
let _ = initialize() else:
|
|
154
|
+
return 1
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Tuple destructuring:
|
|
158
|
+
|
|
159
|
+
```mt
|
|
160
|
+
let (a, b) = pair()
|
|
161
|
+
let (x, y) = (1, 2)
|
|
162
|
+
let (_, _, title) = triple # _ may appear more than once
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Struct destructuring:
|
|
166
|
+
|
|
167
|
+
```mt
|
|
168
|
+
struct Vec2:
|
|
169
|
+
x: float
|
|
170
|
+
y: float
|
|
171
|
+
let p = Vec2(x = 1.0, y = 2.0)
|
|
172
|
+
let Vec2(x, y) = p
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Rules for `let ... else:` and `var ... else:`:
|
|
176
|
+
|
|
177
|
+
- Both `let` and `var` support an `else` block.
|
|
178
|
+
- The initializer must have type `T?`, `Option[T]`, or `Result[T, E]`.
|
|
179
|
+
- For `T?`, the bound name has type `T`.
|
|
180
|
+
- For `Option[T]`, the bound name is `some.value`.
|
|
181
|
+
- For `Result[T, E]`, the bound name is `success.value`.
|
|
182
|
+
- `else as error:` optionally binds the `failure.error` value.
|
|
183
|
+
- `let _ = expr else:` checks success without binding a name.
|
|
184
|
+
- The `else` block must terminate control flow.
|
|
185
|
+
|
|
186
|
+
Postfix Result/Option propagation:
|
|
187
|
+
|
|
188
|
+
```mt
|
|
189
|
+
let parsed = parse(input)?
|
|
190
|
+
let lowered = lower(parsed)?
|
|
191
|
+
return Result[Output, Error].success(value= lowered)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
- `expr?` requires `Option[T]` or `Result[T, E]` with a non-`void` success type. Any variant with matching arm structure (`some(value: T)`/`none` or `success(value: T)`/`failure(error: E)`) also works.
|
|
195
|
+
- On success, `expr?` evaluates to the unwrapped `T`.
|
|
196
|
+
- On failure, `expr?` returns `Option[_].none` or `Result[_, E].failure(error= ...)` from the enclosing function or proc.
|
|
197
|
+
- As an expression statement, `expr?` also accepts `Option[void]` or `Result[void, E]`; success continues and failure returns early.
|
|
198
|
+
- `expr?` is only allowed inside function and proc bodies.
|
|
199
|
+
- Inside `async` functions, failure completes the task early.
|
|
200
|
+
- `expr?` is not allowed inside `defer` blocks.
|
|
201
|
+
- The enclosing function or proc must return a compatible type — `Option[_]` or `Result[_, E]` with the same error type `E`.
|
|
202
|
+
- `let _ = expr else:` is still useful when you need an explicit `else` block or `else as error:` binding.
|
|
203
|
+
|
|
204
|
+
Callable and `ref[...]` rules:
|
|
205
|
+
|
|
206
|
+
- Plain stored `ref[T]` values are rejected in constants, module variables, and nested local storage such as arrays or other generic containers.
|
|
207
|
+
- In struct or union fields, bare `ref[T]` auto-generates an implicit lifetime parameter. The struct becomes non-owning, inheriting ref-like restrictions: allowed as function params and local `let` variables, rejected as returns and module storage. Explicit lifetime parameters (`struct Cursor[@a]: data: ref[@a, span[ubyte]]`) are still supported when the lifetime needs to be shared across multiple fields.
|
|
208
|
+
- Ordinary local bindings may still hold a direct `ref[T]` value, for example `let handle = ref_of(counter)`.
|
|
209
|
+
- `fn(...)` and `proc(...)` parameter types may use `ref[...]` directly in parameter position.
|
|
210
|
+
- Stored callable values may use `ref[...]` only in direct callable parameter positions. This includes `fn(...)` values and `proc(...)` closure values stored in locals, struct fields, and generic containers such as `array[...]`.
|
|
211
|
+
- Stored callable values may not use `ref[...]` in return types.
|
|
212
|
+
- Stored callable values may not nest `ref[...]` anywhere except direct callable parameter positions.
|
|
213
|
+
- External functions still cannot take `ref[...]` parameters, and ordinary functions still cannot return `ref[...]`.
|
|
214
|
+
- `proc` captures are value captures. A captured local is not a mutable alias back to the outer binding. Any storable type may be captured, including scalars, arrays, structs, and other `proc` values. Captured `proc` values participate in the ref-counted lifecycle: the capturing proc retains the captured proc on creation and releases it when the env is freed.
|
|
215
|
+
- `ref[T]` values are not capturable by design since they are non-owning.
|
|
216
|
+
- Shared mutable proc state should use explicit storage such as `std.cell.alloc[T](...)` or other explicit pointer-backed state, not implicit mutable capture.
|
|
217
|
+
|
|
218
|
+
## 5. Data Declarations
|
|
219
|
+
|
|
220
|
+
Examples:
|
|
221
|
+
|
|
222
|
+
```mt
|
|
223
|
+
type Seconds = float
|
|
224
|
+
|
|
225
|
+
struct Vec2:
|
|
226
|
+
x: float
|
|
227
|
+
y: float
|
|
228
|
+
|
|
229
|
+
@[packed]
|
|
230
|
+
struct Header:
|
|
231
|
+
tag: ubyte
|
|
232
|
+
|
|
233
|
+
@[align(16)]
|
|
234
|
+
struct Mat4:
|
|
235
|
+
data: array[float, 16]
|
|
236
|
+
|
|
237
|
+
Nested structs declare scoped types inside an enclosing struct body:
|
|
238
|
+
|
|
239
|
+
```mt
|
|
240
|
+
struct Rectangle:
|
|
241
|
+
x: float
|
|
242
|
+
y: float
|
|
243
|
+
|
|
244
|
+
struct Edge:
|
|
245
|
+
start: float
|
|
246
|
+
end: float
|
|
247
|
+
|
|
248
|
+
top_edge: Edge
|
|
249
|
+
left_edge: Edge
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- Nested structs are full independent types scoped inside their parent. Their qualified name is `Parent.Nested` (e.g., `Rectangle.Edge`).
|
|
253
|
+
- Inside the parent struct, bare names resolve to nested types (e.g., `Edge` means `Rectangle.Edge`).
|
|
254
|
+
- Outside, use the qualified name: `var e: Rectangle.Edge`.
|
|
255
|
+
- Nested structs may themselves contain nested structs to arbitrary depth.
|
|
256
|
+
- The generated C name uses underscore-separated path components (e.g., `module_Rectangle_Edge`).
|
|
257
|
+
|
|
258
|
+
union Number:
|
|
259
|
+
i: int
|
|
260
|
+
f: float
|
|
261
|
+
|
|
262
|
+
enum State: ubyte
|
|
263
|
+
idle = 0
|
|
264
|
+
running = 1
|
|
265
|
+
|
|
266
|
+
# Backing type defaults to int; values auto-increment from 0:
|
|
267
|
+
enum Color:
|
|
268
|
+
red
|
|
269
|
+
green
|
|
270
|
+
blue
|
|
271
|
+
|
|
272
|
+
flags Mask: uint
|
|
273
|
+
a = 1 << 0
|
|
274
|
+
b = 1 << 1
|
|
275
|
+
|
|
276
|
+
opaque SDL_Window
|
|
277
|
+
|
|
278
|
+
variant Token:
|
|
279
|
+
ident(text: str)
|
|
280
|
+
number(value: int)
|
|
281
|
+
eof
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Rules:
|
|
285
|
+
|
|
286
|
+
- `struct` and `opaque` may declare nominal interface conformance with `implements`.
|
|
287
|
+
- `attribute[target, ...]` declares reusable declaration attributes for `struct`, `field`, `callable`, `const`, `event`, `enum`, `flags`, `union`, and `variant` targets.
|
|
288
|
+
- Attributes are applied with one or more leading `@[name(...)]` blocks. Built-in `packed`, `align(bytes)`, and `deprecated(message)` are predefined attributes.
|
|
289
|
+
- `variant` arms may carry named payload fields.
|
|
290
|
+
- Payload arm construction uses named fields: `Token.ident(text = "hello")`.
|
|
291
|
+
- No-payload arms are bare member expressions: `Token.eof`.
|
|
292
|
+
- `enum` and `flags` backing types must be integer primitives.
|
|
293
|
+
- `enum` and `flags` members must be compile-time integer constants.
|
|
294
|
+
- `enum` backing types default to `int` when omitted; member values auto-increment from 0 or the previous explicit value.
|
|
295
|
+
- `flags` members may reference earlier members to spell composite aliases such as `read_write = Permission.read | Permission.write`.
|
|
296
|
+
- `align(...)` must be a positive power of two.
|
|
297
|
+
- Compile-time reflection over validated attributes uses `has_attribute`, `attribute_of`, `attribute_arg[T]`, `field_of`, and `callable_of`.
|
|
298
|
+
- `field_of(...)`, `callable_of(...)`, and `attribute_of(...)` produce compile-time handle values with source-visible handle types `field_handle`, `callable_handle`, and `attribute_handle`.
|
|
299
|
+
- 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.
|
|
300
|
+
|
|
301
|
+
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 (`|`, `&`, `^`, `~`).
|
|
302
|
+
|
|
303
|
+
Generic variants and structs are supported, for example `Option[int]`.
|
|
304
|
+
|
|
305
|
+
## 6. Interfaces And Methods
|
|
306
|
+
|
|
307
|
+
Interface example:
|
|
308
|
+
|
|
309
|
+
```mt
|
|
310
|
+
public interface Damageable:
|
|
311
|
+
editable function take_damage(amount: int) -> void
|
|
312
|
+
function is_alive() -> bool
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Interface rules:
|
|
316
|
+
|
|
317
|
+
- Interface bodies contain `function`, `editable function`, or `static function` signatures.
|
|
318
|
+
- Generic interfaces are supported: `interface Mapper[T]: function map(x: T) -> T`.
|
|
319
|
+
- Interface methods may not have their own type params — `T` comes from the interface.
|
|
320
|
+
- Interface methods may not be `async`.
|
|
321
|
+
- Interface methods do not have bodies.
|
|
322
|
+
- Bare interface names are not runtime storage types.
|
|
323
|
+
- Interfaces are used by `implements` and constrained generics, not as runtime value types.
|
|
324
|
+
- Runtime interface values use `dyn[InterfaceName]` — a fat pointer carrying a data pointer and a vtable pointer. Construct with `adapt[Interface](value: ref[T])`, which verifies `T implements Interface` at compile time.
|
|
325
|
+
- Generic interfaces instantiated through `dyn` must be fully specified: `dyn[Mapper[int]]` is valid; `dyn[Mapper]` is rejected.
|
|
326
|
+
- Conformance with generic interfaces uses type substitution: `struct Foo implements Mapper[int]` checks that `Foo`'s methods match `Mapper`'s methods with `T` replaced by `int`.
|
|
327
|
+
|
|
328
|
+
Method kinds:
|
|
329
|
+
|
|
330
|
+
- `function` -> value receiver
|
|
331
|
+
- `editable function` -> editable receiver
|
|
332
|
+
- `static function` -> no receiver
|
|
333
|
+
|
|
334
|
+
Method notes:
|
|
335
|
+
|
|
336
|
+
- Async methods are supported.
|
|
337
|
+
- Generic methods are supported.
|
|
338
|
+
- There is no constructor keyword. Names like `init` and `default` are ordinary static methods.
|
|
339
|
+
|
|
340
|
+
## 7. Functions, Externals, And Foreign Functions
|
|
341
|
+
|
|
342
|
+
Ordinary functions:
|
|
343
|
+
|
|
344
|
+
- Parameters must be typed.
|
|
345
|
+
- Parameters are non-rebindable.
|
|
346
|
+
- Return type defaults to `void` if omitted.
|
|
347
|
+
- Generic functions are supported.
|
|
348
|
+
- Generic function and method type parameters may use `implements` constraints.
|
|
349
|
+
|
|
350
|
+
`const function`:
|
|
351
|
+
|
|
352
|
+
A `const function` is evaluable at compile time. Its body follows the same restrictions as a block-bodied `const`. When called from a compile-time context (`const`, `when`, `inline if`, `inline for`), the call is constant-folded:
|
|
353
|
+
|
|
354
|
+
```mt
|
|
355
|
+
const function square(x: int) -> int:
|
|
356
|
+
return x * x
|
|
357
|
+
|
|
358
|
+
const RESULT: int = square(5) # folded to 25 at compile time
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
`const function` also generates a normal runtime function, callable from ordinary runtime code.
|
|
362
|
+
|
|
363
|
+
External functions:
|
|
364
|
+
|
|
365
|
+
```mt
|
|
366
|
+
external function printf(format: cstr, ...) -> int
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Raw `std.c.*` modules usually group many `external function` declarations inside an external file, but `external function` is also allowed in ordinary files for small manual ABI bridges.
|
|
370
|
+
|
|
371
|
+
Rules:
|
|
372
|
+
|
|
373
|
+
- No body.
|
|
374
|
+
- Variadic `...` is supported.
|
|
375
|
+
- Cannot be generic.
|
|
376
|
+
- Cannot be async.
|
|
377
|
+
- Cannot take arrays.
|
|
378
|
+
- Cannot take `ref` parameters.
|
|
379
|
+
- Cannot take `proc` parameters.
|
|
380
|
+
- Cannot return arrays.
|
|
381
|
+
- Calls may pass enum or flags values to same-width fixed-width integer parameters without an explicit cast for C ABI interop.
|
|
382
|
+
|
|
383
|
+
Foreign functions:
|
|
384
|
+
|
|
385
|
+
```mt
|
|
386
|
+
foreign function init_window(width: int, height: int, title: str as cstr) -> void = c.InitWindow
|
|
387
|
+
foreign function load_file_data(file_name: str as cstr, out data_size: int) -> ptr[ubyte]? = c.LoadFileData
|
|
388
|
+
foreign function close_window(consuming window: Window) -> void = c.CloseWindow
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Parameter modes:
|
|
392
|
+
|
|
393
|
+
- plain
|
|
394
|
+
- `in`
|
|
395
|
+
- `out`
|
|
396
|
+
- `inout`
|
|
397
|
+
- `consuming`
|
|
398
|
+
|
|
399
|
+
Boundary projection syntax:
|
|
400
|
+
|
|
401
|
+
- `name: PublicType as BoundaryType`
|
|
402
|
+
|
|
403
|
+
Foreign-function rules:
|
|
404
|
+
|
|
405
|
+
- `as` is only allowed on plain and `in` parameters.
|
|
406
|
+
- `in`, `out`, and `inout` are declared on the parameter, not at the call site.
|
|
407
|
+
- Legacy call syntax like `load_file_data(path, out size)` or `inspect(in value)` is rejected.
|
|
408
|
+
- `consuming` foreign functions must return `void`.
|
|
409
|
+
- Consuming foreign calls must appear as top-level expression statements.
|
|
410
|
+
- A consuming argument must be a bare nullable local or parameter binding.
|
|
411
|
+
|
|
412
|
+
## 8. Statements And Control Flow
|
|
413
|
+
|
|
414
|
+
Supported statements:
|
|
415
|
+
|
|
416
|
+
- local declaration (`let`, `var`)
|
|
417
|
+
- assignment
|
|
418
|
+
- `if` / `else if` / `else`
|
|
419
|
+
- `match`
|
|
420
|
+
- `unsafe`
|
|
421
|
+
- `static_assert`
|
|
422
|
+
- `for`
|
|
423
|
+
- `parallel for` — data-parallel loop dispatched across CPU cores
|
|
424
|
+
- `while`
|
|
425
|
+
- `when` — compile-time conditional; only the chosen branch is type-checked and emitted
|
|
426
|
+
- `inline for` — loop over a compile-time-known array, unrolled at compile time
|
|
427
|
+
- `inline while` — loop with a compile-time-known condition, unrolled at compile time
|
|
428
|
+
- `inline match` — match with a compile-time-known scrutinee, unrolled at compile time
|
|
429
|
+
- `inline if` — if with a compile-time-known condition; only the chosen branch is type-checked and emitted
|
|
430
|
+
- `pass`
|
|
431
|
+
- `break`
|
|
432
|
+
- `continue`
|
|
433
|
+
- `return`
|
|
434
|
+
- `defer`
|
|
435
|
+
- `emit` — only inside `const function` or `inline for/while/if/match` bodies
|
|
436
|
+
- expression statement
|
|
437
|
+
|
|
438
|
+
Rules:
|
|
439
|
+
|
|
440
|
+
- Conditions must be `bool`.
|
|
441
|
+
- There is no truthy or falsy coercion from integers or pointers.
|
|
442
|
+
- `pass` is an explicit no-op statement for intentionally empty block bodies.
|
|
443
|
+
- `if` supports an inline single-statement form: `if cond: stmt else: stmt`. The body is a single statement on the same line instead of an indented block.
|
|
444
|
+
|
|
445
|
+
`match` supports the following scrutinee types:
|
|
446
|
+
|
|
447
|
+
- enum scrutinees
|
|
448
|
+
- variant scrutinees
|
|
449
|
+
- integer scrutinees
|
|
450
|
+
- `str` scrutinees
|
|
451
|
+
- tuple scrutinees
|
|
452
|
+
|
|
453
|
+
`match` may also be used as an expression, producing a value from the matched arm:
|
|
454
|
+
|
|
455
|
+
```mt
|
|
456
|
+
let label = match code:
|
|
457
|
+
1: "one"
|
|
458
|
+
2: "two"
|
|
459
|
+
_: "other"
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
`match` rules:
|
|
463
|
+
|
|
464
|
+
- Enum and variant matches must be exhaustive unless `_` is present.
|
|
465
|
+
- Integer, `str`, and tuple matches require `_`. Integer match arms accept integer literals and char literals; `str` match arms accept string literals; tuple match arms accept tuple literal patterns whose elements may be literals, char literals, string literals, or `_` discard.
|
|
466
|
+
- Multiple pattern values may share the same arm body using `|`: `kind` matches `kind_a | kind_b`.
|
|
467
|
+
- Variant payload arms may bind with `as name`.
|
|
468
|
+
- Variant payload arms may destructure fields inline with struct patterns: `Variant.arm(field > 0, other)` — comparisons are guards (arm skipped if false), identifiers are bindings (field becomes a local), and `field = value` is an equality guard.
|
|
469
|
+
|
|
470
|
+
```mt
|
|
471
|
+
match token:
|
|
472
|
+
Token.ident(text):
|
|
473
|
+
use_name(text)
|
|
474
|
+
Token.number as n:
|
|
475
|
+
use_value(n.value)
|
|
476
|
+
Token.eof:
|
|
477
|
+
return
|
|
478
|
+
|
|
479
|
+
# Discard unneeded fields with _
|
|
480
|
+
match multi_field:
|
|
481
|
+
Entity.tag(_, _, _, label):
|
|
482
|
+
use_label(label)
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Tuple match example:
|
|
486
|
+
|
|
487
|
+
```mt
|
|
488
|
+
# Expression form
|
|
489
|
+
let label = match rgb:
|
|
490
|
+
(255, 0, 0): "red"
|
|
491
|
+
(0, 255, 0): "green"
|
|
492
|
+
_: "other"
|
|
493
|
+
|
|
494
|
+
# Statement form with wildcards
|
|
495
|
+
match point:
|
|
496
|
+
(_, y) if y > 0:
|
|
497
|
+
handle_above(y)
|
|
498
|
+
_:
|
|
499
|
+
handle_other()
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Struct pattern rules:
|
|
503
|
+
|
|
504
|
+
- Guards (`hp > 0`, `level >= 3`) skip the arm if the condition is false; the match tries the next arm. Supported guard operators: `==`, `!=`, `<`, `<=`, `>`, `>=`.
|
|
505
|
+
- Equality patterns (`kind = Kind.boss`) skip the arm if the field does not equal the value.
|
|
506
|
+
- Bindings (`position`) create immutable local variables bound to the field value.
|
|
507
|
+
- Discard (`_`) skips a field position without binding it; useful when you only need a subset of a multi-field payload arm. `_` may appear more than once.
|
|
508
|
+
- Guards and equality patterns are refutable: they do not count toward exhaustiveness. Exception: when equality patterns for an enum-typed field gatherively cover every member of the enum, the arm is considered exhaustive.
|
|
509
|
+
- For variant payload arms, struct patterns compose with `as name` bindings.
|
|
510
|
+
- When a variant arm has exactly one payload field of struct type, and no pattern argument references that field name, the struct's own fields are transparently destructured. For example, `Entity.positioned(x, y)` where `positioned(loc: Pos)` destructures through `Pos` to bind `x` and `y`.
|
|
511
|
+
|
|
512
|
+
Loop forms:
|
|
513
|
+
|
|
514
|
+
- `for i in 0..count:` for exclusive integer ranges
|
|
515
|
+
- `for item in items:` for arrays, spans, and custom iterables
|
|
516
|
+
- Custom iterable protocol: `items.iter()` must take no arguments, be a non-editable method, and return the iterator value.
|
|
517
|
+
- Iterator forms: either `next() ->` nullable pointer-like item, or `next() -> bool` together with `current() -> T`.
|
|
518
|
+
- `for left, right in xs, ys:` for parallel array/span iteration
|
|
519
|
+
- Parallel `for` does not accept ranges.
|
|
520
|
+
|
|
521
|
+
`parallel for` dispatches loop iterations across multiple CPU cores using real OS threads:
|
|
522
|
+
|
|
523
|
+
```mt
|
|
524
|
+
parallel for i in 0..entity_count:
|
|
525
|
+
positions[i] += velocities[i] * dt
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Rules:
|
|
529
|
+
|
|
530
|
+
- Only range iteration is supported (`0..N`).
|
|
531
|
+
- The loop body must not contain `break`, `continue`, `return`, `defer`, or nested `parallel for`.
|
|
532
|
+
- Captured `ref[T]` values are rejected at compile time.
|
|
533
|
+
- Array captures are passed by pointer; span and scalar captures are passed by value.
|
|
534
|
+
- The compiler automatically links libuv for thread dispatch when `parallel for` is used.
|
|
535
|
+
|
|
536
|
+
`parallel:` blocks run each statement concurrently, blocking the caller until all complete:
|
|
537
|
+
|
|
538
|
+
```mt
|
|
539
|
+
parallel:
|
|
540
|
+
textures = load_textures(path)
|
|
541
|
+
sounds = load_sounds(path)
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Rules:
|
|
545
|
+
|
|
546
|
+
- A `parallel:` block must contain at least two statements.
|
|
547
|
+
- Each statement must not contain `break`, `continue`, `return`, or `defer`.
|
|
548
|
+
- The compiler enforces single-writer-or-multiple-readers: if a variable is written in one statement, no other block may access it.
|
|
549
|
+
- Captured `ref[T]` values are rejected at compile time.
|
|
550
|
+
|
|
551
|
+
`detach` spawns work on a separate thread and returns a `Handle`. `gather` blocks until all handles complete:
|
|
552
|
+
|
|
553
|
+
```mt
|
|
554
|
+
let a = detach load_textures(path)
|
|
555
|
+
let b = detach load_sounds(path)
|
|
556
|
+
process_other_stuff()
|
|
557
|
+
gather a, b
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Rules:
|
|
561
|
+
|
|
562
|
+
- `detach` is an expression returning a `Handle` — must be bound with `let` or `var`.
|
|
563
|
+
- Currently only supports global function calls with no captured local variables.
|
|
564
|
+
- `gather` takes one or more `Handle` values, joined in order.
|
|
565
|
+
- Captured `ref[T]` values are rejected at compile time.
|
|
566
|
+
- The compiler automatically links libuv for thread dispatch.
|
|
567
|
+
|
|
568
|
+
`defer`:
|
|
569
|
+
|
|
570
|
+
- `defer expr`
|
|
571
|
+
- `defer:` block form
|
|
572
|
+
- `return` is not allowed inside defer blocks.
|
|
573
|
+
|
|
574
|
+
`unsafe` is required for:
|
|
575
|
+
|
|
576
|
+
- pointer indexing
|
|
577
|
+
- raw pointer dereference
|
|
578
|
+
- pointer arithmetic
|
|
579
|
+
- pointer casts
|
|
580
|
+
- `reinterpret[...]`
|
|
581
|
+
|
|
582
|
+
Range index assignment is supported:
|
|
583
|
+
|
|
584
|
+
```mt
|
|
585
|
+
buf[0..3] = (1.0, 2.0, 3.0)
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
Rules:
|
|
589
|
+
|
|
590
|
+
- The bounds must be integer literals.
|
|
591
|
+
- The range is start-inclusive and end-exclusive.
|
|
592
|
+
- The right-hand side must be an expression list with exactly matching width.
|
|
593
|
+
|
|
594
|
+
Compile-time control flow:
|
|
595
|
+
|
|
596
|
+
`when` evaluates its discriminant at compile time and emits only the chosen branch:
|
|
597
|
+
|
|
598
|
+
```mt
|
|
599
|
+
when TARGET_OS:
|
|
600
|
+
TargetOs.linux:
|
|
601
|
+
return open_linux(path)
|
|
602
|
+
TargetOs.windows:
|
|
603
|
+
return open_windows(path)
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
- The discriminant must be a compile-time constant.
|
|
607
|
+
- Only the chosen branch is type-checked and lowered.
|
|
608
|
+
- An `else` branch is required unless the discriminant is an enum and every member is covered.
|
|
609
|
+
- `when` may appear at module level to conditionally include declarations.
|
|
610
|
+
|
|
611
|
+
`inline for` unrolls a loop over a compile-time-known array:
|
|
612
|
+
|
|
613
|
+
```mt
|
|
614
|
+
inline for field in fields_of(Particle):
|
|
615
|
+
static_assert(field.type == float, "Particle fields must be float")
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
- The iterable must be a compile-time-known array (from reflection builtins or a literal array).
|
|
619
|
+
|
|
620
|
+
`inline while` unrolls a loop with a compile-time-known condition:
|
|
621
|
+
|
|
622
|
+
```mt
|
|
623
|
+
inline while n < 1024:
|
|
624
|
+
n = n * 2
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
- The condition must be a compile-time constant. The loop unrolls to a fixed number of iterations.
|
|
628
|
+
|
|
629
|
+
`inline match` unrolls a match with a compile-time-known scrutinee; only the chosen arm emits code. It is not required to be exhaustive.
|
|
630
|
+
|
|
631
|
+
`inline if` branches on a compile-time-known boolean condition:
|
|
632
|
+
|
|
633
|
+
```mt
|
|
634
|
+
const DEBUG_RENDER: bool = false
|
|
635
|
+
|
|
636
|
+
function draw() -> void:
|
|
637
|
+
inline if DEBUG_RENDER:
|
|
638
|
+
debug_overlay()
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
- The condition must be a compile-time constant.
|
|
642
|
+
- A compile-time **type comparison** is a valid condition: `T == int`, `field.type == float`, etc., where `T` is a generic type parameter and `field.type` is a reflected field type — enabling type-based dispatch in generic bodies.
|
|
643
|
+
- Only the chosen branch is type-checked and emitted. The dead branch may reference types and symbols that do not exist.
|
|
644
|
+
- `inline if` supports `else` and `else if` branches; the chosen branch follows the same dead-elimination rule.
|
|
645
|
+
|
|
646
|
+
## 9. Expressions And Operators
|
|
647
|
+
|
|
648
|
+
Primary expressions:
|
|
649
|
+
|
|
650
|
+
- identifiers
|
|
651
|
+
- literals
|
|
652
|
+
- parenthesized expressions
|
|
653
|
+
- tuple literal: `(a, b)` — positional; `(x = 1, y = 2)` — named
|
|
654
|
+
- `size_of(T)`
|
|
655
|
+
- `align_of(T)`
|
|
656
|
+
- `offset_of(T, field)`
|
|
657
|
+
|
|
658
|
+
`size_of` and `offset_of` accept compile-time expressions for the type and field arguments respectively, enabling generic per-field introspection through `inline for`:
|
|
659
|
+
|
|
660
|
+
```mt
|
|
661
|
+
inline for field in fields_of(Point):
|
|
662
|
+
let s = size_of(field.type)
|
|
663
|
+
let o = offset_of(Point, field)
|
|
664
|
+
```
|
|
665
|
+
- `proc(...) -> T: ...`
|
|
666
|
+
- `proc(...) -> T: expr` for a single expression body, implicitly returned
|
|
667
|
+
- `if cond: a else: b`
|
|
668
|
+
- `match scrutinee: arm: value ...` — produces a value from the matched arm
|
|
669
|
+
|
|
670
|
+
Postfix forms:
|
|
671
|
+
|
|
672
|
+
- member access: `a.b`
|
|
673
|
+
- indexing: `a[i]`
|
|
674
|
+
- call: `f(x)`
|
|
675
|
+
- partial field update: `v.with(x = 10.0)` — returns a copy with specified fields replaced
|
|
676
|
+
- specialization: `name[T]`, `name[32]`, `mod.name[T]`
|
|
677
|
+
- explicit specialization is only accepted on bare or module-qualified names; `value.member[32](...)` remains indexed-call syntax, so value-member calls rely on inference instead of explicit literal specialization
|
|
678
|
+
|
|
679
|
+
Operator precedence, low to high:
|
|
680
|
+
|
|
681
|
+
1. `or`
|
|
682
|
+
2. `and`
|
|
683
|
+
3. `not` (unary prefix)
|
|
684
|
+
4. `is`
|
|
685
|
+
5. `|`
|
|
686
|
+
6. `^`
|
|
687
|
+
7. `&`
|
|
688
|
+
8. `==`, `!=`
|
|
689
|
+
9. `<`, `<=`, `>`, `>=`
|
|
690
|
+
10. `<<`, `>>`
|
|
691
|
+
11. `+`, `-`
|
|
692
|
+
12. `*`, `/`, `%`
|
|
693
|
+
|
|
694
|
+
Native type operators:
|
|
695
|
+
|
|
696
|
+
- Vectors (`vecN`/`ivecN`): `+`, `-`, `*` (component-wise) with same-type vectors; `*`, `/` with scalar; unary `-`
|
|
697
|
+
- Matrices (`matN`): `+`, `-` with same-type matrices; `*`, `/` with scalar; unary `-`
|
|
698
|
+
- Quaternions (`quat`): `+`, `-`, `*` (component-wise) with same-type quaternions; unary `-`
|
|
699
|
+
|
|
700
|
+
## 10. Type System
|
|
701
|
+
|
|
702
|
+
Primitive types:
|
|
703
|
+
|
|
704
|
+
- `bool`
|
|
705
|
+
- `byte`, `short`, `int`, `long`
|
|
706
|
+
- `ubyte`, `ushort`, `uint`, `ulong`
|
|
707
|
+
- `char`
|
|
708
|
+
- `ptr_int`, `ptr_uint`
|
|
709
|
+
- `float`, `double`
|
|
710
|
+
- `void`
|
|
711
|
+
- `str`
|
|
712
|
+
- `cstr`
|
|
713
|
+
- `vec2`, `vec3`, `vec4` — float vectors with `.x` `.y` `.z` `.w` fields
|
|
714
|
+
- `ivec2`, `ivec3`, `ivec4` — integer vectors with `.x` `.y` `.z` `.w` fields
|
|
715
|
+
- `mat3`, `mat4` — column-major matrices; `mat3` has `vec3` columns `.col0`–`.col2`, `mat4` has `vec4` columns `.col0`–`.col3`
|
|
716
|
+
- `quat` — quaternion with `.x` `.y` `.z` `.w` fields (layout-compatible with `vec4`)
|
|
717
|
+
|
|
718
|
+
Native vector, matrix, and quaternion types support aggregate construction with named fields, same as struct literals. Omitted fields default to zero.
|
|
719
|
+
|
|
720
|
+
```mt
|
|
721
|
+
let direction = vec3(x = 1.0, y = 0.0, z = 0.0)
|
|
722
|
+
let identity = mat4(
|
|
723
|
+
col0 = vec4(x = 1.0, y = 0.0, z = 0.0, w = 0.0),
|
|
724
|
+
col1 = vec4(x = 0.0, y = 1.0, z = 0.0, w = 0.0),
|
|
725
|
+
col2 = vec4(x = 0.0, y = 0.0, z = 1.0, w = 0.0),
|
|
726
|
+
col3 = vec4(x = 0.0, y = 0.0, z = 0.0, w = 1.0),
|
|
727
|
+
)
|
|
728
|
+
let q = quat(x = 0.0, y = 0.0, z = 0.0, w = 1.0)
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
Primitive type names are reserved. They cannot be reused for value bindings, parameters, locals, import aliases, or type parameters.
|
|
732
|
+
|
|
733
|
+
Type constructors:
|
|
734
|
+
|
|
735
|
+
- `ptr[T]`
|
|
736
|
+
- `const_ptr[T]`
|
|
737
|
+
- `own[T]` — owning heap pointer: auto-dereferences like `ref` but storable, returnable, and nullable. Created via `heap.must_alloc[T](count)`. Compiles to `T*`.
|
|
738
|
+
- `ref[T]`
|
|
739
|
+
- `span[T]`
|
|
740
|
+
- `array[T, N]`
|
|
741
|
+
- `str_buffer[N]`
|
|
742
|
+
- `Task[T]`
|
|
743
|
+
- `Option[T]`
|
|
744
|
+
- `Result[T, E]`
|
|
745
|
+
- `fn(params...) -> R`
|
|
746
|
+
- `proc(params...) -> R`
|
|
747
|
+
- `SoA[T, N]` — Structure-of-Arrays: each struct field becomes a separate array of length `N`; access `soa[i].field` reads from column `field` at row `i`
|
|
748
|
+
- `dyn[InterfaceName]` — runtime interface value (fat pointer: `{ void* data, void* vtable }`). Constructed via `adapt[Interface](value: ref[T])`. @see §6.
|
|
749
|
+
- `atomic[T]` — atomic value for lock-free concurrent access. `T` must be a primitive integer or `bool`. Methods: `load() -> T`, `store(value: T)`, `add(value: T) -> T`, `sub(value: T) -> T`, `exchange(value: T) -> T`. All operations use sequential consistency. Lowers to C11 `_Atomic T` with `__atomic_*` builtins.
|
|
750
|
+
- `(T, U)` — tuple type. Positional fields auto-named `_0`, `_1`. Named fields use `(x = T, y = U)`. Copy by value, returns supported.
|
|
751
|
+
|
|
752
|
+
When a `span[T]` is expected, an addressable `array[T, N]` value may be passed directly via implicit boundary coercion. For explicit conversion, `array.as_span()` returns `span[T]` without requiring a boundary context.
|
|
753
|
+
|
|
754
|
+
Nullability:
|
|
755
|
+
|
|
756
|
+
- Nullable form is `T?` and is valid for any type.
|
|
757
|
+
- For pointer-like bases (`ptr[T]`, `const_ptr[T]`, `own[T]`, `cstr`, `fn(...)`, `proc(...)`, opaque), `T?` is a nullable pointer and `null` is the absent value.
|
|
758
|
+
- For non-pointer value bases (`int`, `bool`, `float`, structs, ...), `T?` is stored inline by value as a tagged optional (a presence flag plus the value). It copies by value with no hidden heap allocation or pointer aliasing.
|
|
759
|
+
- Use `null` for absence in any nullable context.
|
|
760
|
+
- In nullable pointer-like contexts, prefer `null` over `zero[ptr[T]]`.
|
|
761
|
+
- `ref[T]` is non-null and cannot be nullable.
|
|
762
|
+
- At an FFI boundary (`external` / `foreign function` parameters and returns), only pointer-like `T?` is allowed. A non-pointer value nullable such as `int?` is rejected — use `ptr[T]?` or pass an explicit struct.
|
|
763
|
+
|
|
764
|
+
Generics:
|
|
765
|
+
|
|
766
|
+
- Generic structs, variants, functions, methods, and foreign functions are supported.
|
|
767
|
+
- Generic interfaces are supported: `interface Mapper[T]: function map(x: T) -> T`.
|
|
768
|
+
- Generic type parameter constraints use `implements` on structs, variants, interfaces, functions, and methods.
|
|
769
|
+
- `implements` is the interface constraint kind.
|
|
770
|
+
- Multiple interface constraints are joined with `and`.
|
|
771
|
+
- There are no separate `hashes` or `equates` constraints. Generic bodies that call `hash[T](...)`, `equal[T](...)`, or `order[T](...)` rely on specialization-time checking of the canonical associated functions.
|
|
772
|
+
- Current type parameters can be used as type expressions for associated function calls in generic bodies, for example `T.default()` or `T.tag()`.
|
|
773
|
+
- Generic value parameters use the form `[N: int]` to declare a compile-time integer usable in expressions. The call site specializes with a literal: `int_with_bits[64]`.
|
|
774
|
+
- `type` is a built-in type name representing the type of types. A function may return `type` to pick a type at compile time from its value parameters.
|
|
775
|
+
|
|
776
|
+
## 11. Built-In Callable Surface
|
|
777
|
+
|
|
778
|
+
Special recognized callables:
|
|
779
|
+
|
|
780
|
+
- `fatal(message)`
|
|
781
|
+
- `ref_of(x)`
|
|
782
|
+
- `const_ptr_of(x)`
|
|
783
|
+
- `read(r)`
|
|
784
|
+
- `read(p)`
|
|
785
|
+
- `ptr_of(x)`
|
|
786
|
+
- `T<-value`
|
|
787
|
+
- `reinterpret[T](value)`
|
|
788
|
+
- `zero[T]`
|
|
789
|
+
- `default[T]`
|
|
790
|
+
- `hash[T](value)`
|
|
791
|
+
- `equal[T](left, right)`
|
|
792
|
+
- `order[T](left, right)`
|
|
793
|
+
- `array[T, N](...)`
|
|
794
|
+
- `span[T](data = ..., len = ...)`
|
|
795
|
+
- `get(coll, index)` — recoverable array/span indexing returning `ptr[T]?`; null on out‑of‑bounds instead of aborting
|
|
796
|
+
- `adapt[I](value)` — constructs a `dyn[I]` runtime interface value; verifies `value`'s type implements interface `I` at compile time
|
|
797
|
+
|
|
798
|
+
Reference and pointer notes:
|
|
799
|
+
|
|
800
|
+
- `read(ref_value)` explicitly projects the referent value. Use `read(handle) = value` to write through a bare `ref[T]` value.
|
|
801
|
+
- Member access and method calls auto-dereference `ref[T]` receivers. For mutable field access through `ref[Struct]`, use `handle.field += x` directly — no `read()` needed.
|
|
802
|
+
- Passing a mutable addressable `T` to a parameter of type `ref[T]` implicitly borrows it.
|
|
803
|
+
- `hash[T](value)`, `equal[T](left, right)`, and `order[T](left, right)` lower to `T.hash(...)`, `T.equal(...)`, and `T.order(...)` associated functions. Each argument must be a safe stored `T` lvalue that can be borrowed, or an existing `ref[T]`, `ptr[T]`, or `const_ptr[T]`.
|
|
804
|
+
- `T.order(left: const_ptr[T], right: const_ptr[T]) -> int` returns a negative value when `left < right`, `0` when equal, and a positive value when `left > right`.
|
|
805
|
+
- There are no separate `hashes` or `equates` constraints; the builtins themselves force those hook requirements at specialization time.
|
|
806
|
+
- There is no separate `defaults` constraint. A generic body that uses `default[T]` relies on specialization-time checking that `T.default()` exists.
|
|
807
|
+
|
|
808
|
+
Compile-time reflection builtins:
|
|
809
|
+
|
|
810
|
+
- `field_of(T, name)` — returns a `field_handle` for the named field of `T`.
|
|
811
|
+
- `callable_of(T, name)` — returns a `callable_handle` for the named callable of `T`.
|
|
812
|
+
- `attribute_of(T, name)` — returns an `attribute_handle` for the named attribute on `T`.
|
|
813
|
+
- `has_attribute(T, name)` — returns `bool`; true if `T` has the named attribute applied.
|
|
814
|
+
- `attribute_arg[T]` — returns the `T`-typed argument of a resolved attribute handle.
|
|
815
|
+
- `fields_of(T)` — returns `array[field_handle, N]` of all fields of struct `T`, in declaration order.
|
|
816
|
+
- `members_of(E)` — returns `array[member_handle, N]` of all members of enum or variant `E`.
|
|
817
|
+
- `attributes_of(T)` — returns `array[attribute_handle, N]` of all attributes on `T`.
|
|
818
|
+
- `attributes_of(T, name)` — returns `array[attribute_handle, N]` of attributes whose kind matches `name`.
|
|
819
|
+
|
|
820
|
+
Handle types expose: `field_handle` has `.name` and `.type`; `member_handle` has `.name` and optionally `.value`; `attribute_handle` provides access to attribute arguments.
|
|
821
|
+
|
|
822
|
+
A `field_handle`'s `.type` is usable directly **in type position** within a compile-time context (e.g. inside `inline for field in fields_of(T)`): `const_ptr[field.type]`, `equal[field.type](...)`, `Vec[field.type]`, etc. resolve to the field's concrete type. This powers reflective generics such as `std.hash`'s `equal_struct`/`hash_struct`/`order_struct` (per-field canonical-hook dispatch) and `std.fmt.format_value[T]`, which renders any struct as `{ field = value, ... }`.
|
|
823
|
+
|
|
824
|
+
### Standard library
|
|
825
|
+
|
|
826
|
+
Core modules in `std/`:
|
|
827
|
+
|
|
828
|
+
- `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`)
|
|
829
|
+
- `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
|
|
830
|
+
- `std.str` — extends `str` with `byte_at`, `equal`, `starts_with`, `ends_with`, `find_substring`, `is_valid_utf8`, `slice`, `to_cstr`, `hash`, `order`
|
|
831
|
+
- `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).
|
|
832
|
+
- `std.cstring` — C string helpers (`cstr_len`, `cstr_as_str`)
|
|
833
|
+
- `std.math` — `sqrt`, `sin`, `cos`, `abs`, `pow`, etc. via C math
|
|
834
|
+
- `std.encoding` — UTF-8 validation (`is_valid_utf8`, `utf8_codepoint_count`, `decode_utf8_codepoint`, `utf8_overlong_check`)
|
|
835
|
+
- `std.string.String` — growable owned UTF-8 text
|
|
836
|
+
- `std.mem.heap`, `std.mem.arena`, `std.mem.pool`, `std.mem.stack`, `std.mem.tracking`, `std.mem.endian` — allocators and memory utilities
|
|
837
|
+
- `std.async` — task runtime (`sleep`, `work`, `completed`, `result`, `wait`, `run`)
|
|
838
|
+
- `std.option.Option[T]` — optional value with `is_some`, `is_none`, `unwrap`, `expect`, `unwrap_or`, `unwrap_or_else` (auto-imported via prelude)
|
|
839
|
+
- `std.result.Result[T, E]` — fallible computation with `is_success`, `is_failure`, `unwrap`, `unwrap_error`, `unwrap_or`, `unwrap_or_else`, `ok`, `error`, `map_error` (auto-imported via prelude)
|
|
840
|
+
|
|
841
|
+
**Collections**: `std.vec.Vec[T]`, `std.deque.Deque[T]`, `std.map.Map[K,V]`, `std.set.Set[T]`, `std.ordered_map.OrderedMap[K,V]`, `std.ordered_set.OrderedSet[T]`, `std.binary_heap.BinaryHeap[T]`, `std.priority_queue.PriorityQueue[T]`, `std.linked_map.LinkedMap[K,V]`, `std.linked_set.LinkedSet[T]`, `std.counter.Counter[T]`, `std.multiset.MultiSet[T]`, `std.queue.Queue[T]`, `std.stack.Stack[T]`
|
|
842
|
+
|
|
843
|
+
**Serialization**: `std.json`, `std.toml`, `std.uri`, `std.serialize`
|
|
844
|
+
|
|
845
|
+
**System**: `std.time`, `std.fs`, `std.path`, `std.process`, `std.cli`, `std.stdio`, `std.terminal`
|
|
846
|
+
|
|
847
|
+
**Concurrency**: `std.sync`, `std.thread`, `std.jobs`
|
|
848
|
+
|
|
849
|
+
**AI/State**: `std.fsm` (finite state machine), `std.goap` (goal-oriented action planning), `std.behavior_tree`
|
|
850
|
+
|
|
851
|
+
**Networking**: `std.http`, `std.tls`, `std.net` (see also `std.net.manager`, `std.net.discovery`)
|
|
852
|
+
|
|
853
|
+
**Compression**: `std.gzip`, `std.tar`
|
|
854
|
+
|
|
855
|
+
**Other**: `std.bytes`, `std.ctype`, `std.asset_pack`, `std.cell`
|
|
856
|
+
|
|
857
|
+
See module source for full method surface. Iterator forms:
|
|
858
|
+
- Pointer-returning (`next() -> nullable ptr[T]`): `Vec`, `Deque`, `BinaryHeap`/`PriorityQueue`/`OrderedSet` (read-only), `OrderedMap.keys`/`Map.keys`/`Set`/`LinkedMap.keys`/`LinkedSet`/`Counter.keys`/`MultiSet.values`, `Queue`/`Stack` (mutable)
|
|
859
|
+
- `next() -> bool` + `current()`: `OrderedMap.entries`/`iter`, `Map.entries`/`iter`, `LinkedMap.entries`/`iter`, `Counter.counts`/`entries`/`iter`, `MultiSet.entries`/`iter`, `SnapshotValues`/`SnapshotEntries`
|
|
860
|
+
|
|
861
|
+
## 12. Strings, Text, And Builders
|
|
862
|
+
|
|
863
|
+
Text categories:
|
|
864
|
+
|
|
865
|
+
- `str` -> string view
|
|
866
|
+
- `cstr` -> C ABI string
|
|
867
|
+
- `str_buffer[N]` -> fixed-capacity mutable UTF-8 text buffer
|
|
868
|
+
|
|
869
|
+
`str_buffer[N]` methods:
|
|
870
|
+
|
|
871
|
+
- `clear()`
|
|
872
|
+
- `assign(str)`
|
|
873
|
+
- `append(str)`
|
|
874
|
+
- `assign_format(str)`
|
|
875
|
+
- `append_format(str)`
|
|
876
|
+
- `len()`
|
|
877
|
+
- `capacity()`
|
|
878
|
+
- `as_str()`
|
|
879
|
+
- `as_cstr()`
|
|
880
|
+
|
|
881
|
+
Format strings:
|
|
882
|
+
|
|
883
|
+
- `f"count=#{count}"` has type `str`.
|
|
884
|
+
- Allowed interpolations: `str`, `cstr`, `bool`, numeric primitives, integer-backed enums and flags, plus types implementing `format_len() -> ptr_uint` and `append_format(output: ref[std.string.String]) -> void`.
|
|
885
|
+
- `f"..."` is a borrowed temporary on the stack — it cannot be returned from a function as `str`. Use `std.fmt.format(f"...")` returning `string.String` when ownership must escape.
|
|
886
|
+
- Float and double interpolations support `:.N` precision.
|
|
887
|
+
- Integer primitive and integer-backed enum/flags interpolations support `:x` (lowercase hex) and `:X` (uppercase hex).
|
|
888
|
+
- Integer primitive and integer-backed enum/flags interpolations support `:o` / `:O` (octal) and `:b` / `:B` (binary).
|
|
889
|
+
- `std.fmt.format(...)` receives special lowering and returns `string.String`.
|
|
890
|
+
- `std.fmt.append_format(...)` / `std.fmt.assign_format(...)` receive special lowering when passed a format string and write directly into an existing `string.String` sink.
|
|
891
|
+
- `string.String.append_format(...)` / `string.String.assign_format(...)` receive the same direct-sink lowering when passed a format string.
|
|
892
|
+
- `str_buffer[N].append_format(...)` / `str_buffer[N].assign_format(...)` receive the same direct-sink lowering for fixed-capacity buffers.
|
|
893
|
+
- Custom interpolation hooks use the direct sink when formatting into `string.String`; plain `f"..."` expressions and `str_buffer` sinks pass a borrowed `string.String` view onto the destination slice, so those paths stay allocation-free as long as the hook writes exactly `format_len()` bytes.
|
|
894
|
+
|
|
895
|
+
Heredoc notes:
|
|
896
|
+
|
|
897
|
+
- `<<-TAG ... TAG` -> `str`
|
|
898
|
+
- `c<<-TAG ... TAG` -> `cstr`
|
|
899
|
+
- `f<<-TAG ... TAG` -> `str`
|
|
900
|
+
- Content is dedented by shared leading spaces of nonblank lines.
|
|
901
|
+
- The trailing newline before the terminator is preserved.
|
|
902
|
+
|
|
903
|
+
## 13. Safety And Conversion Rules
|
|
904
|
+
|
|
905
|
+
- Conditions must be `bool`.
|
|
906
|
+
- No truthy or falsy coercion.
|
|
907
|
+
- Outside external-call boundaries, enum and flags values do not implicitly coerce to their backing integer types.
|
|
908
|
+
- Mixed signed and unsigned integer arithmetic requires an explicit cast.
|
|
909
|
+
- Non-widening integer conversions (narrowing, signed → unsigned) require an explicit cast. Lossless widening conversions (same signedness to wider or equal width, unsigned → wider signed) are implicit.
|
|
910
|
+
- `%` requires integer-compatible operands.
|
|
911
|
+
- Bitwise operators require matching integer or flags types.
|
|
912
|
+
- Shift operators require integer operands.
|
|
913
|
+
- Safe array indexing requires an addressable array value.
|
|
914
|
+
- Safe indexing (`arr[i]`) is bounds-checked and calls `fatal` on out-of-bounds access.
|
|
915
|
+
- Use `get(arr, i)` for recoverable indexing that returns `ptr[T]?` (null on out-of-bounds) instead of aborting.
|
|
916
|
+
- Pointer indexing requires `unsafe`.
|
|
917
|
+
- `read(ptr)` requires `unsafe`.
|
|
918
|
+
- Pointer casts require `unsafe`.
|
|
919
|
+
- `reinterpret[...]` requires `unsafe`, non-array concrete sized types, and equal-size source and target types.
|
|
920
|
+
|
|
921
|
+
## 14. Async
|
|
922
|
+
|
|
923
|
+
Example:
|
|
924
|
+
|
|
925
|
+
```mt
|
|
926
|
+
async function child() -> int:
|
|
927
|
+
return 41
|
|
928
|
+
|
|
929
|
+
async function parent() -> int:
|
|
930
|
+
let v = await child()
|
|
931
|
+
return v + 1
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
Rules:
|
|
935
|
+
|
|
936
|
+
- `async function` lifts its declared return type to `Task[T]`.
|
|
937
|
+
- `await` is only allowed inside async functions.
|
|
938
|
+
- `async main` is compiler-bootstrapped.
|
|
939
|
+
- `async main` pre-lift return type must be `int` or `void`.
|
|
940
|
+
- `aio.wait(...)` and `aio.run(...)` accept either zero-arg task roots or direct task expressions.
|
|
941
|
+
|
|
942
|
+
Supported `await` contexts include:
|
|
943
|
+
|
|
944
|
+
- plain expression positions
|
|
945
|
+
- call arguments (normalization hoists to `let` bindings)
|
|
946
|
+
- binary operations (`and`, `or`, arithmetic, comparison)
|
|
947
|
+
- `if` expressions
|
|
948
|
+
- `if` / `else if` / `else` bodies and conditions
|
|
949
|
+
- `while` bodies and conditions
|
|
950
|
+
- single-form and parallel `for` bodies and iterables
|
|
951
|
+
- `match` discriminants and arms
|
|
952
|
+
- member access (`a.b`) and indexing (`a[i]`)
|
|
953
|
+
- `let ... else:` initializers and else bodies
|
|
954
|
+
- `unsafe` blocks
|
|
955
|
+
- short-circuit `and` / `or`
|
|
956
|
+
- assignment targets
|
|
957
|
+
- `defer` cleanup bodies inside async functions
|
|
958
|
+
- format strings (`f"#{await expr}"`)
|
|
959
|
+
|
|
960
|
+
## 15. Events
|
|
961
|
+
|
|
962
|
+
Event declarations provide a built-in typed publisher/subscriber surface with fixed-capacity listener storage.
|
|
963
|
+
|
|
964
|
+
Declaration forms:
|
|
965
|
+
|
|
966
|
+
```mt
|
|
967
|
+
event name[capacity]
|
|
968
|
+
event name[capacity](PayloadType)
|
|
969
|
+
public event name[capacity]
|
|
970
|
+
public event name[capacity](PayloadType)
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
Examples:
|
|
974
|
+
|
|
975
|
+
```mt
|
|
976
|
+
public event closed[4]
|
|
977
|
+
public event resized[8](ResizeEvent)
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
Rules:
|
|
981
|
+
|
|
982
|
+
- The capacity expression must be a compile-time positive integer literal.
|
|
983
|
+
- An event carries either no payload or exactly one payload value.
|
|
984
|
+
- The payload type must be a storable type; `ref[T]` payloads are rejected.
|
|
985
|
+
- Event declarations are valid at top level and as struct members.
|
|
986
|
+
- `emit` is only callable from within the declaring module.
|
|
987
|
+
|
|
988
|
+
Built-in event operations:
|
|
989
|
+
|
|
990
|
+
- `event.subscribe(listener) -> Result[Subscription, EventError]`
|
|
991
|
+
- `event.subscribe_once(listener) -> Result[Subscription, EventError]`
|
|
992
|
+
- `event.subscribe(state: ptr[State], listener: fn(ptr[State], ...)) -> Result[Subscription, EventError]` — stateful overload (detected by passing 2 positional arguments)
|
|
993
|
+
- `event.subscribe_once(state: ptr[State], listener: fn(ptr[State], ...)) -> Result[Subscription, EventError]` — stateful one-shot (detected by passing 2 positional arguments)
|
|
994
|
+
- `event.unsubscribe(subscription) -> bool` — returns `true` if the listener was active and removed
|
|
995
|
+
- `event.emit()` or `event.emit(payload)` — only callable from the declaring module
|
|
996
|
+
- `event.wait() -> Task[Result[T, EventError]]` — async wait for the next emission; for no-payload events the result type is `Result[void, EventError]`
|
|
997
|
+
|
|
998
|
+
`EventError` is a built-in enum with a single member `full` (value `0`), returned when listener capacity is exhausted.
|
|
999
|
+
|
|
1000
|
+
`Subscription` is a built-in opaque handle type returned by `subscribe` and `subscribe_once`, used to identify a listener for `unsubscribe`.
|
|
1001
|
+
|
|
1002
|
+
## 16. Language Limitations
|
|
1003
|
+
|
|
1004
|
+
Current compiler rejects:
|
|
1005
|
+
|
|
1006
|
+
### Function and external restrictions
|
|
1007
|
+
|
|
1008
|
+
- `external function` cannot be generic, async, or array-taking / array-returning
|
|
1009
|
+
- `external function` cannot take `ref[...]` or `proc(...)` parameters
|
|
1010
|
+
- `external function` parameters cannot use `as`, `in`, `out`, or `inout`
|
|
1011
|
+
- `foreign function` cannot be async and cannot take `proc(...)` parameters
|
|
1012
|
+
- a `foreign function` with `consuming` parameter(s) must return `void`
|
|
1013
|
+
- `consuming` foreign calls must appear as top-level expression statements
|
|
1014
|
+
- `external function` and `foreign function` cannot use a non-pointer value nullable (such as `int?`) as a parameter or return type; only pointer-like `T?` may cross an FFI boundary
|
|
1015
|
+
- `main` cannot be generic
|
|
1016
|
+
- `async main` pre-lift return type must be `int` or `void`
|
|
1017
|
+
- a function's return type cannot be `ref[T]` or a non-owning struct (contains `ref` via auto-generated lifetime)
|
|
1018
|
+
- `const function` bodies follow the same restrictions as block-bodied `const`
|
|
1019
|
+
|
|
1020
|
+
### Parameters and variables
|
|
1021
|
+
|
|
1022
|
+
- module variables must have an explicit type; initializer must be static-storage-safe
|
|
1023
|
+
- `ref[T]` values are rejected in constants, module variables, and nested local storage such as arrays
|
|
1024
|
+
- `proc(...)` values that capture local state are rejected in constants and module variables; capture-free procs (body only references module-level functions, constants, and types) are allowed in module variables
|
|
1025
|
+
- `ref[T]` values are not capturable by `proc`
|
|
1026
|
+
- stored callable values (`fn(...)`, `proc(...)`) may use `ref[...]` only in direct callable parameter positions, not in return types
|
|
1027
|
+
- bare interface names are not runtime storage types; use `dyn[Interface]`
|
|
1028
|
+
|
|
1029
|
+
### Event restrictions
|
|
1030
|
+
|
|
1031
|
+
- `event` declarations are not allowed in external files
|
|
1032
|
+
- event payload cannot be `ref[T]` in v1; the payload type must be storable
|
|
1033
|
+
- event payload cannot use event storage types or unsupported proc nesting
|
|
1034
|
+
- event storage types cannot be returned from functions or passed through non-pointer/non-ref parameters; locals cannot copy event storage
|
|
1035
|
+
- `emit` is only callable from within the declaring module
|
|
1036
|
+
- event methods (`subscribe`, `subscribe_once`, `unsubscribe`, `emit`, `wait`) do not support named arguments
|
|
1037
|
+
|
|
1038
|
+
### Pointer and unsafe requirements
|
|
1039
|
+
|
|
1040
|
+
- pointer indexing, raw pointer dereference, pointer arithmetic, and pointer casts require `unsafe`
|
|
1041
|
+
- `reinterpret[T]` requires `unsafe` and non-array concrete sized types
|
|
1042
|
+
- `ptr_of`, `const_ptr_of`, and `ref_of` require an addressable source expression
|
|
1043
|
+
- safe array indexing requires an addressable array value; `get(arr, i)` provides recoverable bounds-checked access
|
|
1044
|
+
- legacy call-site markers `in`, `out`, and `inout` are rejected; parameter modes are declared on `foreign function`
|
|
1045
|
+
- `ptr_of` / `ref_of` cannot target a `ref` value directly
|
|
1046
|
+
- pointer comparison is not treated as boolean truthiness
|
|
1047
|
+
|
|
1048
|
+
### Type system restrictions
|
|
1049
|
+
|
|
1050
|
+
- conditions must be `bool`; integers and pointers have no implicit truthy or falsy coercion
|
|
1051
|
+
- mixed signed and unsigned integer arithmetic requires an explicit cast
|
|
1052
|
+
- non-widening integer conversions (narrowing, signed → unsigned) require an explicit `T<-value` cast; lossless widening is implicit
|
|
1053
|
+
- enum and flags values do not implicitly coerce to their backing integer types outside external-call boundaries
|
|
1054
|
+
- `enum` backing types must be integer primitives; `flags` members must be compile-time integer constants
|
|
1055
|
+
- `variant` arm payloads cannot use `ref[T]` in v1
|
|
1056
|
+
- struct field `ref[T]` auto-generates an implicit lifetime parameter; the struct becomes non-owning
|
|
1057
|
+
- `null` must be used instead of `zero[ptr[T]]` in typed nullable pointer-like contexts
|
|
1058
|
+
- bare interface names (`Damageable`) are not a valid field, local, parameter, or return type; use `dyn[Interface]`
|
|
1059
|
+
- `dyn[Interface]` for a generic interface must be fully specified: `dyn[Mapper[int]]`, not `dyn[Mapper]`
|
|
1060
|
+
|
|
1061
|
+
### Interface restrictions
|
|
1062
|
+
|
|
1063
|
+
- interface method signatures cannot be `async` or generic
|
|
1064
|
+
- interface conformance must be declared on the nominal type, not on an `extending` block
|
|
1065
|
+
- a type implementing an interface must match method kinds, receiver editability, parameter types, return type, and asyncness exactly
|
|
1066
|
+
|
|
1067
|
+
### Operator and expression restrictions
|
|
1068
|
+
|
|
1069
|
+
- `+` does not support `str`/`cstr` concatenation; use format strings or `std.str` helpers
|
|
1070
|
+
- `==` and `!=` are not supported on struct types; use `equal[T]`. Variant types support `==`/`!=` (generates per-variant comparison helper).
|
|
1071
|
+
- range expressions are restricted to `for`-loop iterables and range-index assignment targets
|
|
1072
|
+
- functions, methods, generic functions, and variant arms must be called — they are not usable as bare values
|
|
1073
|
+
- `read(...)` of a raw pointer requires `unsafe`
|
|
1074
|
+
|
|
1075
|
+
### Control flow restrictions
|
|
1076
|
+
|
|
1077
|
+
- `break` and `continue` must be inside loops
|
|
1078
|
+
- `return` is not allowed inside `defer` blocks
|
|
1079
|
+
- `match` on `enum`/`variant` must be exhaustive unless `_` is present; `match` on integer or `str` requires `_`
|
|
1080
|
+
- `let ... else:` and `var ... else:` require `T?`, `Option[T]`, or `Result[T, E]`; the `else` block must terminate control flow
|
|
1081
|
+
- `?` propagation is only allowed inside function and proc bodies, not in `defer` blocks
|
|
1082
|
+
- `await` is only allowed inside async functions
|
|
1083
|
+
|
|
1084
|
+
### Format string restrictions
|
|
1085
|
+
|
|
1086
|
+
- `:.N` precision is only valid on `float` and `double` interpolations
|
|
1087
|
+
- `:x`/`:X`, `:o`/`:O`, and `:b`/`:B` are only valid on integer primitives and integer-backed enums/flags
|
|
1088
|
+
|
|
1089
|
+
### External file restrictions
|
|
1090
|
+
|
|
1091
|
+
- external files cannot contain `attribute`, `event`, `var`, `variant`, `interface`, `extending`, `foreign function`, ordinary `function`, `async function`, or `static_assert` declarations
|
|
1092
|
+
- `public` is rejected in external files (declarations are implicitly exported)
|
|
1093
|
+
- `import` statements must appear before directives and declarations
|
|
1094
|
+
|
|
1095
|
+
### Attribute restrictions
|
|
1096
|
+
|
|
1097
|
+
- user-defined `attribute` declarations target `struct`, `field`, `callable`, `const`, `event`, `enum`, `flags`, `union`, or `variant`
|
|
1098
|
+
- `@[...]` attribute applications are only accepted on the above declaration kinds
|
|
1099
|
+
- `attribute` declarations are not allowed in external files
|
|
1100
|
+
- only built-in `packed` and `align(...)` struct attributes are allowed in external files
|
|
1101
|
+
|
|
1102
|
+
### Concurrency restrictions
|
|
1103
|
+
|
|
1104
|
+
- `parallel for` only supports range iteration (`0..N`); collection iteration is not supported
|
|
1105
|
+
- `parallel for` and bodies reject `break`, `continue`, `return`, `defer`, and nested `parallel for`
|
|
1106
|
+
- `ref[T]` captures are rejected at thread boundaries in both `parallel for` and `parallel:` blocks
|
|
1107
|
+
- `parallel:` blocks enforce single-writer-or-multiple-readers: a variable written in one statement cannot be accessed by another
|
|
1108
|
+
- `atomic[T]` requires `T` to be a primitive integer type or `bool`
|
|
1109
|
+
- `atomic[T]` methods (`store`, `add`, `sub`, `exchange`) require an editable (mutable) receiver
|
|
1110
|
+
- `atomic[T].compare_exchange` is accepted by the type checker but not yet implemented in the lowering; use `std.sync.AtomicUint` for compare-exchange operations
|
|
1111
|
+
|
|
1112
|
+
## 17. CLI Commands
|
|
1113
|
+
|
|
1114
|
+
The `mtc` CLI is the primary tool for checking, building, and running Milk Tea programs.
|
|
1115
|
+
|
|
1116
|
+
Essential commands:
|
|
1117
|
+
|
|
1118
|
+
```
|
|
1119
|
+
mtc check <path> # Type-check + lint; reports all diagnostics sorted by line
|
|
1120
|
+
mtc build <path> # Build only (emit C, compile, link, --no-cache to build without cache)
|
|
1121
|
+
mtc run <path> # Build and execute (--no-cache to build and run without cache)
|
|
1122
|
+
mtc debug <file.mt> # Print debug info (tokens, AST, facts, bindings, diagnostics)
|
|
1123
|
+
mtc emit-c <path> # Emit generated C to stdout
|
|
1124
|
+
mtc format <path> # Format sources in place (--check for dry-run)
|
|
1125
|
+
mtc lint <path> # Run linter (--fix to apply fixes, --select/--ignore to filter)
|
|
1126
|
+
mtc test <path> # Discover and run @[test] functions (--timeout, --mem, --jobs)
|
|
1127
|
+
mtc new <name> # Scaffold a new package (package.toml + src/main.mt)
|
|
1128
|
+
mtc cache status # Show build cache stats
|
|
1129
|
+
mtc lex <file.mt> # Print lexer token stream
|
|
1130
|
+
mtc parse <path> # Print parsed AST
|
|
1131
|
+
mtc lower <path> # Print lowered IR
|
|
1132
|
+
```
|
|
1133
|
+
|
|
1134
|
+
Package management:
|
|
1135
|
+
|
|
1136
|
+
```
|
|
1137
|
+
mtc deps tree <path> # Print the dependency graph
|
|
1138
|
+
mtc deps lock <path> # Write/refresh package.lock
|
|
1139
|
+
mtc deps add <path> <name> # Add a dependency
|
|
1140
|
+
mtc deps remove <path> <name> # Remove a dependency
|
|
1141
|
+
mtc deps update <path> # Update dependencies
|
|
1142
|
+
mtc deps publish <path> # Publish a package to the local registry
|
|
1143
|
+
mtc deps fetch <path> # Materialize cache-backed sources
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
Run a pre-built module (no compilation):
|
|
1147
|
+
|
|
1148
|
+
```
|
|
1149
|
+
mtc run-module <module> # Run compiled module by name (e.g. std.fmt.bench)
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
Toolchain maintenance:
|
|
1153
|
+
|
|
1154
|
+
```
|
|
1155
|
+
mtc toolchain bootstrap # Bootstrap the native toolchain
|
|
1156
|
+
mtc toolchain doctor # Diagnose toolchain setup
|
|
1157
|
+
mtc toolchain tools # List available native tools
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
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).
|
|
1161
|
+
|
|
1162
|
+
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.
|
|
1163
|
+
|
|
1164
|
+
Diagnostic output uses standard compiler format (file:line:column with source context, error codes, and caret highlighting):
|
|
1165
|
+
|
|
1166
|
+
```
|
|
1167
|
+
[E0001] error: unknown type floa
|
|
1168
|
+
--> file.mt:1:16
|
|
1169
|
+
|
|
|
1170
|
+
1 | type Seconds = floa
|
|
1171
|
+
| ^~~~
|
|
1172
|
+
note: did you mean 'float'?
|
|
1173
|
+
|
|
1174
|
+
error: could not check due to 1 previous error
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
`mtc check` surfaces both errors and linter warnings:
|
|
1178
|
+
|
|
1179
|
+
| Severity | Label | Meaning |
|
|
1180
|
+
|---|---|---|
|
|
1181
|
+
| `error:` | red | semantic errors, linter errors |
|
|
1182
|
+
| `warning:` | yellow | linter warnings (dead-assignment, etc.) |
|
|
1183
|
+
| `hint:` | cyan | style suggestions (prefer-let, etc.) |
|
|
1184
|
+
|
|
1185
|
+
Exit code is 0 on success, 1 when errors are present (warnings/hints alone do not fail).
|
|
1186
|
+
|
|
1187
|
+
## 18. Minimal Example
|
|
1188
|
+
|
|
1189
|
+
```mt
|
|
1190
|
+
struct Counter:
|
|
1191
|
+
value: int
|
|
1192
|
+
|
|
1193
|
+
extending Counter:
|
|
1194
|
+
editable function bump() -> void:
|
|
1195
|
+
this.value += 1
|
|
1196
|
+
|
|
1197
|
+
function read() -> int:
|
|
1198
|
+
return this.value
|
|
1199
|
+
|
|
1200
|
+
function main() -> int:
|
|
1201
|
+
var c = Counter(value = 0)
|
|
1202
|
+
|
|
1203
|
+
for i in 0..3:
|
|
1204
|
+
c.bump()
|
|
1205
|
+
|
|
1206
|
+
let text = f"count=#{c.read()}"
|
|
1207
|
+
return 0
|
|
1208
|
+
```
|