A module is a directory of Atoll source files. The project compiler derives a
file’s module path from the project root, its atoll.toml module name, and the
file’s parent directory.
seaport/
atoll.toml
main.at
core/
models/
booking.at
customer.atWith module = "workreef.dev/seaport", these files belong to:
| File | Module |
|---|---|
main.at |
workreef.dev/seaport |
core/models/booking.at |
workreef.dev/seaport/core/models |
core/models/customer.at |
workreef.dev/seaport/core/models |
The filename is not part of the module path.
Renaming booking.at therefore does not change its declarations’ import path as
long as it stays in the same directory. Moving it to another directory does.
Shared scope
Files in one directory share a module namespace. Public declarations from one file are available to another file in that directory without an import.
// booking.at
struct Booking {
id: int
}// display.at
fn booking_label(booking: Booking): string {
return "booking ${booking.id}"
}A module is therefore larger than a file but smaller than a project. Duplicate top-level names across sibling files conflict just as they would in one file.
Project checking registers declarations across the whole source set before resolving bodies. Forward references and mutual imports between modules can therefore resolve, including multi-module cycles. This does not make recursive value layouts valid; it only means import order is not a source-order restriction.
workreef.dev/seaport/orders -> workreef.dev/seaport/customers
workreef.dev/seaport/customers -> workreef.dev/seaport/ordersKeep dependency cycles small even though they are supported. A lower-level shared module often communicates the design more clearly than two feature modules that import each other broadly.
Source headers
Do not add a module declaration to ordinary source files. The parser still
accepts the legacy header for compatibility, but the current project pipeline
uses filesystem and manifest metadata as the source of truth.
The loader and editor derive the same path from the parent directory. A source header cannot override that derived identity.
Cross-module access
Code in another directory needs an import. Exported declarations are public by default; visibility can restrict them to their declaring file.
Imports are file-local. Same-directory public names are the only declarations made available automatically across source files.
Project roots
The normal project root is the directory containing atoll.toml. atoll check
can also inspect a directory without a manifest as an ad-hoc project. In that
mode the directory name becomes a synthetic root module, and dependency,
datasource, and host-capability configuration is unavailable.
Discovery
The project loader recursively reads .at files. It skips:
- dot-prefixed directories;
target;node_modules;build.
Directory entries are sorted before loading so diagnostics and project input remain deterministic. Files with other extensions do not participate in module scope.
Extra roots and dependencies can contribute more modules. A dependency carrying
its own atoll.toml keeps its declared module root; a bare local dependency
uses the dependency key as its root.
Organization
The compiler does not require one declaration per file. That remains a useful human convention for primary public types, while closely related private helpers can stay beside their caller. Directory names should express stable domain or layer boundaries because they become public import paths.
Read Projects for manifest and dependency behavior.