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.
Exporting Symbols (export)
Section titled “Exporting Symbols (export)”Use export on functions, constants, structs, or annotations:
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")}Bare Module Imports vs. Quoted Resource Imports
Section titled “Bare Module Imports vs. Quoted Resource Imports”Flame makes a clear, foundational distinction between module resolution and external resource resolution:
// 1. Bare Imports: Flame packages, standard library, and module namespacesimport std.webimport std.fsimport math_utilsimport flamer
// 2. Quoted Imports: External files, data resources, scripts, and stylesheetsimport "data.json" as dataimport "config.txt" as configimport "playground.js" as scryptimport "theme.css" as theme| Import Syntax | Resolution Engine | Target Types | Typical Use Cases |
|---|---|---|---|
Bare Import (import name) |
Flame Module / Package System | .fm source modules, std.*, native crates, downloaded packages |
Business logic, standard libraries, traits, structs, and functions |
Quoted Import (import "path" as alias) |
File System / Resource Engine | .toml, .json, .fmi, .txt, .js, .css, .html |
Configurations, structured datasets, metadata, stylesheets, client scripts |
Importing Modules (import)
Section titled “Importing Modules (import)”Whole Module Import
Section titled “Whole Module Import”When imported by bare identifier name, the module creates a namespace from another Flame source file or standard library module:
import math_utilsimport std.fmt
fn main() { let result = math_utils.add(10, 20) print($"Result: {result}, PI: {math_utils.PI}")}External Resource Imports (import "file")
Section titled “External Resource Imports (import "file")”Resource imports are a universal language feature in Flame, available for every kind of application:
- CLI tools & daemons: Embed static templates, help texts, or seed schemas without packaging extra directories.
- Backend servers & microservices: Load configuration files (
flame.toml,.env) and data schemas (.json,.fmi) instantly with zero disk IO overhead. - Desktop applications: Access bundled assets directly from the filesystem.
- Web applications (
@Web): Seamlessly bundle stylesheets (.css) and client scripts (.js).
Path Resolution (./ and ../)
Section titled “Path Resolution (./ and ../)”Quoted imports support direct filesystem paths, including relative indicators:
./file.ext: Resolves relative to the directory containing the current source file.../file.ext: Walks up the directory tree relative to the current file (ideal fortests/importing the project rootflame.tomlor shared fixtures).file.ext: Searches the current folder and automatically walks up project folders (src/,public/,assets/,static/, root).
// Importing from parent directories or sibling foldersimport "../flame.toml" as configimport "./assets/seed.json" as seedimport "../meta.fmi" as meta1. Data Files & Array Indexing (import "data.json")
Section titled “1. Data Files & Array Indexing (import "data.json")”Importing a .json file automatically parses structured data into accessible Flame objects and tuples at compile time and runtime:
{ "appName": "Flame Studio", "version": "0.6.0", "maxConnections": 1000, "features": ["reactive-dom", "wasm-compute", "hot-reload"]}import "data.json" as data
fn main() { // Access JSON properties directly without manual fs.read or deserialization! println($"Launching {data.appName} v{data.version}") println($"Connection limit: {data.maxConnections}") println($"First feature: {data.features[0]}")}Array-Rooted JSON Files (data[0])
Section titled “Array-Rooted JSON Files (data[0])”When a JSON file begins with a root array [ ... ], Flame represents it as an indexable collection of objects. You can index by integer (data[0]) and directly access fields by dot (data[0].id) or string key (data[0]["id"]):
[ { "id": 1, "name": "Alice", "role": "admin" }, { "id": 2, "name": "Bob", "role": "developer" }]import "users.json" as users
fn main() { let first_user = users[0] println($"First user: {first_user.name} (#{users[0]["id"]})") println($"Second user: {users[1].name}")}2. TOML Configuration Files (import "flame.toml")
Section titled “2. TOML Configuration Files (import "flame.toml")”Flame natively supports importing TOML configuration files—including flame.toml or custom configuration profiles—with high-speed native parsing:
[package]name = "my_app"version = "0.6.0"tags = ["fast", "reactive"]
[database]host = "127.0.0.1"port = 5432import "flame.toml" as config
fn main() { // Tables and nested properties are accessible via standard dot syntax: println($"App: {config.package.name} v{config.package.version}") println($"Primary Tag: {config.package.tags[0]}") println($"Database: {config.database.host}:{config.database.port}")}In @Web builds, TOML configurations are automatically serialized into the client resource bundle so frontend components can inspect build properties and application settings seamlessly.
3. Flame Metadata Interface (import "*.fmi")
Section titled “3. Flame Metadata Interface (import "*.fmi")”.fmi (Flame Metadata Interface) files are JSON-formatted metadata manifests used for component declarations, plugin contracts, and package interfaces.
Flame treats .fmi files with the same first-class support as JSON:
// component.fmi{ "name": "DataGrid", "version": "1.0.0", "inputs": ["columns", "rows"]}import "component.fmi" as meta
fn main() { println($"Component: {meta.name} (v{meta.version})") println($"Input 0: {meta.inputs[0]}")}4. Static Text & Configuration Files (import "config.txt")
Section titled “4. Static Text & Configuration Files (import "config.txt")”Text files (.txt, .text, .md) are imported as native String values:
import "motd.txt" as bannerimport "config.env" as envConfig
fn main() { println(banner) println($"Config payload length: {envConfig.len()} bytes")}5. External JavaScript Modules (import "app.js")
Section titled “5. External JavaScript Modules (import "app.js")”When developing web applications with @Web or integrating with browser environments, you often have existing JavaScript libraries, DOM utilities, or legacy scripts. Flame allows you to import JavaScript files directly:
export function loadExample(name) { const editor = document.getElementById("code"); if (editor) { editor.value = "// Loaded: " + name; }}
export function clearEditor() { const editor = document.getElementById("code"); if (editor) editor.value = "";}import std.webimport "playground.js" as scrypt
fn handleSelect(e: Unknown) { let selected = e.target.value // Directly call the external JavaScript function! scrypt.loadExample(selected)}
fn handleReset(e: Unknown) { scrypt.clearEditor()}What Flame Provides for JavaScript Imports:
Section titled “What Flame Provides for JavaScript Imports:”- Intelligent Signature Inspection: Flame scans exported JS functions (
export function name(args)orfunction name(args)) and provides autocomplete for member functions. - Unified IDE Experience: Hovering over
scrypt.loadExamplereveals the signature (fn loadExample(name: Unknown) -> Unknown) and notesExternal JavaScript function in playground.js. - Go-to-Definition: Running Go-to-Definition on
loadExampleorscryptjumps straight to the exact line in your.jsfile. - Flexible Argument Passing: Dynamic external JS calls support optional arguments and JavaScript conventions without strict static type mismatches.
6. External Stylesheets (import "theme.css")
Section titled “6. External Stylesheets (import "theme.css")”CSS files can be imported and bound to aliases to pass directly to @Web configurations:
import "theme.css" as themeimport "style.css" as style
@Web(title: "My App", css: [theme, style])fn main() { // ...}Folder-Based Imports & Packages
Section titled “Folder-Based Imports & Packages”If a folder contains multiple .fm files, you can import the entire folder as a single namespace. To do this, every .fm file in that folder must begin with a package declaration.
When imported, Flame will scan all .fm files in the folder and aggregate all exported functions, structs, and annotations into a single module namespace.
package utils
export fn add(a: Int, b: Int) -> Int { return a + b}package utils
@Docs("Reverses a string")export fn reverse(s: String) -> String { // ...}You can then import the utils folder and access symbols from both files seamlessly:
import utils
fn main() { let sum = utils.add(10, 20) let rev = utils.reverse("hello")}The main Package (The src/ Directory)
Section titled “The main Package (The src/ Directory)”In Flame projects, the top-level src/ directory is implicitly treated as the main package. If you are writing tests inside the tests/ directory (or other folders outside of src/), you can import everything exported from your src/ directory using:
import main
@Testfn test_something() { // Access exported symbols from src/ using main.* let result = main.some_exported_function()}You do not need to explicitly declare package main in your src/ files. When you write import main, Flame will automatically aggregate all exported symbols across the .fm files in your src/ folder.
Flame’s language server fully supports folder-based imports, meaning custom @Docs and autocomplete suggestions will work accurately across all files aggregated in the namespace.
Exported Annotations
Section titled “Exported Annotations”Custom annotations exported from a module are automatically brought into scope without requiring namespace qualification:
export annotation Entity(table: String) -> String { return table}
// models.fmimport orm
@Entity("users")struct User { id: Int, name: String}The Package Ecosystem (type = "pkg")
Section titled “The Package Ecosystem (type = "pkg")”Flame allows you to publish modules as reusable packages that can be imported by other projects.
Creating a Package
Section titled “Creating a Package”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"Consuming Remote Dependencies
Section titled “Consuming Remote Dependencies”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"Run fmp install to resolve and cache dependencies into .flame/pkg/:
fmp installDuring fmp build, Blaze performs dependency analysis and constructs an application-specific native runtime containing only the packages and native components your application actually imports and uses.
