Skip to content
Ridgun
English

Ridgun

The language itself: a compiler that compiles itself, the stable project tool, the specification and the book

02-getting-started-and-tooling.md212 lines · 10.8 KBRaw
1# Chapter 02: Your Two Best Friends: `ridgunc` and `stable` (Zero YAML Files, Promised)
2
3Some languages have a wonderful compiler, but a project tooling ecosystem that feels like it was designed by your worst enemy: a 400-line `Makefile` with invisible tabs, an endless `pom.xml`, or a `webpack.config.js` that stops working if you look at it funny...
4
5In Ridgun we made ourselves a very simple promise on day one:
6
7> *"There will be only two executables in the entire ecosystem (`ridgunc` and `stable`), both will be written in Ridgun itself, and the project configuration file (`build.rg`) will be ordinary Ridgun code. No JSON, no YAML, no TOML, no weird inventions."*
8
9Let's see how to use them.
10
11---
12
13## 2.1. `ridgunc`: The Sniper for Standalone Files
14
15When you have a single `.rg` file in front of you and want to test a quick idea, check its types, or compile an executable, you talk directly to **`ridgunc`**.
16
17It only has 4 commands you actually need to remember:
18
19```bash
20# 1. "Does this compile, or did I mess up a type?"
21ridgunc check experiment.rg
22
23# 2. "Run it now!" (Compiles and runs in one go)
24ridgunc run experiment.rg
25
26# 3. "Build me a standalone native ELF binary to go"
27ridgunc build experiment.rg -o my_program
28
29# 4. "Emit the intermediate bytecode artifact (.rgc)"
30ridgunc compile experiment.rg -o experiment.rgc
31```
32
33### The Hidden Superpower of `ridgunc check`
34When you run `ridgunc check`, it doesn't just tell you *"0 errors"*. It also reveals which execution strategy the static analyzer chose for each of your functions:
35- **`InlineSequential`**: *"This function is small and direct; I'll run it inline with zero scheduling overhead"*.
36- **`LazyStealableTask`**: *"There is recursion or a parallel `||` graph here; I'll set it up so other CPU cores can steal work if needed"*.
37
38### The Scalpel Inside `ridgunc build` (Why Your Binaries Don't Weigh 20 MB)
39When you run `ridgunc build`, the compiler doesn't just dump all the code from every library you imported:
401. It starts at your `main` function and walks the call graph to see **which functions you actually use**. If you imported a massive 80-function library but only call 2 of them, the other 78 are discarded before ever touching the assembler (*Tree-Shaking*).
412. It finds every tail-recursive function and turns it into a native `loop` that consumes **0 bytes of stack**.
423. It runs the final link pass with full link-time optimization (*fat LTO*) and strips DWARF debug bloat to leave you with a compact, razor-sharp binary (~350 KB).
43
44---
45
46## 2.2. `stable`: When Your Project Grows and You Want Order
47
48A standalone file is great for a script, but the moment you have multiple modules, shared libraries, and test suites, you need an orchestra conductor. That conductor is **`stable`**.
49
50The directory layout of a Ridgun project is completely straightforward:
51
52```text
53my-super-tool/
54├── build.rg # The project manifest (it's Ridgun code!)
55├── src/
56│ ├── main/
57│ │ └── ridgun/
58│ │ ├── lib/ # Your reusable modules (`import utils`)
59│ │ └── app/
60│ │ └── main.rg # Entry point (`main => ()`)
61│ └── test/
62│ └── ridgun/ # Your test suites (`test *.rg`)
63│ └── test all.rg
64└── target/ # Where compiled binaries appear
65```
66
67---
68
69## 2.3. `build.rg`: A Configuration File That Will Never Lie to You
70
71Why did we refuse to use YAML or TOML to configure a Ridgun project?
72Because in YAML you misalign two spaces of indentation and don't find out until deployment fails. By contrast, since **`build.rg` is a Ridgun file**, it has static types, gets verified by `stable check`, and formats itself with `stable format`:
73
74```ridgun
75fn :: project name => String
76 project name = "my-super-tool"
77
78fn :: project version => String
79 project version = "0.1.0"
80
81-- "exe" (executable), "lib" (.rglib + .so library), or "both"
82fn :: project kind => String
83 project kind = "both"
84
85fn :: main entry => String
86 main entry = "src/main/ridgun/app/main.rg"
87
88fn :: source dir => String
89 source dir = "src/main/ridgun"
90
91fn :: test dir => String
92 test dir = "src/test/ridgun"
93
94fn :: target dir => String
95 target dir = "target"
96
97fn :: dependencies => [String]
98 dependencies = []
99
100fn :: plugins => [String]
101 plugins = []
102
103fn :: task check all => String
104 task check all = "./bin/stable check && ./bin/stable test"
105```
106
107If you mistype a field or return type, the compiler tells you immediately. Notice how all setting functions use **natural spaces** (`project name`, `project kind`, `source dir`, `task check all`) instead of underscores.
108
109---
110
111## 2.4. Your Daily Routine with `stable` (The Fantastic Four)
112
113When working inside your project, your day-to-day workflow boils down to four commands:
114
115### 1. `stable format` — The End of Team Style Wars
116```bash
117stable format
118```
119Your teammate puts three spaces before `=>` and you put one? Doesn't matter. Run `stable format` and in under a second it leaves **every** `.rg` file in the repository aligned like a Swiss watch.
120
121### 2. `stable check` — Instant Radar
122```bash
123stable check
124```
125Walks every module in `src/main/ridgun/`, verifies types, constructors, arities, and tensor dimensions, and gives you a module-by-module verdict.
126
127### 3. `stable test` — Sleep Soundly at Night
128```bash
129stable test
130```
131Finds all `src/test/ridgun/test *.rg` suites, executes them, and verifies every `assert equals` and `assert true`.
132
133```ridgun
134-- Example of src/test/ridgun/test math.rg
135import test
136
137double Int => Int
138double x = x * 2
139
140main => ()
141main =
142 assert equals (double 21) 42
143 assert true ((double 5) > 0)
144```
145
146### 4. `stable built` (and `stable clean`) — Ready for Production
147```bash
148stable built
149```
150Compiles all native targets into `target/`. And if you ever want to wipe `target/` and start fresh: `stable clean`.
151
152---
153
154## 2.5. Building and Using Reusable Libraries (`.rglib` & ELF64 `.so`) and `stable` Plugins
155
156A library module does not need `main => ()`: it exports `type`, `expand type`, `fn ::`, and `op ::` declarations for other projects to import.
157
158### 1. Creating a Library Project with `stable`
159```bash
160stable new --lib geometry
161cd geometry
162stable built lib
163```
164When compiling in library mode (`project kind = "lib"` or `stable built lib`), the compiler disables `main`-rooted dead-code elimination so **all** exported functions and types are preserved, producing two artifacts in `target/`:
165- **`target/geometry.rglib`**: a self-contained Ridgun library bundle ready to be imported from any project via `import geometry` or `import "target/geometry.rglib"`.
166- **`target/libgeometry.so`**: a native Linux ELF64 shared object (`ET_DYN`, for `x86_64` or `arm64-linux`).
167
168```ridgun
169-- src/main/ridgun/lib/geometry.rg (No main function required!)
170type Point = x: Int, y: Int
171
172fn :: shift point Point Int Int => Point
173 shift point p dx dy = Point ((x p) + dx) ((y p) + dy)
174
175fn :: point coords Point => Int Int
176 point coords p = (x p, y p)
177```
178
179### 2. How Do I Import a Module or Library? (`import`)
180
181Without horrific relative paths like `../../../lib/stuff.rg`. If you have a module at `src/main/ridgun/lib/geometry.rg` or a `geometry.rglib` package (in `target/`, `lib/`, or `.stable/deps/` after `stable deps`), write at the top of any file:
182
183```ridgun
184import geometry
185```
186
187All functions, operators, and types from `geometry` become available immediately, and Ridgun's canonical loader guarantees each library is included **only once** even across diamond imports.
188
189### 3. Extending `stable` with Custom Tasks (`fn :: task`) and Plugins (`plugins/*.rg`)
190- **In `build.rg`**: declare any `fn :: task <words...> => String` (e.g., `fn :: task serve web => String`) and run it via `stable serve web`.
191- **In `plugins/*.rg` or `.stable/plugins/*.rg`**: drop `.rg` plugin modules that contribute `fn :: task ...` commands or their own `fn :: main => ()` entrypoint, or extend `expand type StableCommand`. Inspect active extensions anytime with `stable tasks` and `stable plugins`.
192
193### 4. Opt-in Strict Mode (`--strict` and `strict mode = True`)
194By default, neither `ridgunc` nor new projects scaffolded with `stable new` or `stable init` enable strict mode. However, when you want to enforce 100% canonical space-separated Ridgun style across a project, pass `--strict` to `ridgunc` (`ridgunc check --strict`, `ridgunc build --strict`) or set `fn :: strict mode => Bool` (`strict mode = True`) in `build.rg`. Strict mode rejects with a **compilation error**:
1951. Any underscore `_` inside a `fn ::` or `op ::` declaration name (write `fn :: compute total`, never `fn :: compute_total`; local variable names and record field names may still use `_`).
1962. Any parenthesized or comma-separated multi-value return type after `=>` (write `=> Int Int` or `=> RToken [RToken]`, never `=> (Int, Int)`).
197
198---
199
200## 2.6. The Standard and Cryptographic Library Ecosystem (`ridgun-libs`)
201
202Ridgun ships with an official suite of **32 pure-Ridgun libraries** (`ridgun-libs`), compiled as `.rglib` bundles and ELF64 `.so` shared libraries ready to import via `import <name>`:
203
204| Family | Libraries (`import ...`) | What They Provide |
205|---|---|---|
206| **1. Text, Formats & Templates** | `str`, `fmt`, `regex`, `diff`, `template`, `json`, `csv`, `ini`, `codec` | String processing, tabular formatting, Thompson NFA regular expressions (`regex`), Myers diff (`diff`), logic-less templates (`template`), `json`/`csv`/`ini` parsers and serializers, and hex/Base64 encoding (`codec`). |
207| **2. Collections, Math & Tensor Algebra** | `list`, `btree`, `math`, `tensor`, `linalg` | Functional list algorithms, ordered in-memory B-trees (`btree`), numerical routines (`math`), typed tensor views/builders (`tensor`), and linear algebra decompositions (`linalg`). |
208| **3. OS, Filesystem & CLI** | `posix`, `io`, `path`, `glob`, `cli`, `time`, `log`, `uuid`, `test` | POSIX descriptors and signals (`posix`), deadline-aware I/O (`io`), path/glob matching (`path`, `glob`), typed CLI flags (`cli`), monotonic clocks (`time`), structured logging (`log`), RFC 4122 `uuid`, and test assertions (`test`). |
209| **4. Cryptography & Security** | `crypto`, `argon2id`, `jwt` | Raw 32-byte binary SHA-256 (`sha256 raw` / `sha256 bytes`), HMAC-SHA-256, PBKDF2-HMAC-SHA-256, HKDF, ChaCha20-Poly1305 AEAD (`crypto`), RFC 9106 `argon2id` password hashing over `Tensor[U64 * 8 * 16]` with zero-allocation BlaMka permutations (`argon2id`), and signed tokens (`jwt`). |
210| **5. Networking, Protocols & Agents** | `socket`, `http`, `ws`, `agent`, `pool`, `net_agent` | POSIX TCP/UDP sockets (`socket`), HTTP/1.1 client/server (`http`), RFC 6455 WebSockets (`ws`), agent supervisors (`agent`), worker pools (`pool`), and reactive agent-driven network servers (`net_agent`). |
211
212Now that you have the toolbox and libraries under control, let's move on to **Chapter 03** to master functions, types, blocks, and string tricks.