Modules
A module in Arx is a source file (for example, math.x) containing top-level statements such as imports, function definitions, and extern declarations.
Module Layout
```
title: Math module example
summary: Module with one documented function.
```
fn average(x: f32, y: f32) -> f32:
```
title: average
summary: Returns the arithmetic mean of x and y.
```
return (x + y) * 0.5
Package Layout
When a project uses the default src/ source root, or declares [build].src_dir, Arx treats files under that source root as package modules addressed by dotted names.
Example project layout:
.
├── .arxproject.toml
├── src
│ └── geometry
│ ├── __init__.x
│ ├── shared
│ │ └── math.x
│ └── shapes
│ ├── area.x
│ └── helpers.x
└── tests
└── test_area.x
With the default src/ source root:
src/geometry/__init__.xis modulegeometrysrc/geometry/shared/math.xis modulegeometry.shared.mathsrc/geometry/shapes/area.xis modulegeometry.shapes.areasrc/geometry/shapes/helpers.xis modulegeometry.shapes.helpers
Use __init__.x as the package root, following the same layout idea as Python packages.
Import Syntax
import geometry.shapes.area
import geometry.shapes.area as area
import circle_area from geometry.shapes.area
import circle_area as area_of_circle from geometry.shapes.area
import (circle_area, square_area) from geometry.shapes.area
import radius_to_diameter from .helpers
import (circle_area, square_area) from .area
import clamp from ..shared.math
Rules:
- Import statements are module-level statements.
- Grouped imports use parentheses.
- Grouped imports require
from. - Trailing commas are allowed in grouped imports.
- Empty grouped imports are invalid.
- Absolute module paths use dotted notation.
- Relative imports are supported only with
fromimports. - Relative imports use one or more leading dots before the module path.
- Plain relative module imports such as
import .areaare not supported yet. - Prefer
fromimports when you want callable declarations without a module qualifier.
Absolute Imports
Use absolute dotted paths for public imports across package boundaries:
import circle_area from geometry.shapes.area
Installed Package Imports
Arx can also resolve absolute imports from installed Arx source packages declared in [project].dependencies in .arxproject.toml.
For example, if the current project declares an installed dependency that exposes a package root named local_lib, this import resolves from that installed package when no local project source shadows it:
import sum2 from local_lib.stats
Installed package lookup is scoped to the current Python environment running arx. The compiler reads installed distribution metadata, follows transitive dependency metadata, and uses packaged .arxproject.toml files to find Arx source roots. It does not install packages, access the network, or change generated IR/codegen behavior.
For installed packages with the normal project layout, place .arxproject.toml at the packaged project root and declare both [build].src_dir and [build].package:
site-packages/local_lib_project/
├── .arxproject.toml
└── src
└── local_lib
├── __init__.x
└── stats.x
[build]
src_dir = "src"
package = "local_lib"With that layout, local_lib.stats resolves to site-packages/local_lib_project/src/local_lib/stats.x.
Flat package layouts are also supported for packages that place .arxproject.toml and .x files directly in the package directory:
site-packages/local_lib/
├── .arxproject.toml
├── __init__.x
└── stats.x
Resolution precedence is:
- local/current project source files
- installed Arx dependency packages
- unresolved import error
The reserved stdlib and internal builtins namespaces always remain owned by the compiler and cannot be replaced by installed packages.
Bundled stdlib
Arx ships a first-party standard library namespace called stdlib.
stdlibis bundled inside the installedarxPython package- stdlib modules are written in pure Arx source
- stdlib modules are resolved from the installed package location, not from the user project directory
- local user modules are not allowed to shadow the reserved
stdlibnamespace
Example:
import math from stdlib
fn main() -> i32:
return math.square(4) + math.clamp(0 - 3, 0, 2)
Bundled builtins
Arx also ships compiler-provided builtins backed by bundled Arx source modules.
Builtins and stdlib are intentionally separate:
- builtins are compiler/language-provided facilities resolved by dedicated compiler logic
- stdlib is the importable library namespace under
stdlib - builtin source files live under
packages/arx/src/arx/builtins/in the compiler repo - builtin source files use the
.xextension and are bundled inside the installedarxPython package - bundled builtin sources are loaded from package resources at compile time and are not copied into user projects
- builtin source modules are an internal compiler asset store, not a public stdlib-like import surface
- user code cannot import the internal
builtinsnamespace directly - local user modules are not allowed to shadow the reserved
builtinsnamespace
The first builtin module is generators. It is intentionally generic so future generator helpers, yield, and fuller generator semantics can live in the same conceptual area.
Current MVP:
rangeis available automatically without an import- supported callable shapes:
range(start, stop) -> list[i32]range(start, stop, step) -> list[i32]
startandstopare always explicitstepdefaults to1when omittedstep > 0counts up andstep < 0counts downstep == 0is rejected with an assertion failure- for-in loops can iterate over
range(...), list literals, and list variables because they consume list-valued expressions - ambient builtin names such as
rangeare injected only when not shadowed by a local top-level declaration or import
Example:
fn main() -> none:
print(range(0, 4)[2])
Namespace Imports
Use a module alias when you want to keep names grouped under a module namespace:
```
title: Geometry namespace import
summary: Call one module member through a namespace alias.
```
import geometry.shapes.area as area
fn main() -> f64:
```
title: main
summary: Demonstrates namespace member access.
```
return area.circle_area(10.0)
Direct symbol imports remain available when you prefer shorter local names:
import circle_area from geometry.shapes.area
Relative Imports
Use relative from imports for package-internal references. For example, inside geometry.shapes.area:
import radius_to_diameter from .helpers
import clamp from ..shared.math
Module Docstring
Arx supports module docstrings in Douki YAML format, delimited by triple backticks:
```
title: Module documentation
summary: Optional summary text
```
Current placement rule:
- The module docstring must be the first top-level element in the file.
- It must begin at character 0 of line 1 (no leading spaces).
Valid:
```
title: Module docs
```
fn main() -> i32:
```
title: main
summary: Entry point for the module.
```
return 1
Invalid (leading indentation before module docstring):
```
title: Module docs
```
fn main() -> i32:
```
title: main
summary: Entry point for the module.
```
return 1
For now, module docstrings are parsed and validated but ignored by AST/IR generation.