The Loup Books
Loup — the Language of Unusual Portability | Power — is one strongly typed language for quick scripts, programs compiled to native code or WebAssembly, and bare-metal firmware. The language is the same everywhere; what changes from one environment to the next is the mode a file declares, which decides the features it may use, how it is compiled, and how it starts.
There are four books, one for each family of modes. Each is self-contained, practical and example-first. This edition describes Loup 1.25.1: every runnable example was checked with that toolchain, and features the specification describes but the toolchain does not implement yet are marked ⚠ Planned.
The books are also published at https://code-craft.ai/references/loup, where every page is available as Markdown by adding .md to its address.
The four books
| Book | Modes (@mode(...)) |
Files | Build and run | Status in 1.25.1 |
|---|---|---|---|---|
| The Loup Scripting Book | host.scripted |
.lpscr |
loup run tool.lpscr |
Works on Linux, macOS and Windows |
| The Loup Native Book | host.native, host.dual |
.lphc, .loup |
loup build --target native |
Native builds on Linux x86-64; macOS is a preview; loup run everywhere |
| The Loup Web Book | web.compiled, web.scripted |
.lpweb |
loup-bootstrap build --target browser |
The language works; the browser runtime is ⚠ planned |
| The Loup Freestanding Book | freestanding |
.lpfree |
loup build --target freestanding --arch … |
Builds on Linux with ld.lld; QEMU-verified on x86_64, aarch64, riscv64, armv7 and Cortex-M |
Every source file declares its mode on its first line (ruling MODE-2), and the file extension follows the mode (ruling MODE-3):
@mode(host.scripted)
let name = "world"
println(i"hello, {$ name $}")
The v1.16 names @mode(scripted), @mode(compiled) and @mode(native) were retired in v1.17. The compiler does not reject them — it quietly treats the file as a script — so if a program's main() never seems to run, check the mode line first.
Which book should you read?
Start with the book that matches what you are building. If you are new to Loup, start with The Loup Scripting Book: scripts need no project and no build step, so you can try every language feature with loup run. Its later chapters show when to turn a script into a host.dual program with a main(), which is where the Native Book picks up.
The books cross-reference each other where a concept differs between modes.
How the modes differ
| Feature | Scripting | Native and dual | Web | Freestanding |
|---|---|---|---|---|
| Memory model | ARC semantics | ARC | ARC semantics | No runtime: compile-time ownership only |
Ownership verbs (reads / edits / takes / shares) |
✓ | ✓ | ✓ | ✓ |
modifier methods and safe { } |
✓ | ✓ | ✓ | ✓ |
unique let |
✓ | ✓ | ✓ | ✓ |
unique class |
✗ | host.native only |
✗ | ✓ |
throw / try / catch |
✓ | ✓ | ✓ | ✗ — attempt with catch Err(e) |
Growable collections (list, dict) |
✓ | ✓ | ✓ | ✗ — fixed buffer[T, N] |
async / await |
✓ (runs eagerly)¹ | Interpreter only; native builds refuse it | ✓ on Wasm | ✗ |
Template fences (html, css, sql) |
✓ | Interpreter only; not in native builds | ✓ | ✗ |
asm { } |
✗ | host.native only |
✗ | ✓ |
@entry, @interrupt, @naked, Volatile[T] |
✗ | ✗ | ✗ | ✓ |
arc let, reactive UI, DOM, core.reflect |
⚠ Planned | ⚠ Planned | ⚠ Planned | ✗ |
¹ The interpreter runs an async func to completion when it is called; a real scheduler is planned.
Memory safety. Every mode presents ARC semantics: classes are reference-counted, and structs, enums, tuples and collections are copied. There is no garbage collector in any mode. The ownership verbs say what a function may do with each argument, and the compiler checks them in every mode. Freestanding has no runtime at all, so it relies entirely on these compile-time checks.
Reading the examples
The books teach the way The Rust Programming Language does: they show working code, then the mistake you would naturally make, the toolchain's actual message, and the fix. Problem code is always labelled:
| Label on the website | Fence in the Markdown | Meaning |
|---|---|---|
| This code does not compile | ```loup,does_not_compile |
The compiler rejects it; the block after it shows the diagnostic |
| This code throws at run time | ```loup,throws |
It compiles, then stops with an uncaught exception |
| This code panics | ```loup,panics |
It compiles, then panics |
| This code does not do what it should | ```loup,not_desired_behavior |
It runs, with a bug the text explains |
| Fragment — not a complete program | ```loup,ignore |
A sketch, or a ⚠ Planned feature |
Unlabelled ```loup listings compile and run. Some listings need a line of setup that would distract from the point — an import, a main() wrapper. Those lines start with #~ in the Markdown, are hidden on the website, and are still compiled when the examples are checked. Since # starts a comment in Loup, a #~ line is harmless if you copy it.
Diagnostics are shown the way loup run prints them:
main.lpscr:3:4: error[E0001]: E_CONDITION_PARENS: the condition of `if` must be in parentheses; add them: `if (...) {`
Installing Loup
Official builds are published for Linux (x86-64, arm64), macOS (Apple silicon, Intel) and Windows (x86-64).
# Linux and macOS
curl -fsSL https://github.com/code-craft-ai-company/loup-releases/releases/latest/download/loup-install.sh | sh
# Windows (PowerShell)
irm https://github.com/code-craft-ai-company/loup-releases/releases/latest/download/loup-install.ps1 | iex
The installer puts the toolchain in ~/.loup (or %LOCALAPPDATA%\Programs\Loup) and adds its bin directory to your PATH; no administrator rights are needed. To install a particular version, pass --version 1.25.1 (sh -s -- --version 1.25.1) or set LOUP_VERSION.
On Linux x86-64, loup is the self-hosted toolchain. On macOS, Windows and Linux arm64, loup is the bootstrap compiler, loup-bootstrap; the two accept the same commands for everything in these books, and the books note the few differences.
Running the examples
loup run hello.lpscr # run a script — no project, no build step
loup-bootstrap init demo # create a project: demo/demo.lppkg, demo/src/main.loup
loup-bootstrap check # type-check the project in the current directory
loup build --target native -o app # native binary (Linux x86-64; macOS preview)
loup-bootstrap build --target browser # WebAssembly for the browser (bare .wasm today)
loup build --target freestanding --arch x86_64 # bare-metal image (Linux, needs ld.lld)
loup test # run *_test.lpscr / *_test.loup files
The language reference
The books are guides, not the specification. The normative reference is the four-volume Loup Language Reference in specs/, cited in the books as §V-N.M — volume 1 core, 2 runtime, 3 compilation, 4 data:
- Core —
loup-language-core-v1_20.md: syntax, types, modes (§1-2), the feature matrix (§1-2.6), modules and packages (§1-13). - Runtime —
loup-language-runtime-v1_20.md: concurrency, shared memory, FFI, UI. - Compilation —
loup-language-compilation-v1_20.md: Wasm, native, ownership (§3-2.4), freestanding (§3-3), hardware back ends. - Data —
loup-language-data-v1_20.md: serialization and interchange.
The volumes keep their v1_20 file names but are amended in place as the language changes; rulings made since are cited by name (MODE-3, RESWORD-1, PANIC-1, …). The companion references are the Standard Library Reference (§21.1–§21.27), the Packages Reference, and the Testing Reference (a draft that describes more than ships). What actually ships in the standard library is tracked in docs/stdlib-status.md.
When a book and the reference disagree about the design, the reference wins. When a book shows code, that code was checked against the toolchain.
Checking the examples
tools/verify-listings.py checks every Loup listing in the books against its label: plain listings must compile and run, does_not_compile listings must be rejected, and throws listings must fail at run time. Run it after editing a chapter:
cd loup-books
python3 tools/verify-listings.py --loup "$(command -v loup)" --only-failures loup-scripting/*.md
Each listing runs under its own @mode(...): hosted and web listings with loup run, freestanding listings with loup check in a throwaway project.