# Mapanare v0.3.0 — Complete Documentation > Mapanare is the first AI-native compiled programming language. Agents, signals, streams, and tensors are built-in language primitives — not libraries. Compiles to Python or native binaries via LLVM. Website: https://mapanare.dev GitHub: https://github.com/Mapanare-Research/Mapanare Discord: https://discord.gg/5hpGBm3WXf License: MIT Author: Juan Denis — https://juandenis.com File Extension: .mn --- ## Table of Contents 1. Overview 2. Getting Started 3. Variables & Mutability 4. Functions & Lambdas 5. Control Flow 6. Structs & Enums 7. Type System 8. Error Handling 9. Operators 10. Modules & Imports 11. Traits 12. Decorators 13. Agents 14. Signals 15. Streams 16. Tensors 17. Pipes 18. CLI Reference 19. Standard Library 20. Benchmarks 21. Design Principles --- # 1. Overview Mapanare is a compiled programming language where agents, signals, streams, and tensors are first-class language primitives — not libraries. It's designed for a world where AI writes and orchestrates code, not just humans. The language compiles two ways: to readable Python (accessing the full Python ecosystem) or to native binaries via LLVM for production performance up to 63x faster than Python. No OOP. No classes. No inheritance. Mapanare uses structs, enums, and pattern matching — algebraic data types that AI models generate more reliably. ### Hello, Mapanare ```mn // hello.mn print("Hello, Mapanare!") ``` Top-level statements are automatically wrapped in a main function by the compiler. ### Design Principles 1. **AI-native primitives** — agents, signals, streams, tensors are language constructs 2. **Always compiled** — transpiler to Python, LLVM for native 3. **Familiar syntax** — draws from Rust, TypeScript, and Python 4. **Type-safe with inference** — types where they clarify, inference elsewhere 5. **No OOP** — structs, enums, and pattern matching instead 6. **Concurrency via agents** — no raw threads, no shared mutable state --- # 2. Getting Started ### Installation **pip (all platforms)** ```bash pip install mapanare ``` **Linux / macOS** ```bash curl -fsSL https://mapanare.dev/install | bash ``` **Windows (PowerShell)** ```powershell irm https://mapanare.dev/install.ps1 | iex ``` ### Your First Program Create a file called `hello.mn`: ```mn // hello.mn fn main() { print("Hello, Mapanare!") } ``` Run it: ```bash mapanare run hello.mn ``` ### Your First Agent Agents are concurrent actors with typed input/output channels: ```mn // greeter.mn agent Greeter { input name: String output greeting: String fn handle(name: String) -> String { return "Hello, " + name + "!" } } fn main() { let greeter = spawn Greeter() greeter.name <- "World" let result = sync greeter.greeting print(result) // Hello, World! } ``` Key concepts: - `agent` defines a concurrent actor - `spawn` creates an instance - `<-` sends a message - `sync` waits for output ### Compilation Modes **Python Transpiler** — Emits readable Python. Access the entire Python ecosystem. ```bash mapanare compile hello.mn ``` **LLVM Native** — Compiles to native binaries via LLVM IR. Up to 63x faster than Python. ```bash mapanare build hello.mn ``` ### Editor Support Install the official VS Code extension for syntax highlighting, snippets, and full LSP support (hover, go-to-definition, diagnostics, autocomplete). Search for `mapanare` in the VS Code Extensions marketplace. ### Project Structure ```bash mapanare init my-project ``` Creates: ``` my_project/ mapanare.toml # project config & dependencies src/ main.mn # entry point tests/ test_utils.mn ``` --- # 3. Variables & Mutability ### Let Bindings Variables are declared with `let` and are immutable by default. The type is inferred from the right-hand side when not annotated. ```mn let x = 42 // inferred as Int let name = "Mapanare" // inferred as String let pi: Float = 3.14159 // explicitly annotated ``` ### Mutability Add `mut` to allow reassignment. Immutable is the default to encourage safer, more predictable code. ```mn let mut count = 0 count = count + 1 count += 10 let frozen = 100 // frozen = 200 // compile error: cannot assign to immutable variable ``` ### Type Inference The compiler infers types from literals, function return types, and expressions. You only need explicit annotations on function parameters and return types. ```mn let a = 42 // Int let b = 3.14 // Float let c = true // Bool let d = 'x' // Char let e = "hello" // String let f = [1, 2, 3] // List let g: Option = none // annotation needed (none is ambiguous) ``` ### Compound Assignment | Operator | Equivalent | |----------|-----------| | `x += y` | `x = x + y` | | `x -= y` | `x = x - y` | | `x *= y` | `x = x * y` | | `x /= y` | `x = x / y` | ### Numeric Literals Integers support multiple bases and underscores as visual separators: ```mn let decimal = 1_000_000 let hex = 0xFF let binary = 0b1010_0101 let octal = 0o777 let sci = 1.5e10 ``` --- # 4. Functions & Lambdas ### Function Definitions Functions are declared with `fn`. Parameter types and the return type are always annotated. If the return type is omitted, it defaults to `Void`. ```mn fn greet(name: String) { print("Hello, " + name) } fn add(a: Int, b: Int) -> Int { return a + b } ``` ### Visibility Functions are private by default. Use `pub` to make them accessible from other modules: ```mn pub fn public_api(x: Int) -> Int { return helper(x) + 1 } fn helper(x: Int) -> Int { return x * 2 } ``` ### Generic Functions Type parameters are declared in angle brackets after the function name. The compiler infers type arguments at call sites. ```mn fn identity(x: T) -> T { return x } fn first(a: A, b: B) -> A { return a } let n = identity(42) // T = Int let s = identity("hello") // T = String let r = first(1, "two") // A = Int, B = String ``` ### Trait Bounds on Functions Constrain type parameters with trait bounds to require specific capabilities: ```mn fn max(a: T, b: T) -> T { if a.cmp(b) > 0 { return a } return b } fn print_all(items: List) { for item in items { println(item.to_string()) } } ``` ### Lambda Expressions Lambdas use the `=>` arrow syntax. They are first-class values that can be passed to other functions. ```mn // Single parameter let double = x => x * 2 // Multiple parameters (parenthesized) let add = (a, b) => a + b // Block body let clamp = (x, lo, hi) => { if x < lo { return lo } if x > hi { return hi } return x } // Passing lambdas to higher-order functions let nums = [1, 2, 3, 4, 5] let evens = nums |> filter(x => x % 2 == 0) let doubled = nums |> map(x => x * 2) ``` ### Function Types Functions can be passed as values. The type syntax is `fn(Params) -> Return`: ```mn fn apply(f: fn(Int) -> Int, x: Int) -> Int { return f(x) } let result = apply(x => x * 3, 10) // 30 type Predicate = fn(Int) -> Bool ``` ### Implicit Main Top-level statements are allowed without wrapping them in `fn main()`. The compiler synthesizes a main function automatically: ```mn // This is a complete program — no fn main() needed let name = "world" print("Hello, " + name) ``` You cannot mix top-level statements with an explicit `fn main()` — the compiler will emit an error if both are present. --- # 5. Control Flow ### If / Else No parentheses around the condition, braces are required. ```mn if x > 0 { print("positive") } else if x == 0 { print("zero") } else { print("negative") } ``` ### For Loops Iterate over ranges or any iterable with `for` / `in`: ```mn // Exclusive range: 0, 1, 2, 3, 4 for i in 0..5 { print(i) } // Inclusive range: 1, 2, 3, 4, 5 for i in 1..=5 { print(i) } // Iterate over a list let names = ["Alice", "Bob", "Carol"] for name in names { print("Hello, " + name) } ``` ### Ranges | Syntax | Name | Values | |--------|------|--------| | `a..b` | Exclusive | a, a+1, ..., b-1 | | `a..=b` | Inclusive | a, a+1, ..., b | ### Match Expressions Pattern matching with exhaustiveness checking: ```mn enum Color { Red, Green, Blue, Custom(Int, Int, Int), } fn describe(c: Color) -> String { match c { Red => "red", Green => "green", Blue => "blue", Custom(r,g,b) => "custom color", } } ``` ### Match with Blocks ```mn fn handle(result: Result) -> Int { match result { Ok(value) => value, Err(msg) => { print("Error: " + msg) return -1 }, } } ``` ### Wildcard Pattern Use `_` to match any value without binding it: ```mn match status_code { 200 => "OK", 404 => "Not Found", 500 => "Internal Error", _ => "Unknown", } ``` --- # 6. Structs & Enums ### Structs Structs are product types with named fields. No inheritance, no constructors with side effects. ```mn struct Point { x: Float, y: Float, } struct User { name: String, age: Int, active: Bool, } ``` ### Impl Blocks Methods are defined in separate `impl` blocks. Use `self` to access the instance: ```mn impl Point { fn distance(self, other: Point) -> Float { let dx = self.x - other.x let dy = self.y - other.y return Math::sqrt(dx * dx + dy * dy) } fn origin() -> Point { return Point(0.0, 0.0) } } ``` Functions without `self` are static methods, called via `Point::origin()`. ### Generic Structs ```mn struct Pair { first: A, second: B, } struct Stack { items: List, size: Int, } ``` ### Enums Enums are sum types (algebraic data types). Each variant can carry associated data: ```mn enum Shape { Circle(Float), Rectangle(Float, Float), Triangle(Float, Float, Float), } enum Token { Number(Int), Word(String), Comma, EOF, } ``` ### Pattern Matching on Enums The compiler checks that all variants are covered: ```mn fn area(shape: Shape) -> Float { match shape { Circle(r) => 3.14159 * r * r, Rectangle(w, h) => w * h, Triangle(a, b, c) => { let s = (a + b + c) / 2.0 return Math::sqrt(s * (s - a) * (s - b) * (s - c)) }, } } ``` ### Generic Enums The built-in `Option` and `Result` types are generic enums: ```mn // Built-in definitions (you don't write these) enum Option { Some(T), None, } enum Result { Ok(T), Err(E), } // Usage fn find(items: List, target: Int) -> Option { for i in 0..len(items) { if items[i] == target { return Some(i) } } return none } ``` ### Visibility Structs and enums can be marked `pub` to export them from their module: ```mn pub struct Config { verbose: Bool, output: String, } pub enum LogLevel { Debug, Info, Warn, Error, } ``` --- # 7. Type System ### Static Typing with Inference Mapanare is statically typed — every expression has a known type at compile time. Local type inference reduces annotation burden. ```mn let x = 42 // inferred as Int let y = 3.14 // inferred as Float let z: String = "hello" // explicitly annotated let flag = true // inferred as Bool ``` ### Primitive Types | Type | Description | |------|-------------| | `Int` | 64-bit signed integer | | `Float` | 64-bit IEEE 754 floating-point | | `Bool` | Boolean — true or false | | `String` | Immutable UTF-8 encoded string | | `Char` | Single Unicode scalar value | | `Void` | Unit type — absence of a value | | `Option` | Some(value) or None | | `Result` | Ok(value) or Err(error) | | `Tensor[shape]` | N-dimensional array, compile-time shape | | `List` | Dynamically-sized ordered collection | | `Map` | Hash map from K to V | | `Signal` | Reactive container | | `Stream` | Async iterable with backpressure | | `Channel` | Typed inter-agent message channel | ### Function Signatures Type annotations are required on function parameters and return types: ```mn fn add(a: Int, b: Int) -> Int { return a + b } ``` ### Generics ```mn fn identity(x: T) -> T { return x } let a = identity(42) // T = Int let b = identity("hello") // T = String struct Pair { first: A, second: B, } ``` ### Trait Bounds Constrain generic type parameters with trait bounds. The compiler verifies that concrete types at call sites implement the required trait: ```mn fn max(a: T, b: T) -> T { if a.cmp(b) > 0 { return a } return b } fn print_all(items: List) { for item in items { println(item.to_string()) } } ``` See section 11 (Traits) for full details on defining and implementing traits. ### Option & Result ```mn // Option — no null pointers let x: Option = Some(42) let y: Option = none match x { Some(v) => print("Got: ${v}"), None => print("Nothing"), } // Result — recoverable errors fn divide(a: Float, b: Float) -> Result { if b == 0.0 { return Err("division by zero") } return Ok(a / b) } // ? operator for error propagation let value = divide(10.0, 3.0)? ``` ### Type Aliases ```mn type Name = String type Matrix = Tensor[3, 3] type Callback = fn(Int) -> Bool ``` --- # 8. Error Handling ### No Exceptions, No Null Mapanare has no exceptions, no try/catch, and no null pointers. Errors are values — represented by `Result` for operations that can fail, and `Option` for values that may be absent. ### Result Type ```mn fn divide(a: Float, b: Float) -> Result { if b == 0.0 { return Err("division by zero") } return Ok(a / b) } fn parse_int(s: String) -> Result { // ... return Ok(42) } ``` ### The ? Operator The `?` operator unwraps a `Result` or `Option` — if it's an error/none, it returns early from the current function: ```mn fn compute(input: String) -> Result { let n = parse_int(input)? // returns Err early if parsing fails let result = divide(n, 3.0)? // returns Err early if division fails return Ok(result) } ``` ### Option Type Use `Option` when a value might not exist. This replaces null/nil: ```mn fn find_user(id: Int) -> Option { if id == 1 { return Some("Alice") } return none } let user = find_user(1) match user { Some(name) => print("Found: " + name), None => print("User not found"), } ``` ### Matching on Results ```mn let result = divide(10.0, 0.0) match result { Ok(value) => print("Result: " + value), Err(msg) => print("Error: " + msg), } ``` --- # 9. Operators ### Arithmetic | Operator | Name | Example | |----------|------|---------| | `+` | Add | `a + b` | | `-` | Subtract | `a - b` | | `*` | Multiply | `a * b` | | `/` | Divide | `a / b` | | `%` | Modulo | `a % b` | | `@` | Matrix multiply | `a @ b` | | `-x` | Negate | `-value` | ### Comparison | Operator | Meaning | |----------|---------| | `==` | Equal | | `!=` | Not equal | | `<` | Less than | | `>` | Greater than | | `<=` | Less or equal | | `>=` | Greater or equal | ### Logical | Operator | Meaning | |----------|---------| | `&&` | Logical AND (short-circuit) | | `\|\|` | Logical OR (short-circuit) | | `!` | Logical NOT | ### Pipe Operator The `|>` operator passes the left-hand value as the first argument to the right-hand function: ```mn let result = data |> filter(x => x > 0) |> map(x => x * 2) |> fold(0, (acc, x) => acc + x) ``` ### Send Operator The `<-` operator sends a message to an agent's input channel: ```mn let counter = spawn Counter() counter.input <- 5 // non-blocking send ``` ### Error Propagation The postfix `?` unwraps a `Result` or `Option`, returning early on error: ```mn let value = parse_input(raw)? // early return on Err/None ``` ### Namespace Access The `::` operator accesses static methods and module members: ```mn let root = Math::sqrt(2.0) let pi = Math::pi() ``` ### Precedence (lowest to highest) | Level | Operators | |-------|-----------| | 1 (lowest) | `=>` (lambda) | | 2 | `= += -= *= /= <-` (assignment, send) | | 3 | `\|\|` (logical or) | | 4 | `&&` (logical and) | | 5 | `== !=` (equality) | | 6 | `< > <= >=` (comparison) | | 7 | `\|>` (pipe) | | 8 | `.. ..=` (range) | | 9 | `+ -` (additive) | | 10 | `* / % @` (multiplicative, matmul) | | 11 | `- !` (unary prefix) | | 12 (highest) | `. () [] ?` (postfix) | --- # 10. Modules & Imports ### Imports ```mn // Import an entire module import std::math // Import specific items import std::io { read_file, write_file } // Import from nested modules import std::http::client { get, post } // Import a local module (sibling file) import helpers // Import from nested directory import utils::validators ``` ### File-Based Resolution Module paths map to files on disk. The `::` separator maps to directory separators: | Import | Resolves to | |--------|-------------| | `import math` | `math.mn` (sibling file) | | `import utils::helpers` | `utils/helpers.mn` | | `import utils::helpers` | `utils/helpers/mod.mn` (directory module) | Each module is parsed and type-checked at most once — the compiler caches resolved modules. ### Circular Import Detection The compiler detects circular imports and produces a clear error: ``` error: circular import detected: a.mn -> b.mn -> a.mn ``` ### Transitive Imports If module A imports B, and B imports C, A sees B's public symbols but NOT C's. Re-export explicitly: ```mn // In module B — re-export selected names from C export { name1, name2 } ``` ### Exports ```mn // Export a function definition directly export fn process(data: List) -> List { return data |> map(x => x * 2) } // Export an agent export agent Worker { input task: String output result: String fn handle(task: String) -> String { return "done: " + task } } // Export names defined elsewhere export process, Worker ``` ### Visibility with pub The `pub` keyword marks definitions as public. Without it, items are private to their file: ```mn pub fn api_function() -> String { return helper() } fn helper() -> String { // private — only visible in this file return "internal" } pub struct Config { verbose: Bool, output: String, } ``` ### Standard Library Modules | Module | Contents | |--------|----------| | `std::math` | sqrt, pow, abs, clamp, trig, statistics | | `std::io` | File I/O, stdin/stdout, reader/writer agents | | `std::http` | HTTP client/server agents, get/post helpers | | `std::time` | Timers, intervals, delay, stopwatch | | `std::text` | Case conversion, trim, split, join, search | | `std::log` | Structured logging with agent context | ### Project Structure ``` my_project/ mapanare.toml # project config & dependencies src/ main.mn # entry point utils.mn # local module tests/ test_utils.mn ``` --- # 11. Traits ### Overview Traits define shared behavior that types can implement. They enable bounded generics — write a function once that works for any type satisfying a contract. No classes, no inheritance, no virtual dispatch. ### Defining a Trait ```mn trait Display { fn to_string(self) -> String } trait Ord { fn cmp(self, other: Self) -> Int } trait Eq { fn eq(self, other: Self) -> Bool } trait Hash { fn hash(self) -> Int } ``` - `self` is the receiver (the implementing type) - `Self` in parameter/return positions refers to the implementing type - Traits can be `pub` for cross-module visibility ### Implementing a Trait ```mn struct Point { x: Float, y: Float, } impl Display for Point { fn to_string(self) -> String { return str(self.x) + ", " + str(self.y) } } impl Eq for Point { fn eq(self, other: Point) -> Bool { return self.x == other.x && self.y == other.y } } ``` All methods declared in the trait must be implemented. Missing or extra methods produce compile errors. ### Trait Bounds on Generics ```mn fn max(a: T, b: T) -> T { if a.cmp(b) > 0 { return a } return b } fn print_all(items: List) { for item in items { println(item.to_string()) } } ``` ### Builtin Traits | Trait | Method | Purpose | |-------|--------|---------| | `Display` | `to_string(self) -> String` | Human-readable string | | `Eq` | `eq(self, other: Self) -> Bool` | Equality comparison | | `Ord` | `cmp(self, other: Self) -> Int` | Ordering (-1, 0, 1) | | `Hash` | `hash(self) -> Int` | Hash value for maps/sets | ### Traits vs Impl Blocks Inherent `impl` blocks and trait implementations coexist: ```mn // Inherent methods — belong to Vector impl Vector { fn length(self) -> Float { return Math::sqrt(self.x * self.x + self.y * self.y) } } // Trait methods — satisfy Display contract impl Display for Vector { fn to_string(self) -> String { return "(" + str(self.x) + ", " + str(self.y) + ")" } } ``` ### Code Generation - **Python backend:** Traits emit as `typing.Protocol` classes. Duck typing handles dispatch. - **LLVM backend:** Monomorphization. Generic functions with trait bounds are specialized per concrete type — no vtable indirection. ### Future Planned: default method implementations, trait inheritance (supertraits), multiple bounds with `+`, associated types, `dyn Trait` for dynamic dispatch. --- # 12. Decorators ### Overview Decorators attach metadata and behavior to functions, agents, structs, and enums. They use the `@name` syntax and can accept arguments. ### Syntax ```mn // Without arguments @decorator_name fn my_function() { } // With arguments @decorator_name(arg1, arg2) fn my_function() { } // Multiple decorators @gpu @inline fn compute(data: Tensor[1024]) -> Tensor[1024] { return data * 2.0 } ``` ### GPU / CPU Dispatch Annotate functions for device-specific execution. The compiler selects the appropriate backend (CUDA, Metal, or Vulkan) at compile time: ```mn @gpu fn matrix_multiply(a: Tensor[M, K], b: Tensor[K, N]) -> Tensor[M, N] { return a @ b } @cpu fn fallback_multiply(a: Tensor[M, K], b: Tensor[K, N]) -> Tensor[M, N] { return a @ b } ``` ### Agent Restart Policies ```mn let worker = spawn DataProcessor() @restart(policy: "always", max: 3, window: 60) ``` | Parameter | Description | |-----------|-------------| | `policy` | "always", "never", or "transient" | | `max` | Maximum restart attempts within the window | | `window` | Time window in seconds for counting restarts | ### Decorated Definitions ```mn @serializable struct Config { host: String, port: Int, } @deprecated("use ProcessorV2 instead") agent OldProcessor { input data: String output result: String fn handle(data: String) -> String { return data } } ``` --- # 13. Agents ### Overview Agents are concurrent actors that encapsulate state and communicate exclusively through typed message channels. There is no shared mutable state between agents. They run independently, and the compiler understands their lifecycle, channel types, and message flow. ### Defining an Agent ```mn agent Counter { input increment: Int output count: Int let mut state: Int = 0 fn handle(increment: Int) -> Int { self.state += increment return self.state } fn on_init() { } fn on_stop() { } } ``` - `input` and `output` declare typed channels - `handle` is called when input arrives - `on_init` and `on_stop` are optional lifecycle hooks ### Spawning and Communication ```mn fn main() { let counter = spawn Counter() counter.increment <- 5 // send (non-blocking) let result = sync counter.count // receive (blocking) print(result) // 5 } ``` - `spawn` creates and starts an agent instance - `<-` sends a message to an input channel (non-blocking, queued) - `sync` blocks until the agent produces output ### Lifecycle ``` init -> running -> paused -> stopped ``` | State | Description | |-------|-------------| | `init` | Agent created. on_init() called. Resources allocated. | | `running` | Processing messages from input channels. | | `paused` | Temporarily suspended. Messages buffered. | | `stopped` | Terminated. on_stop() called. Resources released. | ### Native LLVM Backend When compiled to native code via LLVM, agents run as real OS threads with high-performance message passing: - **OS threads:** One thread per agent instance, managed by a thread pool - **Lock-free queues:** SPSC ring buffers for message channels — no mutex contention - **Semaphore scheduling:** Agents sleep on semaphores instead of polling, for minimal CPU overhead - **Arena memory:** Function-scoped arena allocation eliminates memory leaks for temporaries The Python backend uses asyncio tasks for agent concurrency. ### Backpressure When an agent's input buffer reaches capacity, the sender is notified. Backpressure propagates through pipelines automatically. Strategies: blocking (default), dropping, or timeout with Result. ### Supervision ```mn let worker = spawn MyAgent() @restart(policy: "always", max: 3, window: 60) ``` | Policy | Behavior | |--------|----------| | `always` | Restart on any failure, up to max times within window seconds | | `never` | Stay stopped on failure | | `transient` | Restart only on unexpected failures | ### Multi-Agent Pipelines ```mn agent Tokenizer { input text: String output tokens: List fn handle(text: String) -> List { return text.split(" ") } } agent Classifier { input tokens: List output label: String fn handle(tokens: List) -> String { if tokens.len() > 10 { return "long" } return "short" } } pipe ClassifyText { Tokenizer |> Classifier } ``` --- # 14. Signals ### Overview Signals hold a value and automatically propagate changes to dependents. They enable declarative, reactive dataflow without manual event wiring — no React, no RxJS, no state management library. Reactivity is a language feature. ### Declaration ```mn // Mutable signal let mut count = signal(0) // Computed signal (derived, read-only) let doubled = computed { count * 2 } // Update count.set(5) print(doubled) // 10 ``` ### Dependency Tracking The compiler tracks which signals are read during computed signal evaluation. When any dependency changes, the computed signal recomputes. ```mn let mut a = signal(1) let mut b = signal(2) let sum = computed { a + b } a.set(10) print(sum) // 12 ``` ### Change Streams Every signal exposes a stream of its changes, bridging reactive and streaming models: ```mn let mut temperature = signal(20.0) for change in temperature.changes() { print("Temperature changed to ${change}") } ``` ### Batched Updates Multiple updates within a `batch` block coalesce into a single recomputation pass: ```mn batch { x.set(10) y.set(20) z.set(30) } // Dependents recompute once, not three times ``` ### Signals in Agents ```mn agent Thermometer { output temperature: Signal let mut temp = signal(20.0) fn handle(reading: Float) -> Signal { self.temp.set(reading) return self.temp } } ``` --- # 15. Streams ### Overview Streams are asynchronous iterables that produce values over time. The `|>` pipe operator chains transformations naturally, and the compiler automatically fuses adjacent operations into a single pass. ### Basic Usage ```mn let result = stream([1, 2, 3, 4, 5]) |> filter(fn(x) { x > 2 }) |> map(fn(x) { x * 10 }) |> fold(0, fn(acc, x) { acc + x }) ``` ### Stream Operators | Operator | Description | |----------|-------------| | `map(fn)` | Transform each element | | `filter(fn)` | Keep elements matching a predicate | | `flat_map(fn)` | Map then flatten | | `take(n)` | Emit only the first n elements | | `skip(n)` | Skip the first n elements | | `chunk(n)` | Group into chunks of size n | | `zip(other)` | Pair elements from two streams | | `merge(other)` | Interleave elements | | `fold(init, fn)` | Reduce to a single value | | `scan(init, fn)` | Emit each intermediate accumulator | | `distinct()` | Remove consecutive duplicates | | `throttle(ms)` | At most one element per time window | | `debounce(ms)` | Emit after a quiet period | ### Hot vs Cold Streams **Cold** — Values produced on demand. Each subscriber gets an independent sequence. **Hot** — Values produced continuously. Subscribers see values from the point they subscribe. ```mn // Cold stream let cold = stream([1, 2, 3]) // Hot stream let hot = Stream::interval(1000) // emits every 1000ms ``` ### Backpressure | Strategy | Behavior | |----------|----------| | `buffer(n)` | Buffer up to n elements, then apply backpressure | | `drop_oldest` | Drop the oldest buffered element when full | | `drop_newest` | Drop the incoming element when full | | `error` | Raise an error on buffer overflow | ### Stream Fusion The compiler fuses adjacent stream operators into a single pass, eliminating intermediate allocations: ```mn // These three operators fuse into a single iteration: let result = data |> filter(fn(x) { x > 0 }) |> map(fn(x) { x * 2 }) |> take(100) ``` ### Streams + Agents Agent output channels are streams — all stream operators work on agent outputs: ```mn let sensor = spawn TemperatureSensor() sensor.readings |> filter(fn(t) { t > 100.0 }) |> throttle(5000) |> map(fn(t) { "ALERT: ${t} degrees" }) |> for_each(fn(msg) { notify(msg) }) ``` --- # 16. Tensors ### Overview Tensors in Mapanare are first-class types with compile-time shape verification. The compiler rejects shape mismatches before your code ever runs. ### Declaration ```mn // 1D vector let v: Tensor[3] = [1.0, 2.0, 3.0] // 2D matrix let m: Tensor[2, 3] = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] // 3D tensor let t: Tensor[2, 2, 2] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] ``` ### Compile-Time Shape Checking Shape mismatches are compile-time errors: ```mn let a: Tensor[3] = [1.0, 2.0, 3.0] let b: Tensor[4] = [1.0, 2.0, 3.0, 4.0] let c = a + b // COMPILE ERROR: shape mismatch [3] vs [4] ``` ### Matrix Multiplication The `@` operator performs matrix multiplication with dimensional compatibility verified at compile time: ```mn let a: Tensor[3, 3] = identity(3) let b: Tensor[3, 4] = zeros(3, 4) let c = a @ b // Result: Tensor[3, 4] // Inner dimensions must match: [3, 3] @ [3, 4] -> [3, 4] ``` ### Built-in Operations ```mn let a: Tensor[3, 3] = identity(3) let b: Tensor[3, 3] = zeros(3, 3) // Arithmetic let sum = a + b let diff = a - b let product = a * b // element-wise let matmul = a @ b // matrix multiplication // Constructors let z = zeros(4, 4) // Tensor[4, 4] let o = ones(3, 3) // Tensor[3, 3] let id = identity(5) // Tensor[5, 5] ``` ### Why This Matters **Python (NumPy):** Shape errors throw at runtime. You find out dimensions don't match in production. **Mapanare:** Shape errors are caught at compile time. AI-generated code is correct by construction. --- # 17. Pipes ### Overview Pipes compose multiple agents into named pipelines using the `|>` operator. The compiler verifies that the output type of each stage matches the input type of the next. ### Defining a Pipe ```mn agent Tokenizer { input text: String output tokens: List fn handle(text: String) -> List { return text.split(" ") } } agent Counter { input tokens: List output count: Int fn handle(tokens: List) -> Int { return tokens.len() } } pipe WordCount { Tokenizer |> Counter } ``` The compiler checks that `Tokenizer`'s output (`List`) matches `Counter`'s input type. ### Using Pipes Spawn and communicate with a pipe the same way you would with a single agent: ```mn fn main() { let wc = spawn WordCount() wc.text <- "hello world from mapanare" let result = sync wc.count print(result) // 4 } ``` ### Multi-Stage Pipelines Chain as many agents as needed. Each stage runs concurrently: ```mn pipe NLPPipeline { Tokenizer |> Normalizer |> Embedder |> Classifier } ``` ### Visibility Pipes support `pub` for exporting across modules: ```mn pub pipe DataPipeline { Ingester |> Transformer |> Writer } ``` --- # 18. CLI Reference ### Commands | Command | Description | |---------|-------------| | `mapanare run ` | Compile and run | | `mapanare build ` | Compile to native binary via LLVM | | `mapanare jit ` | JIT-compile and run natively | | `mapanare check ` | Type-check only (no output) | | `mapanare compile ` | Transpile to Python | | `mapanare emit-llvm ` | Emit LLVM IR | | `mapanare fmt ` | Format source code | | `mapanare init [path]` | Initialize new project | | `mapanare install ` | Install package (git-based) | | `mapanare targets` | List supported compilation targets | ### Quick Start ```bash # Create a new project mapanare init my-project cd my-project # Run the default entry point mapanare run src/main.mn # Type-check without running mapanare check src/main.mn # Compile to native binary mapanare build src/main.mn # Transpile to Python mapanare compile src/main.mn ``` ### Optimization Levels | Level | Description | |-------|-------------| | `-O0` | No optimization. Fastest compilation, best for debugging. | | `-O1` | Basic optimizations. Constant folding, dead code elimination. | | `-O2` | Standard optimizations. Includes stream fusion and agent inlining. | | `-O3` | Aggressive optimizations. Maximum performance, longer compile times. | ```bash mapanare build -O3 src/main.mn ``` ### Compilation Targets The LLVM backend supports cross-compilation: ```bash mapanare targets # Cross-compile mapanare build --target x86_64-linux src/main.mn ``` ### Package Management Mapanare uses git-based package management: ```bash # Install a package mapanare install github.com/user/package ``` Packages are declared in `mapanare.toml`: ```toml [dependencies] my-lib = { git = "https://github.com/user/my-lib" } ``` --- # 19. Standard Library ### std::math ```mn import std::math let root = Math::sqrt(144.0) // 12.0 let clamped = Math::clamp(x, 0, 100) let power = Math::pow(2.0, 10.0) // 1024.0 let sine = Math::sin(Math::pi() / 2.0) ``` | Category | Functions | |----------|-----------| | Basic | abs, clamp, lerp, min, max | | Powers | sqrt, pow, log, log2, log10, exp | | Trig | sin, cos, tan, asin, acos, atan, atan2 | | Rounding | floor, ceil, round, trunc | | Statistics | sum, mean, median, variance, stddev, percentile | | Constants | pi(), e(), tau() | ### std::io ```mn import std::io { read_file, write_file } let content = read_file("data.txt")? write_file("output.txt", "processed: " + content)? // Agent-based I/O for streaming import std::io { FileReader, FileWriter } let reader = spawn FileReader("large_file.csv") let writer = spawn FileWriter("output.csv") ``` ### std::http ```mn import std::http { get, post } let response = get("https://api.example.com/data")? print(response.body) let result = post("https://api.example.com/submit", body)? ``` ### std::time ```mn import std::time { delay, stopwatch, interval } delay(1000) // sleep 1 second let sw = stopwatch() // ... some work ... let elapsed = sw.elapsed() // milliseconds // Periodic execution let tick = interval(5000) // every 5 seconds ``` ### std::text ```mn import std::text let upper = text::to_upper("hello") // "HELLO" let slug = text::slugify("Hello World!") // "hello-world" let parts = text::split("a,b,c", ",") // ["a", "b", "c"] let joined = text::join(parts, " | ") // "a | b | c" let trimmed = text::trim(" hello ") // "hello" ``` ### std::log ```mn import std::log log::info("server started", port: 8080) log::warn("high memory usage", percent: 92) log::error("connection failed", host: "db.local") ``` --- # 20. Benchmarks ### Execution Performance Cross-language benchmarks. Each benchmark runs 3 times; median wall time reported. The transpiler runs at Python-comparable speed; the LLVM backend delivers native performance. | Benchmark | Features Tested | MN (Transpile) | MN (Native) | Python | Go | Rust | vs Python | |-----------|-----------------|----------------|-------------|--------|----|------|-----------| | Fibonacci (recursive, n=35) | Functions, recursion, arithmetic | 1.2104s | 0.0448s | 1.1885s | 0.0341s | 0.0211s | 26.5x | | Message Passing (10K msgs) | Agents, spawn, send, sync | 0.9989s | — | 1.0978s | 0.0025s | 0.0203s | 1.1x | | Stream Pipeline (1M items) | Streams, .map(), .filter(), .fold() | 1.1141s | 0.0165s | 1.0342s | 0.0005s | 0.0001s | 62.8x | | Matrix Multiply (100x100) | Nested loops, arithmetic | 0.1769s | 0.0199s | 0.4556s | 0.0005s | 0.0009s | 22.9x | ### Stream Pipeline Microbenchmarks (1M items) | Pipeline | Throughput | Avg Latency | |----------|-----------|-------------| | fold_sum | 10.3M items/sec | 0.10 us | | take(1000) | 6.3M items/sec | 0.16 us | | filter | 4.2M items/sec | 0.24 us | | map | 4.2M items/sec | 0.24 us | | map | filter | 2.6M items/sec | 0.39 us | | chained_maps(5) | 1.7M items/sec | 0.60 us | | chained_maps(10) | 1.2M items/sec | 0.80 us | ### Code Expressiveness Lines of code per benchmark. Fewer lines means fewer tokens, more context window for AI, and less room for bugs. | Benchmark | Mapanare | Python | Go | Rust | |-----------|----------|--------|----|------| | Fibonacci (recursive, n=35) | 8 | 12 | 18 | 23 | | Message Passing (10K msgs) | 16 | 28 | 27 | 32 | | Stream Pipeline (1M items) | 8 | 17 | 18 | 20 | | Matrix Multiply (100x100) | 12 | 21 | 37 | 33 | | Agent Pipeline (1K msgs) | 18 | 32 | 33 | 28 | Mapanare programs are consistently the shortest across all benchmarks. --- # 21. Design Principles 1. **AI-native primitives** — Agents, signals, streams, and tensors are language constructs the compiler understands, optimizes, and type-checks. Not library calls. 2. **Always compiled** — Two targets: transpile to Python for ecosystem compatibility, or compile to native binaries via LLVM for production speed (22-63x faster than Python). 3. **Familiar syntax** — Draws from Rust (enums, match, ownership ideas), TypeScript (type annotations), and Python (readability). Minimal learning curve for experienced developers. 4. **Type-safe with inference** — Static types catch errors at compile time. Type inference reduces annotation burden. Types where they clarify, inference elsewhere. 5. **No OOP** — No classes, no inheritance, no virtual methods. Structs, enums, and pattern matching produce cleaner, more correct code — especially when AI generates it. Less ambiguity means less hallucination. 6. **Concurrency via agents** — No raw threads, no shared mutable state. Agents communicate through typed channels. The compiler verifies message flow. 7. **Error handling as values** — No exceptions, no null. `Result` and `Option` with the `?` operator for concise error propagation. 8. **Stream fusion** — Adjacent stream operations (map, filter, take) fuse into a single pass at compile time. Zero-overhead abstractions. 9. **Compile-time tensor shapes** — Tensor dimensions are part of the type system. Shape mismatches are caught before runtime. 10. **Declarative pipelines** — The `pipe` keyword composes agents into type-checked multi-stage pipelines. Data flow is verified by the compiler.