diff --git a/AGENTS.md b/AGENTS.md index b15bc60..f8484b8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,7 +55,7 @@ monad-rs run examples/hello.mo # Run with debug output cargo run -- run examples/hello.mo -- --debug -# Run @[test] annotated definitions +# Run #[test] annotated definitions cargo run -- test init/tests.mo # Run the bootstrapped cli in lang/main.mo @@ -428,32 +428,35 @@ infix:20 (++) := List.append ### Module Imports ```monad -// Load a module -use prelude -use io +// Load a module, listing exactly the names needed +use io {IO} // Open namespace. Make defs available without given prefix. -open IO +open IO {println} ``` +`{*}` imports/opens everything explicitly; a bare `use`/`open` (no braces) still parses but is deprecated in favor of an explicit filter. + ### Native Functions -Call Rust functions from Monad using the `@[native "..."]` attribute: +Call Rust functions from Monad using the `#[native "..."]` attribute: ```monad -@[native "add"] +#[native "add"] def add (a: I64) (b: I64) : I64 ``` ## Attributes -Declarations can be annotated with `@[...]` attributes: +Declarations can be annotated with `#[...]` attributes: ```monad -@[native "function_name"] // Declare a Rust-native function -@[test] // Mark as a test (run via `cargo run -- test `) +#[native "function_name"] // Declare a Rust-native function +#[test] // Mark as a test (run via `cargo run -- test `) ``` +`@[...]` is the older spelling of the same syntax — it still parses, but the compiler warns and suggests `#[...]` instead. + ## Operators All operators and their precedences: @@ -536,14 +539,14 @@ cargo test eval::test # Run tests from a single file cargo run -- test init/tests.mo -# Run tests from an entire directory (recursively finds all .mo files with @[test]) +# Run tests from an entire directory (recursively finds all .mo files with #[test]) cargo run -- test init/ # Run all test suites cargo run -- test init/ && cargo run -- test examples/ ``` -The test runner supports both files and directories. When given a directory, it recursively scans for `.mo` files and runs any definitions annotated with `@[test]`, reporting pass/fail. +The test runner supports both files and directories. When given a directory, it recursively scans for `.mo` files and runs any definitions annotated with `#[test]`, reporting pass/fail. ### Pre-commit @@ -581,7 +584,7 @@ type MyType { 1. Add Rust implementation in `core/src/eval/native.rs` 2. Declare in a `.mo` file: ```monad -@[native "function_name"] +#[native "function_name"] def function_name (args: Types) : ReturnType ``` @@ -945,7 +948,7 @@ scope builder (`module.rs`) is usually the culprit. 1. **Add a parser test** (`core/src/parser/test/`) if the bug involves syntax 2. **Add an eval test** (`core/src/eval/test.rs`) if the bug involves evaluation -3. **Add a Monad test** — use `@[test]` in: +3. **Add a Monad test** — use `#[test]` in: - `init/tests.mo` for bugs involving core language semantics (prelude types, operators, etc.) - `std/_test.mo` for bugs in `std/` modules (concurrency, collections, etc.) - Never add `std/`-dependent tests to `init/tests.mo` — `init/` must not depend on `std/` diff --git a/docs/src/error-handling.md b/docs/src/error-handling.md index 88ebb56..4f53462 100644 --- a/docs/src/error-handling.md +++ b/docs/src/error-handling.md @@ -103,8 +103,8 @@ def findUser (id : I64) : Result DatabaseError String := Error handling in effectful code: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := match List.first args { diff --git a/docs/src/getting-started.md b/docs/src/getting-started.md index faa1c51..eb505e9 100644 --- a/docs/src/getting-started.md +++ b/docs/src/getting-started.md @@ -13,8 +13,8 @@ Before getting started, ensure you have: Let's start with the classic "Hello, World!" program: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Hello, World!" ``` @@ -149,8 +149,8 @@ def greet (name : String) : IO Unit := println name Monad supports infix operators with defined precedence: ```monad -use init -use math +use init {} +use math {} def result : I64 := 3 + 4 * 2 // 11 (multiplication binds tighter) ``` diff --git a/docs/src/instances.md b/docs/src/instances.md index 08eb9c0..ee35ff3 100644 --- a/docs/src/instances.md +++ b/docs/src/instances.md @@ -72,8 +72,8 @@ Monad uses instance resolution to find matching instances: Once an instance is defined, its methods are available through the class: ```monad -use init -use math +use init {} +use math {} def result : I64 := 3 + 4 // Uses I64.add via Add instance ``` diff --git a/docs/src/introduction.md b/docs/src/introduction.md index 8aa6cde..ad06bdc 100644 --- a/docs/src/introduction.md +++ b/docs/src/introduction.md @@ -14,8 +14,8 @@ The Monad language is a dependently typed programming language with compatibilit Here is a simple example: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Hello, World!" ``` @@ -38,9 +38,9 @@ cargo run -- run hello.mo ## Quick Example ```monad -use io -use init -open IO +use io {IO} +use init {} +open IO {println} def factorial (n : I64) : I64 := if n == 0 diff --git a/docs/src/io-monad.md b/docs/src/io-monad.md index 252bf09..4ec6dff 100644 --- a/docs/src/io-monad.md +++ b/docs/src/io-monad.md @@ -7,8 +7,8 @@ Monad provides a safe way to perform side effects through the `IO` monad. `IO A` represents a computation that, when executed, produces an `A` and may have side effects: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Hello, World!" ``` @@ -18,8 +18,8 @@ def main (args : List String) : IO Unit := println "Hello, World!" ### Printing Output ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Hello, World!" @@ -56,8 +56,8 @@ The `do` block sequences IO actions. Two equivalent syntaxes are available: ### Standard `do { ... }` syntax ```monad -use io -open IO +use io {IO} +open IO {println} def greet : IO Unit := do { @@ -72,8 +72,8 @@ def greet : IO Unit := Functions can use `{ ... }` directly instead of `:= do { ... }`: ```monad -use io -open IO +use io {IO} +open IO {println} def greet : IO Unit { println "Enter your name:" @@ -110,19 +110,19 @@ def multiStep : IO Unit { IO operations are implemented as native functions that call Rust code: ```monad -@[native println] +#[native println] def IO.println (s : String) : IO Unit ``` -The `@[native name]` attribute marks a function as implemented in Rust. +The `#[native name]` attribute marks a function as implemented in Rust. ## Running IO Programs The runtime executes the `main` function: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Starting..." @@ -139,9 +139,9 @@ Command-line arguments are passed to `main` as `List String`. ## Combining IO with Other Types ```monad -use io -use init -open IO +use io {IO} +use init {} +open IO {println} def printResult (r : Result String I64) : IO Unit := match r { diff --git a/docs/src/modules.md b/docs/src/modules.md index f6df3e3..d96ecb5 100644 --- a/docs/src/modules.md +++ b/docs/src/modules.md @@ -8,44 +8,48 @@ Each `.mo` file is a module. The module name is derived from the file path. ## Importing Modules -Use `use` to bring a module into scope: +Use `use` to bring a module into scope, listing exactly the names you need in `{...}`: ```monad -use io -use init -use math +use io {IO} +use init {IO} +use math {} ``` -After `use io`, you can access definitions with their full path: +An empty `{}` still imports the module (for qualified access) without bringing any bare names into scope. + +After `use io {...}`, you can access definitions with their full path: ```monad -use io +use io {IO} def main (args : List String) : IO Unit := IO.println "Hello" ``` +Bare `use io` (no braces) still parses but is deprecated — the compiler warns and suggests `use io {*}`. + ## Opening Modules -Use `open` to make a module's definitions available without prefixes: +Use `open` to make a module's definitions available without prefixes, again naming exactly what you need: ```monad -use io -open IO +use io {IO} +open IO {println} def main (args : List String) : IO Unit := println "Hello" ``` -Now `println` is available directly instead of `IO.println`. +Now `println` is available directly instead of `IO.println`. Like `use`, a bare `open IO` (no braces) still parses but is deprecated in favor of an explicit filter — `open IO {*}` if you genuinely need everything. ## Opening Standard Types The prelude opens several types by default: ```monad -open Unit // makes `unit` available -open Bool // makes `true`, `false` available -open Result // makes `ok`, `err` available -open Option // makes `some`, `none` available +open Unit {unit} // makes `unit` available +open Bool {and, false, not, or, true} +open Result {err, ok} +open Option {none, some} ``` ## Module Paths @@ -53,7 +57,7 @@ open Option // makes `some`, `none` available Definitions are accessed using dot notation: ```monad -use init +use init {} def result : I64 := I64.add 3 4 ``` @@ -77,9 +81,9 @@ Monad ships with several standard modules: ## Complete Example ```monad -use io -use init -open IO +use io {IO} +use init {} +open IO {println} def say_hello (s : String) : IO Unit := println s @@ -90,11 +94,16 @@ def main (args : List String) : IO Unit := |> say_hello ``` +## Unused Imports + +The compiler warns when an explicitly-listed `use`/`open` name is never referenced in the file — remove it, or run `monad-rs organize-imports --write` to have the compiler rewrite (and, where a `use` contributes nothing at all, delete) the declaration for you. + ## Summary - Each `.mo` file is a module -- `use` brings modules into scope -- `open` makes definitions available without prefixes +- `use Module {names}` brings a module into scope, selecting exactly which names become bare-accessible +- `open Module {names}` makes definitions available without prefixes +- `{*}` imports/opens everything explicitly; bare `use`/`open` (no braces) still works but is deprecated - Dot notation accesses definitions by path - Standard library modules provide common functionality diff --git a/docs/src/reference.md b/docs/src/reference.md index bcadc7a..c498e23 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -157,29 +157,31 @@ def p := { x := 3, y := 4 } ## Attributes -Declarations can be annotated with `@[...]` attributes: +Declarations can be annotated with `#[...]` attributes: ```monad -@[native "function_name"] // Declare a Rust-native function -@[test] // Mark as a test (run via `cargo run -- test `) +#[native "function_name"] // Declare a Rust-native function +#[test] // Mark as a test (run via `cargo run -- test `) ``` +`@[...]` is the older spelling of the same syntax — it still parses, but the compiler warns and suggests `#[...]` instead. + ## Native Functions Mark functions as implemented in Rust: ```monad -@[native nativeName] +#[native nativeName] def functionName (params) : ReturnType ``` Example from the standard library: ```monad -@[native println] +#[native println] def IO.println (s : String) : IO Unit -@[native num_add] +#[native num_add] def I64.add (a b : I64) : I64 ``` @@ -297,23 +299,25 @@ def multiStep : IO Unit { } // Native function -@[native println] +#[native println] def IO.println (s : String) : IO Unit ``` ## Modules ```monad -// Import module -use io +// Import module, listing exactly the names needed +use io {IO} -// Open module (no prefix needed) -open IO +// Open module (no prefix needed), same explicit-names convention +open IO {println} -// Access by path +// Access by path — always works, whether or not a name is also open'd IO.println "hello" ``` +`{*}` imports/opens everything; a bare `use`/`open` with no braces at all still parses but is deprecated in favor of an explicit filter. + ## Dot Macro The `.` operator (`x.y.z`) is treated as a compile-time macro that concatenates module paths into a single variable reference. This is how module paths like `List.append` work. @@ -410,7 +414,7 @@ cargo run -- run file.mo # Run with debug output cargo run -- run file.mo -- --debug -# Run @[test] annotated definitions +# Run #[test] annotated definitions cargo run -- test file.mo # Compile to native binary (requires llvm feature)