ajhahn.de
← Flash
Markdown 93 lines
# Chapter 10: Modules & Imports

Flash projects are modular. Source files can import system modules, sibling files, and re-export declarations to compile into cohesive binaries.

---

## 1. Importing Modules (`use`)
To import a module, use the `use` statement at the top level of your file.

```flash
// Import flibc module
use flibc
```

### Import Aliases (`as`)
If a module name is long, or conflicts with another declaration, you can rename it during import:

```flash
// Import syscall_defs and reference it as 'defs'
use syscall_defs as defs

pub const Dirent = defs.Dirent
```

---

## 2. Importing Sibling Files
To import another source file in the same directory, name the file stem in double quotes. The quoted name carries **no extension** — the compiler adds the backend suffix (`.zig`) during lowering:

```flash
// Import a local Zig wrapper file
use "syscalls" as sys
```

---

## 3. Re-exporting (`pub use`)
A Flash module can act as an import hub for other files. To make an imported file accessible to external modules that import this module, use `pub use`.

This translates directly to public constant imports downstream:
`pub use "io" as io` translates to `pub const io = @import("io.zig")` in Zig — the extension appears only in the lowered output.

Here is a simplified example of how `flibc.flash` acts as a re-export hub for userland:

```flash
// flibc.flash
pub use "syscalls" as sys
pub use "io" as io
pub use "heap" as heap

// Expose standard functions directly at the top level
pub const printf = io.printf
pub const malloc = heap.malloc
pub const free = heap.free
```

Now, any other program can simply `use flibc` and reach these functions:
```flash
// main.flash
use flibc

export fn main(_ usize, _ argv) noreturn {
    ptr := flibc.malloc(64)
    defer flibc.free(ptr)
    
    flibc.printf("Allocated memory!\n")
    flibc.exit()
}
```

---

## 4. Sharing Symbols Across Objects (`export var` / `extern var`)

Beyond functions, file-scope **variables** can cross object boundaries — the kernel symbol-sharing pattern, where one module owns the storage and every other object names it:

```flash
// In the module that OWNS the storage: define a cross-object symbol
export var nr_tasks i32 = 0

// In every module that CONSUMES it: typed, with no initializer —
// the storage is defined elsewhere, like an extern fn prototype is bodyless
extern var nr_tasks i32
```

`pub` composes in front (`pub export var`, `pub extern var`). An `extern var` carrying an initializer, or missing its type, is rejected with a targeted diagnostic.

The form also covers **linker-script symbols**, where the address itself is the value:

```flash
extern var _kernel_pa_end u8
```