Modules
Packages, Modules, and Files
Paradox organizes code using three levels:
Packages
A package is defined by a dox.yaml file in a directory:
name: my-project
description: My domain specification
The name field defines the package name used in imports. The directory containing dox.yaml is the package root. A package contains one or more modules.
Modules
A module is a directory. All .dox files in a directory are merged into a single module — file names are purely organizational and have no effect on building or compiling (Go-style). Subdirectories are submodules, accessed via path syntax:
std/ # "std" module (root of the std package)
dox.yaml # package manifest: name: "std"
std.dox # ┐
collection.dox # │ all merged into the "std" module
algebra.dox # │
numeric.dox # │
function.dox # │
persist.dox # ┘
ast/ # "std/ast" submodule
foundation.dox # ┐
declaration.dox # │ all merged into "std/ast"
expression.dox # │
type.dox # │
term.dox # │
primitive.dox # ┘
Import System
Paradox has two forms of import:
Package Imports
Import a package (or submodule) by name:
import std
import std/ast
Package names are resolved via the PARADOX_ATLAS environment variable, which contains a colon-separated list of absolute paths to package directories. Each path must contain a dox.yaml. When you import std, Paradox finds the directory whose dox.yaml has name: "std" and loads all .dox files in that directory.
To import a submodule, use path syntax: import std/ast loads all .dox files from the ast/ subdirectory within the std package.
Multi-File Projects
Split large domain models across multiple files. All .dox files in a directory are part of the same module:
my-project/
dox.yaml # name: "my-project"
types.dox # ┐ all part of root module
validation.dox # ┘
models/ # submodule, import with /models
user.dox # ┐ all part of "models" module
pet.dox # ┘
| In types.dox -- no import needed for validation.dox (same directory)
import std
import /models
Files in the same directory are automatically available to each other with no import required.
A file cannot import its own package. If machine.dox is part of the std package, writing import std inside it is a self-import error. Files within a package can reference each other’s types without importing their own package.
|
PARADOX_ATLAS
The PARADOX_ATLAS environment variable is a colon-separated search path of absolute directory paths. Each directory must contain a dox.yaml file. When you write import std, Paradox walks the atlas left to right, finds the first directory whose dox.yaml has name: "std", and loads all .dox files from that directory.
export PARADOX_ATLAS="/path/to/std:/path/to/my-lib:/path/to/other-pkg"
Requirements
Every entry in PARADOX_ATLAS must be:
-
An absolute path (starts with
/) — relative paths are rejected -
A valid filesystem path — no null bytes or illegal characters
-
A directory containing a
dox.yamlwith at least anamefield
If any entry fails these checks, Paradox will refuse to start and report the offending path.
dox.yaml
Each package directory has a dox.yaml manifest:
name: my-package
description: A useful domain specification
The name field is the identifier used in import statements. The description is optional metadata.
Resolution
When resolving import foo:
-
Split
PARADOX_ATLASon: -
For each directory, parse its
dox.yaml -
Return the first match where
nameequalsfoo -
If no match, report an error
For submodule imports like import foo/bar, Paradox finds the foo package as above, then loads .dox files from the bar/ subdirectory within that package.
See Also
-
Project Structure — Multi-file project conventions