Modules and visibility
Declaring submodules
mod declares a submodule, which the compiler expects to find as either
name.tg or name/mod.tg:
mod lexer;
mod parser;
mod elab;
A typical layout:
module_example/
mod.tg entry point
greet.tg
math/
mod.tg declares its own sub-modules
ops.tg
// module_example/mod.tg
pub mod math;
pub mod greet;
use greet::answer;
fn main() -> Nat {
answer()
}
// module_example/math/ops.tg
pub fn add(a: Nat, b: Nat) -> Nat {
a + b
}
Importing
use lexer::token::Token;
use driver::{parse_args, dispatch_command, process_exit};
Paths are absolute from the crate root. There is no super and no relative
import — a path means the same thing wherever it is written, which is worth the
occasional extra segment.
Visibility
Declarations are private to their module unless marked pub:
pub fn public_function() -> Nat { 1 }
pub type PublicType = { value: Nat }
pub extern "C" fn public_extern() -> Unit
pub applies to modules too — pub mod math; makes the module itself
reachable. Visibility is enforced per constructor and per field, so a pub type
does not automatically expose everything inside it.
Import aliasing
Since 1.5
Rename on import to resolve a collision or shorten a name:
use util::original_name as renamed;
use lexer::token::Token as LexToken;
Modules are properly namespaced
Two modules may each define label without interfering: v1.5 removed the
flattening pass that used to merge everything into one namespace after
elaboration, and each module is now elaborated on its own.
A known divergence. With same-named definitions in sibling modules, the interpreter currently resolves the wrong one — it binds the last-declared module’s version regardless of what the
usenames. Compiled binaries are correct. Until this is fixed, avoid exporting the same name from two modules in the same program, or verify withalbite compilerather thanalbite run. See Current limitations.