Luce
Luce BaseSourceLuciaOS

15. Modules and packages

15.1 Files and modules#

One .luc file is one module; its path under the package's source root is its name: src/image/color.luc is image.color. A file's name is an identifier. A .lucb file in the same package is a Base module (§16). Module cycles are errors. The source root is the one the package's manifest names (§15.5); a program run without a manifest has its entry module's directory as the root and app as its package name.

15.2 Imports and visibility#

import image.color
import data.serialization as serial
from image.geometry import Point, Size

import keeps a module qualified, with an optional alias; from ... import brings the named public declarations in. Imports come first and are used; a name is imported once and never declared beside its import. Declarations, fields and methods are private to their module unless pub: a pub type with no pub member can be named and passed but not read or called from another module. A public signature mentions only public types. A module's name is read only to reach a member, shapes.origin, shapes.Point; the closed protocols (§13.3) are visible in every module without an import.

15.3 Top level#

A module contains imports, then struct, enum, class, interface, type, func, test, and let constants. A top-level let is a constant expression: literals, arithmetic, tuples, enum cases, and constructors of structs of those. There is no module initialisation and no global var; mutable state lives in an object the program constructs.

15.4 Entry point#

pub func main(arguments: list[str]) -> int!:
    return 0

15.5 Packages#

A package is a directory with a luce.toml naming the package, its source root, its tests, and its dependencies exactly. There is no build script and no network during a build. The manifest is the same document for the Base modules the package contains.

[package]
name = "demo"
source = "src"

name is the package's identity (§12.3); source is the root the modules are named from, src unless written. The nearest manifest above the entry module is the program's.

[dependencies] maps a dependency's package name to its local directory, relative to this manifest. The dependency's [exports] maps public import names to modules under its source root. For example, ui = "luce_ui.ui" exposes src/luce_ui/ui.lucb as from ui import Button; construction is Button("pause"). Aliases retain the canonical type identity. Conflicting exports are errors. Base owns module resolution; Luce invokes the compiler LUCE_BASE names, else luce-base beside the luce executable, as a release lays them out, else luce-base on the path. Standard imports such as math use its embedded modules. See the package import contract for complete examples and source-bundle relocation. Builds do not fetch dependencies.