The Loup Native Book — contents
  1. Chapter 1: Getting started
  2. Chapter 2: Native mode overview
  3. Chapter 3: Variables and numerics
  4. Chapter 4: Functions
  5. Chapter 5: Control flow
  6. Chapter 6: Collections
  7. Chapter 7: Structs
  8. Chapter 8: Enums and pattern matching
  9. Chapter 9: Classes and ARC
  10. Chapter 10: Interfaces
  11. Chapter 11: Generics
  12. Chapter 12: Error handling
  13. Chapter 13: Modules and packages
  14. Chapter 14: Template fences
  15. Chapter 15: Ownership verbs
  16. Chapter 16: borrow, excl borrow and noescape
  17. Chapter 17: unique ownership
  18. Chapter 18: Lifetimes and regions
  19. Chapter 19: @unsafe and calling C
  20. Chapter 20: Concurrency with OS threads
  21. Chapter 21: Async on native
  22. Chapter 22: Desktop UI
  23. Chapter 23: SIMD and GPU
  24. Chapter 24: Building and distributing
  25. Chapter 25: Memory safety patterns

The Loup Native Book

Writing Loup programs that compile to native executables. This edition describes Loup 1.25.1.


What this book covers

Native Loup is Loup compiled ahead of time to a platform executable: an ELF binary on Linux, a Mach-O binary on macOS. The program carries its runtime with it (reference counting, strings, collections, exceptions), so nothing else needs to be installed on the machine that runs it. Memory is managed by automatic reference counting rather than a garbage collector, and an ownership system checked at compile time (reads, edits, takes and shares parameters, modifier methods, safe blocks, unique values) says who may change what.

The book is for people writing command-line tools, services and systems code who want a statically typed language with predictable memory behaviour. It assumes you can program; it does not assume you know Loup.

Every runnable example in the book was checked with the Loup 1.25.1 toolchain. Where the Language Reference specifies something the toolchain does not do yet, the book says so and marks it ⚠ Planned, and where the toolchain behaves differently from the specification, the text states the actual behaviour.

The two native modes

Every Loup file declares its mode on its first line. This book uses two:

@mode(host.native)

func main(): void {
    println("hello, native world");
}
  • @mode(host.native), in .lphc files, is for code whose deliverable is a native binary. It allows the features that only make sense in machine code, such as unique class and inline asm { }.
  • @mode(host.dual), in .loup files, is for code that should also run on the interpreter (loup run) or as WebAssembly. Every host.dual file is also a valid host.native file.

Both start at main(), which takes no parameters and returns void or int; arguments come from runtime.args(). Statements outside functions are an error (E_TOPLEVEL_CONTROL_AOT). The names @mode(native) and @mode(compiled) from earlier editions were retired in v1.17; the compiler does not reject them, but silently treats the file as a script whose main() is never called. Chapter 2 explains the modes in full.

What works in Loup 1.25.1

Status
Native binaries on Linux x86-64 Supported (loup build --target native; needs clang)
Native binaries on macOS 11+ Preview: LLVM backend only; needs the Xcode Command Line Tools
Native binaries on Windows and Linux arm64 Not yet
loup run of host.native and host.dual files Every platform (the interpreter runs the program and calls main())
Native builds of async, template fences, for concurrent Refused with E-BUILD-NATIVE; they run under loup run and in WebAssembly
weak references in native binaries Accepted, but stored as strong references, so cycles leak
native.ffi, native.simd, native.gpu, ui.desktop, sync.* ⚠ Planned

Installing Loup

Official builds come from the code-craft-ai-company/loup-releases GitHub releases:

# 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. Pass --version 1.25.1 (sh -s -- --version 1.25.1) or set LOUP_VERSION to pin a version. Chapter 1 continues from there.

How to read the examples

Listings without a label compile and run; the output that follows them is what loup run printed. Listings that show a mistake are labelled, and the block after them is the toolchain's real message:

