Modules and Imports
NG uses a file-based module system. Every .ng file is a module, and you control visibility with export and import.
Module Basics
Every File is a Module
When you create math.ng:
// math.ng — this is a module
fun add(x: i32, y: i32) -> i32 => x + y;By default, nothing is visible to other modules. You must export what you want to expose.
Exporting
The export Keyword
// math.ng
export fun add(x: i32, y: i32) -> i32 => x + y;
export fun multiply(x: i32, y: i32) -> i32 => x * y;
// This is private — not visible outside this file
fun helper(x: i32) -> i32 => x + 1;Wildcard Export
Use exports * in the module declaration to export everything:
module math exports *;
fun add(x: i32, y: i32) -> i32 => x + y;
fun multiply(x: i32, y: i32) -> i32 => x * y;All top-level bindings are now exported.
Module Declaration Syntax
module <name> exports <list>;The module name is used for qualified imports.
Importing
Wildcard Import
Import all exported symbols into the current namespace:
// main.ng
import math (*);
add(1, 2); // OK
multiply(3, 4); // OKNamed Import
Import specific symbols:
import math (add); // only add is imported
add(1, 2); // OK
// multiply(3, 4); // ERROR: not importedQualified Import
Use a module prefix to avoid name conflicts:
import math;
val result = math::add(1, 2);Mixed Import
import math (add); // unqualified add
import math; // also provides math:: prefixModule-Level Alias
You can alias a module at import time:
import std.prelude as prelude;
prelude::print("Hello!");Module Resolution
Search Paths
When you import math, NG searches for math.ng in:
- The directory of the importing file
- The
lib/directory (standard library) - The
../lib/directory (relative to binary)
Module Paths with Dots
Dots in module names map to directory paths:
import std.prelude; // loads lib/std/prelude.ng
import std.string; // loads lib/std/string.ng
import std.io; // loads lib/std/io.ngCircular Imports
Circular imports are not supported. If module A imports module B, module B cannot import module A (directly or transitively).
Standard Library Import
The std.prelude module is implicitly imported into every NG file. Other standard library modules must be explicitly imported:
import std.io;
val content = readFile("data.txt");
import std.string;
val lines = split(content, "\n");Bytecode Module Artifacts (.ngo)
NG can compile modules to bytecode for faster loading:
# Compile to bytecode
./build/ngi --emit-ngo math.ngo example/math.ng
# Run referencing the .ngo artifact
./build/ngi example/main.ngThe module loader automatically:
- Checks for a
.ngofile alongside the source - Verifies the source hash matches (detects staleness)
- Falls back to source compilation if the artifact is stale or incompatible
Exporting Types
Types, functions, and even trait implementations can be exported:
// shapes.ng
module shapes exports *;
type Point {
x: i32;
y: i32;
}
export fun origin() -> Point {
return new Point { x: 0, y: 0 };
}
// Importing export impls
module math exports *;
impl Show for i32 { ... }When you import shapes, you get access to the Point type and the origin function.
What's Next?
Continue to Generics to learn about writing reusable, type-parameterized code.
Try it:
example/08.imports.ng— Basic imports Try it:example/13.import_std_prelude.ng— Importing standard library Try it:example/56.stdlib_modules.ng— Multiple module interactions