Luce Base
LuceEngineeringLuciaOS

16. Modules, packages, and tests

16.1 Files and modules#

One file is one module; its path is its package-relative path: src/image/color.lucb is image.color. There is no module declaration and no re-export. Module cycles are errors. Declarations are private unless pub, and a public signature may mention only public types.

16.2 The three module kinds#

KindSuffixReference identityRaw pointersRuntime required
Safe Luce.lucreference-counted classes, collections, closuresnoyes
Native Luce.lucnyesintrinsics, auditedyes
Base.lucbnoordinary, C spellingno

The suffix is the kind. A Base module imports Base modules and C, never a full Luce module. A safe or native module imports any kind. A package whose modules are all Base is a Base package; the sealed runtime package is one, with the single exception that it may contain .lucn modules under its own identity for its two sealed intrinsics (§18.13).

Why the direction is one-way. Everything a Base module can reach is Base or C, so a Base artifact needs no runtime, and that is checkable: the compiler's reachability analysis reports the first full Luce function a freestanding build touches.

16.3 Imports#

import image.color
import data.serialisation as serial
from image.geometry import Point

import keeps a module qualified, with an optional alias. from ... import brings named declarations in. There are no wildcards and no relative imports. Unused and duplicate imports are errors with automatic fixes.

16.4 Packages#

A package has a luce.toml manifest and an exact lock. The manifest names the package, its source roots, its dependencies, and its C inputs (§17.4). There are no build scripts.

16.5 Tests#

test "cursor advances by one":
    var cursor = Cursor(data = "ab".bytes(), offset = 0)
    try cursor.advance(1)
    assert(cursor.offset == 1)

test is a declaration, compiled to a hidden unit! function and discovered statically; luce test runs every test and luce build removes them all. A test may use its module's private declarations. Inside a full Luce program tests run under the shared harness. In a Base artifact they run under a freestanding runner with a Base testing module providing assertions, deterministic seeds, and a fixed-buffer allocator; facilities that need an isolated execution domain are absent, and a trap ends the run after naming the test. A test that writes a module global is not isolated from the others, and the runner reports which globals it wrote.