machdocs
Home GitHub

Modules

A Mach project is a tree of modules rooted at the project's id. Each file is reachable by a dotted path; use imports a name privately and fwd re-exports it on a module's public surface.

Module paths

Every .mach file under a project's source directory is a module, reachable by a dotted path from the project root. The path separator is ., and each segment mirrors the directory and file name.

Project idFileModule path
myprojsrc/foo/bar.machmyproj.foo.bar

There is no this. self-prefix. Within a project, modules always reference each other by their full project-rooted path, so every reference reads the same regardless of where it appears.

Imports with use

use brings an external symbol or module into the current scope under a local name. It is a private import: the imported name is not exposed to consumers of this module.

use PATH;                   # binds the leaf component
use ALIAS: PATH;            # binds ALIAS

Module vs symbol binding

The resolver binds whatever the path points to. A path ending at a module binds the module, and you reach its members with qualified module.member access. A path ending at a symbol binds the symbol for bare use. Importing a module does not pull its members into scope unqualified: to use usize bare, import the symbol, not its module.

use std.types.size;             # binds module 'size'; use as size.usize
use sz: std.types.size;         # binds module under 'sz'; use as sz.usize
use std.types.size.usize;       # binds symbol 'usize'; use bare as usize
use my_usize: std.types.size.usize;  # binds symbol under 'my_usize'
Note

A Mach module imports every dependency it directly names, including any reached only through a re-export. There is no shortcut for "my surface uses these transitively; just give me the leaf." The dependency graph stays visible at the top of every file.

Re-exports with fwd

fwd re-exports a symbol or module from another module under this module's public surface. It is the public counterpart to use, and it mirrors use's grammar exactly.

fwd PATH;                   # re-export under the path leaf
fwd ALIAS: PATH;            # re-export with rename
use impl: full.core.data;

fwd impl.Point;             # re-exports as 'Point'
fwd Pt: impl.Point;         # re-exports as 'Pt'

A fwd path that ends at a module re-exports the whole module as a public module alias, mirroring use's module binding. A consumer reaches the alias's members with qualified access, chaining through any depth of re-export, including a fwd of another library's fwd.

fwd demo.alpha;             # re-exports module 'alpha'
fwd deep: demo.deep.beta;   # re-exports module under 'deep'

use demo.lib;               # lib.mach contains: fwd demo.alpha;
lib.alpha.answer();         # resolves through the module re-export

As with use, a module alias is not a value; only its members can be named.

The shadow-module pattern

A file foo.mach may co-exist with a directory foo/. The file is the surface module, the public face of foo. The directory's files are split implementations that the surface loads and re-exports.

myproj/
  foo.mach          # surface
  foo/
    a.mach          # split: myproj.foo.a
    b.mach          # split: myproj.foo.b

The surface loads each split with use and re-exports its public symbols with fwd. Consumers use myproj.foo and reach symbols through the surface; they never name the split files directly.

# myproj/foo.mach (surface)
use myproj.foo.a;
use myproj.foo.b;

fwd a.X;
fwd b.Y;

Two common uses:

Bare project-id imports

A one-segment use/fwd path equal to a resolvable project id (a dependency's id or the current project's own id) resolves to that project's declared [project].module, the surface file named by the manifest. A library glfw that declares module = "glfw.mach" is imported by its id alone.

use glfw;                    # binds glfw's declared [project].module
Note

A bare import of a project that declares no module is an error, directing you to a full path or to add the manifest key. Longer paths are unaffected.

See also

  • Visibility - what pub exposes for use and fwd to reach
  • Manifest - declaring [project].module for bare imports
  • Project layout - how the source tree maps to module paths