Ridgun
The language itself: a compiler that compiles itself, the stable project tool, the specification and the book
| 1 | # Chapter 01: Your First Contact with Ridgun (No Boilerplate, No Braces, No Semicolons) |
| 2 | |
| 3 | Alright, Chapter 00 convinced you that we weren't crazy for creating Ridgun. Right now you're probably thinking: |
| 4 | |
| 5 | > *"Nice speech about tables and 16 cores, but show me real code. How long does it take to write something that actually works without fighting the compiler?"* |
| 6 | |
| 7 | Let's get right to it! |
| 8 | |
| 9 | --- |
| 10 | |
| 11 | ## 1.1. "Hello, World!", But with Teeth |
| 12 | |
| 13 | Most programming books show you a bland `print("Hello world")` and turn the page. We are going to jump straight into a function with real logic so you can see how Ridgun breathes from minute one. |
| 14 | |
| 15 | Create a file named `hello.rg` and write this: |
| 16 | |
| 17 | ```ridgun |
| 18 | greet String => String |
| 19 | greet "" = "Hello, mysterious traveler! (You didn't tell me your name)" |
| 20 | greet "Root" = "Hey there, Root! Careful what you delete today." |
| 21 | greet name = "Hello, {name}! Welcome to Ridgun." |
| 22 | |
| 23 | main => () |
| 24 | main = |
| 25 | echo (greet "Ada") |
| 26 | echo (greet "Root") |
| 27 | echo (greet "") |
| 28 | ``` |
| 29 | |
| 30 | To run it right now: |
| 31 | |
| 32 | ```bash |
| 33 | ridgunc run hello.rg |
| 34 | ``` |
| 35 | |
| 36 | And you will see in your terminal: |
| 37 | |
| 38 | ```text |
| 39 | Hello, Ada! Welcome to Ridgun. |
| 40 | Hey there, Root! Careful what you delete today. |
| 41 | Hello, mysterious traveler! (You didn't tell me your name) |
| 42 | ``` |
| 43 | |
| 44 | Pause for a moment and look at the `greet` block above. Notice what is **NOT** there? |
| 45 | - **No `function`, `def`, or `pub fn`** (you can put `fn ::` before the signature if you like, but it's optional). |
| 46 | - **No parentheses `(String name)` or curly braces `{ ... }`** cluttering the screen. |
| 47 | - **No `if (name == "") ... else if (name == "Root") ... else ...`**. |
| 48 | - **No `return`**. |
| 49 | |
| 50 | --- |
| 51 | |
| 52 | ## 1.2. How Your Brain Reads an `.rg` File |
| 53 | |
| 54 | Let's dissect those four lines of `greet`, because 50% of Ridgun's philosophy is already right here: |
| 55 | |
| 56 | ```ridgun |
| 57 | greet String => String |
| 58 | greet "" = "Hello, mysterious traveler! (You didn't tell me your name)" |
| 59 | greet "Root" = "Hey there, Root! Careful what you delete today." |
| 60 | greet name = "Hello, {name}! Welcome to Ridgun." |
| 61 | ``` |
| 62 | |
| 63 | 1. **The first line is the contract (`greet String => String`)**: |
| 64 | It says: *"My name is `greet`, I take a `String`, and I give you back (`=>`) another `String`"*. Period. If someone tries to call me with the number `42`, the compiler will tap them on the shoulder before the program even runs. |
| 65 | 2. **The lines below are the cases (top to bottom)**: |
| 66 | - Did you pass me the empty string `""`? I return the first sentence. |
| 67 | - Did you pass me the exact string `"Root"`? I return the second sentence. |
| 68 | - Did you pass me anything else? I bind it to the variable `name` and interpolate it directly into the string using `{name}`. |
| 69 | 3. **And what is `main => ()`?**: |
| 70 | Since `main` takes no arguments, we place `=>` right after its name. And it returns `()` (the empty or *Unit* type), because its only job is to print things to the screen with `echo`. |
| 71 | |
| 72 | --- |
| 73 | |
| 74 | ## 1.3. "Wait... do I have to align those spaces by hand like a medieval scribe?" |
| 75 | |
| 76 | Not a chance! If you had to hit the spacebar counting columns by eye, you would quit Ridgun in ten minutes (and rightfully so). |
| 77 | |
| 78 | You type your code quickly, with just a single space between words: |
| 79 | |
| 80 | ```ridgun |
| 81 | greet String => String |
| 82 | greet "" = "Hello, mysterious traveler!" |
| 83 | greet name = "Hello, {name}!" |
| 84 | ``` |
| 85 | |
| 86 | And when you run **`stable format`** (or press `TAB` / save the file in Emacs with `ridgun-mode`), the canonical formatter places every parameter directly beneath its type and aligns every `=` with pinpoint precision. You write fast; the machine typesets the table. |
| 87 | |
| 88 | --- |
| 89 | |
| 90 | ## 1.4. From Quick Script to Battle-Ready Binary in One Command |
| 91 | |
| 92 | When you run `ridgunc run hello.rg`, you are compiling and launching the program on the fly. But imagine you've finished your tool and want to deploy it to a production server or share it with a teammate who doesn't have Ridgun installed. |
| 93 | |
| 94 | You run: |
| 95 | |
| 96 | ```bash |
| 97 | ridgunc build hello.rg -o hello |
| 98 | ``` |
| 99 | |
| 100 | And now you have `./hello`: a **native Linux x86_64 ELF executable**, lean, stripped of dead code (*Tree-Shaking*), built with full link-time optimization (*LTO*), and completely independent of any external interpreter. |
| 101 | |
| 102 | --- |
| 103 | |
| 104 | ## 1.5. The Honest Cheat Sheet: Where Does Every Idea in Ridgun Come From? |
| 105 | |
| 106 | Ridgun doesn't try to reinvent the flat tire; it unapologetically borrows the best ideas from four traditions: |
| 107 | |
| 108 | | From Whom | What Ridgun Borrows | What It Leaves Behind (For Your Sanity) | |
| 109 | |---|---|---| |
| 110 | | **Haskell / ML** | Pure functions, case-by-case *pattern matching*, algebraic data types (`Option`, `Result`), and polymorphism (`A`..`Z`). | Abstract monad transformers, 40 `LANGUAGE` pragmas, and the garbage collector. | |
| 111 | | **J / APL** | Obsession with tabular code layout, native tensors, and sequence masks (`s(_ + _)`). | Hieroglyphic symbols that are impossible to type on a normal keyboard. | |
| 112 | | **Rust / C** | Tiny native ELF binaries, zero GC, deterministic memory control (`with region`), and POSIX system calls. | Constant battles with the *borrow checker*, `'a` *lifetimes*, and syntactic verbosity. | |
| 113 | | **Erlang / Go** | Isolated agents (`agent`, `send ... to`, `receive from`) and channel-based concurrency (`new bounded channel`). | `nil` pointers and accidental shared mutable state. | |
| 114 | |
| 115 | --- |
| 116 | |
| 117 | ## 1.6. Most Importantly: What Does Ridgun Do That Nobody Else Has? |
| 118 | |
| 119 | Giving credit to the classics is good manners, but if Ridgun were just a "greatest hits album" of other languages, you wouldn't be reading this book. |
| 120 | |
| 121 | There are **eight things** we designed and integrated into Ridgun that you won't find together—and many of them not even separately—in any other language today: |
| 122 | |
| 123 | ### 1. Parallel `||` blocks with `->` that are true parallel graphs, not mere syntactic sugar |
| 124 | In other functional languages, a local binding block merely orders expressions that are then evaluated on a single thread. |
| 125 | In Ridgun, **a `||` block with `->` arrows is a parallel-execution Directed Acyclic Graph (DAG)** without even needing extra keywords like `where`: |
| 126 | ```ridgun |
| 127 | annual report Int => Int |
| 128 | annual report id = revenue - expenses |
| 129 | || compute sales id -> revenue |
| 130 | || compute costs id -> expenses |
| 131 | ``` |
| 132 | You draw the dataflow arrows (`->`). The compiler analyzes what depends on what, **statically verifies that you haven't created any infinite dependency cycles**, and launches independent branches in parallel without you writing a single `async`, `await`, `Future`, or `Mutex`. |
| 133 | |
| 134 | ### 2. Zero-friction Native Agent Model (`agent`) with smart compile-time thread selection |
| 135 | In other languages, programming with actors or agents forces you to define special classes, implement traits, juggle locks, or infect your functions with `async`. |
| 136 | In Ridgun, **any ordinary pure function (`fn ::` or `op ::`) turns directly into an autonomous agent—stateless or with isolated state—using `agent`**: |
| 137 | ```ridgun |
| 138 | serve http (Session, String) => (Session, String) |
| 139 | ... |
| 140 | server = agent serve http initial_session |
| 141 | send "GET /profile" to server |
| 142 | reply = receive from server |
| 143 | stop server |
| 144 | ``` |
| 145 | Better yet: the compiler **statically analyzes function call depth and computational cost at compile time** across `agent`, `||`, and `||map`. If a function is lightweight, it executes as an instant *green-thread* step without paying OS thread warmup overhead; if it is a heavy or deeply recursive computation, it is automatically dispatched in parallel across real OS kernel threads (`SYS_clone`) over your CPU cores. |
| 146 | |
| 147 | ### 3. Code as a two-dimensional table where the signature is the column header |
| 148 | In every other language, the type signature lives on its own line and the function body sits below it like an ordinary paragraph of text. |
| 149 | In Ridgun, **the type signature is literally the header of a table**, and every clause below aligns each pattern vertically under its type and each `=` under the `=>`: |
| 150 | ```ridgun |
| 151 | divide Int Int => Option |
| 152 | divide _ 0 = None |
| 153 | divide a b = Some (a / b) |
| 154 | ``` |
| 155 | No other language treats the signature and its equations as a single visual matrix verified by the compiler and automatically typeset by `stable format`. |
| 156 | |
| 157 | ### 4. Typed and aligned N-ary phrase operators (*Mixfix* `op ::`) |
| 158 | In most languages, you either settle for `+`, `-`, `*` or at best define a cryptic binary operator like `<|>` that nobody can read. |
| 159 | In Ridgun you can create **operators that read like natural phrases with as many typed slots as you want** (even using contextual words like `type` or `with`): |
| 160 | ```ridgun |
| 161 | op :: Int clamped between Int and Int => Int |
| 162 | x clamped between min and max = |
| 163 | | x < min = min |
| 164 | | x > max = max |
| 165 | | otherwise = x |
| 166 | ``` |
| 167 | And then in your code you write `speed clamped between 0 and 120`. It reads like plain English, yet it is 100% statically typed and compiled to native machine code. |
| 168 | |
| 169 | ### 5. Visual sequence masks (`s(_ + _)` and `-> (+ _ _ +) ->`) |
| 170 | Have you ever had to write an index salad like `filter(\(i, x) -> i % 2 == 0)` or unpack a tuple with dummy variables just to keep two specific positions? |
| 171 | In Ridgun you pass a **visual mask** directly: |
| 172 | - `data(_ + _)`: drops the first (`_`), keeps the second (`+`), drops the third (`_`). |
| 173 | - `parse packet "v0.9.9" -> (+ _ _ +) -> combine code -> summary`: filters a 4-element tuple right inside a pipeline and unpacks the 1st and 4th elements directly into the next function. |
| 174 | Zero index arithmetic, zero *off-by-one* bugs. |
| 175 | |
| 176 | ### 6. "Zero-noise" polymorphism (`A`..`Z`) governed by your domain |
| 177 | In Rust, TypeScript, or Java, making a function generic means littering the line with angle brackets: `fn swap<A, B>(pair: (A, B)) -> (B, A)`. |
| 178 | In Ridgun you simply use a standalone uppercase letter: |
| 179 | ```ridgun |
| 180 | swap (A, B) => (B, A) |
| 181 | swap (x, y) = (y, x) |
| 182 | ``` |
| 183 | *"What if I want a real type in my program called `type A`?"* — No problem: in Ridgun **your `type` declarations win**. If `type A` does not exist, `A` is a generic type variable; the instant you define `type A = ...`, it becomes your concrete type across the module. |
| 184 | |
| 185 | ### 7. Zero foreign configuration files: `build.rg` is pure Ridgun |
| 186 | Forget learning TOML for Cargo, JSON for npm, XML for Maven, or the arcane tab-sensitive syntax of a `Makefile`. In Ridgun, the recipe that builds your project (`build.rg`) **is just another `.rg` file**, using the exact same pure functions and *pattern matching* as the rest of your code. |
| 187 | |
| 188 | ### 8. The "Holy Trinity" that seemed impossible: Haskell-level expressiveness + RMM memory without GC or Lifetimes + ~350 KB binaries |
| 189 | Until today you had to choose: |
| 190 | - If you wanted pure functional expressiveness (Haskell, OCaml, Elixir), you paid for it with a garbage collector and a heavy runtime. |
| 191 | - If you wanted tiny GC-free systems binaries (C, Rust, Zig), you paid for it by juggling raw pointers or wrestling with the *borrow checker* while writing imperative code full of `let mut`. |
| 192 | |
| 193 | Ridgun breaks that dilemma by combining **Ridgun Memory Management (`RMM`: static `RMM1` and cascading assignment-counted `RMM2`)**, **lexical regions (`with region`)** that free entire arenas in $O(1)$, **tail recursion compiled into native `loop`s**, and **call-graph dead-code elimination (*Tree-Shaking*)** starting from `main`. The result: you write high-level declarative code and get a self-contained **~350 KB** ELF executable ready to go toe-to-toe with tools written in C. |
| 194 | |
| 195 | Now that all cards are on the table, let's head to **Chapter 02** and put **`ridgunc`** and **`stable`** to work. |