Modules
As programs grow, you'll want to split code across multiple files. Gruel's module system is simple: every .gruel file is a module, and you import it with @import.
Importing a File
Use @import("path/to/file.gruel") to import another file. The result is a value containing all the pub declarations from that file:
// math.gruel
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn mul(a: i32, b: i32) -> i32 {
a * b
}
// main.gruel
const math = @import("math.gruel");
fn main() -> i32 {
let sum = math.add(3, 4);
let product = math.mul(3, 4);
@dbg(sum); // prints: 7
@dbg(product); // prints: 12
sum
}
Compile both files together and the import is resolved automatically:
Public and Private
Only declarations marked pub are accessible from other modules. Everything else is private:
// utils.gruel
pub fn public_helper(x: i32) -> i32 {
double(x) + 1
}
fn double(x: i32) -> i32 { // private — not accessible from outside
x * 2
}
// main.gruel
const utils = @import("utils.gruel");
fn main() -> i32 {
utils.public_helper(5) // OK: 11
// utils.double(5) // ERROR: `double` is private
}
Modules and Structs
Modules work just like structs at the type level. You can pass a module to a function, store it in a variable, or use its associated functions—it all uses the same dot syntax you already know.
// shapes.gruel
pub struct Circle {
radius: i32,
}
pub fn area(c: Circle) -> i32 {
// approximate: pi * r^2 ≈ 3 * r^2
3 * c.radius * c.radius
}
// main.gruel
const shapes = @import("shapes.gruel");
fn main() -> i32 {
let c = shapes.Circle { radius: 5 };
let a = shapes.area(c);
@dbg(a); // prints: 75
0
}
Organizing Larger Projects
For larger projects, group related files in a directory. Create an _index.gruel (or a main file) that re-exports what the rest of the project needs:
project/
├── main.gruel
├── math/
│ ├── arithmetic.gruel
│ └── geometry.gruel
└── io/
└── input.gruel
// main.gruel
const arithmetic = @import("math/arithmetic.gruel");
const geometry = @import("math/geometry.gruel");
fn main() -> i32 {
arithmetic.add(1, 2)
}
Compiling Multiple Files
Pass all source files to the compiler. Order doesn't matter—the compiler figures out dependencies:
# Explicit files
# Or use shell glob expansion
The -o flag is required when compiling more than one file.