Skip to content

Modules & Imports

In Flame, every source file (.fm) acts as an isolated module. By default, declarations are private to the file unless explicitly marked with export.


Use export on functions, constants, structs, or annotations:

math_utils.fm
export fn add(a: Int, b: Int) -> Int {
return a + b
}
export const PI: Float = 3.14159
// Private helper (cannot be accessed from outside)
fn internal_helper() {
print("Private computation")
}

When imported by name, the module creates a namespace:

main.fm
import math_utils
fn main() {
let result = math_utils.add(10, 20)
print($"Result: {result}, PI: {math_utils.PI}")
}

Flame searches for imported modules in the following order:

  1. Current Directory: Relative files in the same folder.
  2. Project Source Folders: src/, tests/.
// Cross-folder imports
import src.exports
import tests.helpers
import utils.math

Custom annotations exported from a module are automatically brought into scope without requiring namespace qualification:

orm.fm
export annotation Entity(table: String) -> String {
return table
}
// models.fm
import orm
@Entity("users")
struct User {
id: Int,
name: String
}

Flame allows you to publish modules as reusable packages that can be imported by other projects.

To create a standalone Flame package, update your flame.toml to specify type = "pkg" (or type = "lib"). Packages do not require a main.fm entry point, they simply act as a collection of exported components inside their src/ directory.

[package]
name = "flamer"
version = "0.1.0"
type = "pkg"

You can depend on external Flame packages by adding them to the [dependencies] block of your flame.toml.

[dependencies]
flamer = "https://github.com/shoya-129/flamer"

When you run flame build, the compiler natively merges all abstract syntax trees (ASTs) from your pure Flame dependencies. This allows your local project’s language server, typechecker, and AOT compiler to seamlessly compile the imported code exactly as if it was written locally!