Label Meaning
This code does not compile The compiler rejects it; the diagnostic follows
This code throws at run time It compiles, then stops with an uncaught exception
This code does not do what it should It runs, with a bug the text explains
Fragment Not checked: a multi-file example run as a project, or a ⚠ planned feature

Some listings hide setup lines (an import, a main() wrapper) on the website; in the Markdown they start with #~. Diagnostics are shown as loup run prints them, with the file named main.lphc or main.loup.

loup run executes native-mode programs on an interpreter. A few runtime behaviours differ from a native binary today, notably integer overflow (chapter 3), when finalize() runs (chapter 9), and the format of an uncaught exception (chapter 12); the chapters point these out.

Reading order

Chapters 1 to 8 cover the setup and the core language: modes, numbers, functions, control flow, collections, structs and enums. Chapter 9 introduces classes and reference counting, and chapters 10 to 14 cover interfaces, generics, errors, modules and template fences. Chapters 15 to 18 are the ownership chapters and build on each other: read them in order. Chapters 19 to 25 cover interop, concurrency, the planned UI and SIMD/GPU support, building and distribution, and a summary of memory-safety patterns.

If you already know Loup scripts, skim chapters 1 to 8 (chapter 3 on overflow is worth reading), then read from chapter 9 on.

Contents

  1. Getting started
  2. Native mode overview
  3. Variables and numerics
  4. Functions
  5. Control flow
  6. Collections
  7. Structs
  8. Enums and pattern matching
  9. Classes and ARC
  10. Interfaces
  11. Generics
  12. Error handling
  13. Modules and packages
  14. Template fences
  15. Ownership verbs
  16. borrow and noescape
  17. unique ownership
  18. Lifetimes and regions
  19. @unsafe and FFI
  20. Concurrency and OS threads
  21. Async on native (⚠ planned for native builds; runs under loup run and in WebAssembly)
  22. Desktop UI (⚠ planned: design preview)
  23. SIMD and GPU (⚠ planned: design preview)
  24. Building and distributing
  25. Memory safety patterns

The language reference

This book is a guide, not the specification. The normative reference is the four-volume Loup Language Reference in the repository's specs/ directory, cited here as "Language Reference §V-N.M": volume 1 is the core language (for example §1-2.4 on modes), 2 the runtime (§2-1 concurrency), 3 compilation (§3-2 native compilation and ownership), 4 data formats. Rulings made since the volumes were last revised are cited by name, such as ruling MODE-3. When this book and the reference disagree about the design, the reference wins; when the book shows code, that code was checked against the toolchain.

Companion books

  • The Loup Scripting Book covers host.scripted scripts: no main(), no build step, the quickest way to learn the language.
  • The Loup Web Book covers web.scripted and web.compiled code for the browser.
  • The Loup Freestanding Book covers freestanding code for kernels and firmware: the same ownership keywords, no runtime, no exceptions, no growable collections.

Chapters

  1. Chapter 1: Getting started

    This chapter gets you from an empty directory to a running native Loup program. You will install the toolchain, write a program with a main() function, run it with loup run, and then build it into a…

  2. Chapter 2: Native mode overview

    Chapter 1 got a program running. This chapter steps back and explains what the two native modes, host.native and host.dual, mean to the compiler: where they sit among Loup's six modes, what they…

  3. Chapter 3: Variables and numerics

    This chapter covers bindings (let, var, const), Loup's primitive types, numeric literals and conversions, and the part that matters most for native code: what happens when integer arithmetic…

  4. Chapter 4: Functions

    Functions in native Loup look like functions in any Loup mode, with every parameter and return type written out. This chapter covers declarations, default and named arguments, function values and…

  5. Chapter 5: Control flow

    Loup's control flow is close to C's and TypeScript's, with a few rules that catch people out: conditions always take parentheses, bodies always take braces, there is no ?: operator, and loop…

  6. Chapter 6: Collections

    Loup has four built-in collection types: list[T], dict[K, V], set[T] and tuples. This chapter covers their everyday operations and the property that surprises people coming from Python, JavaScript or…

  7. Chapter 7: Structs

    A struct is a value type for plain data: copied on assignment, compared field by field, and never reference-counted. This chapter covers declaring and constructing structs, mutable fields, methods…

  8. Chapter 8: Enums and pattern matching

    An enum is a type whose values are one of a fixed set of variants, each of which may carry its own data. Together with match, enums are how Loup models "one of several kinds of thing": a parsed…

  9. Chapter 9: Classes and ARC

    Structs (chapter 7) are values. Classes are the other half of Loup's data model: objects with identity, shared by reference, whose lifetime is managed by automatic reference counting (ARC). This…

  10. Chapter 10: Interfaces

    An interface names a set of methods. A class or struct that declares implements the interface and provides those methods can be used wherever the interface is expected. This chapter covers declaring…

  11. Chapter 11: Generics

    Generics let one definition work for many types: a Stack[T] of anything, a binarySearch over any ordered list. Type parameters are written in square brackets, and bounds in a where clause say what a…

  12. Chapter 12: Error handling

    Loup has two ways to report failure. An exception is thrown with throw and travels up the call stack until a try/catch handles it. A Result[T, E] is an ordinary return value that the caller inspects…

  13. Chapter 13: Modules and packages

    A program larger than one file is a package: a directory with a .lppkg manifest and source files, each of which is a module. This chapter covers how modules import each other and the standard…

  14. Chapter 14: Template fences

    Loup has two built-in ways to produce text from values. Interpolated strings, i"…{$ expr $}…", build a string on the spot and work everywhere, including native binaries. Template fences, blocks…

  15. Chapter 15: Ownership verbs

    Every parameter in Loup carries a verb that says what the function will do with the argument: read it, change it in place, take it over, or keep a reference to it. The verb is part of the signature,…

  16. Chapter 16: borrow, excl borrow and noescape

    Chapter 15's verbs (reads, edits, takes, shares) say what a function does with its arguments. This chapter covers three lower-level keywords that say how an argument is held:

  17. Chapter 17: unique ownership

    Reference counting lets any number of bindings share a class instance. That flexibility has two costs: a count in every object and an atomic increment or decrement whenever a reference is copied or…

  18. Chapter 18: Lifetimes and regions

    A plain borrow (chapter 16) lives only as long as the call it was passed to. Sometimes a borrow has to travel further: a function returns a reference into one of its arguments, or a struct holds a…

  19. Chapter 19: @unsafe and calling C

    Every check in chapters 15 to 18 stops at the edge of what the compiler can see. C libraries, inline assembly and claims about thread safety that rest on a protocol the compiler cannot read are on…

  20. Chapter 20: Concurrency with OS threads

    A native Loup binary can run code on several operating-system threads at once. This chapter covers starting threads and collecting their results, the Sendable rules that decide what may cross a…

  21. Chapter 21: Async on native

    ⚠ Planned for native binaries — not in Loup 1.25. The Language Reference (§2-1.1 to §2-1.9) specifies async/await for native programs, running on a multi-threaded, work-stealing executor. The 1.25.1…

  22. Chapter 22: Desktop UI

    ⚠ Planned — not in Loup 1.25. This chapter describes the design in the Language Reference (§2-4, "Reactive UI", and §2-4.8, "Desktop Backend"). The toolchain does not implement it yet, so its…

  23. Chapter 23: SIMD and GPU

    ⚠ Planned — not in Loup 1.25. This chapter describes the design in the Language Reference (§1-2.6 and §1-16.8) and the Packages Reference (§21.29, §21.30). The toolchain does not implement it yet, so…

  24. Chapter 24: Building and distributing

    This chapter covers getting a native Loup program from a project directory onto someone else's machine: the project manifest, the delivery targets loup build can produce, the native build options and…

  25. Chapter 25: Memory safety patterns

    Chapters 15 to 20 introduced Loup's safety mechanisms one at a time: ownership verbs, borrows, unique, lifetimes, @unsafe and Sendable. This chapter goes the other way. It takes the classic…