Stone Modules: Imports, Exports, and Re-Exports
Stone's module system is designed to be:
- static — all module paths are resolved at compile time
- explicit — nothing is imported or exported unless declared
- clean — no namespace pollution or implicit bindings
- path-based — module hierarchy is expressed using
/ - minimal — only essential forms for defining and exposing module APIs
A Stone module is always a single .stn file. Folders may contain many modules, but each file is an isolated compilation unit.
1. Exports
The export keyword marks top-level bindings as part of the module's public API.
export fn calcVelocity(d, t) = d / t
export fn calcAcceleration(dv, dt) = dv / dt
export constant = 42
Bindings not explicitly exported remain private.
Export Rules
- Only top-level bindings may be exported.
- Exported names must be unique within the module.
- Exported bindings must not be rebound.
- The module's public API is exactly the set of names preceded by
export.
2. Import Paths
Module paths mirror directory structure using /. Module references never use .stn extensions.
Stone supports two path forms:
Identifier Paths (ModulePath)
Standard paths using identifiers separated by /:
physics/mechanics/SpeedCalcUtility
math/statistics/variance
Quoted Paths (ModuleLocator)
String literals that allow spaces and special characters in folder/file names:
import "core logic/math/stats"
import "my modules/utilities"
Quoted paths must be string literals—no interpolation or concatenation allowed.
Import Path Rules
- Paths beginning with
./or../are relative. - All others are absolute.
- When importing a module without an alias, the final path segment becomes the namespace name.
- Quoted paths allow folder and file names with spaces.
Examples:
import math // absolute
import physics/rigid // absolute
import ./helpers // relative
import ../shared/utils // relative
// Quoted paths (allows spaces)
import "core logic/math/stats"
import "my modules/utilities"
Directory + Inferred Filename
When using a quoted path with a single selective import, Stone infers the filename from the import name:
// This resolves to "core logic/math/stats.stn"
import stats from "core logic/math"
// Equivalent to:
import stats from "core logic/math/stats"
This rule only applies when:
- The path is a quoted string literal
- There is exactly one import specifier
Multiple specifiers require an exact path:
// Must point to an actual file, no inference
import a, b from "some/dir"
3. Import Forms
Stone provides two import forms:
- Selective import — import specific exported names
- Namespace import — import the entire module as a namespace binding
These forms preserve clarity without polluting the local scope.
3.1 Selective Imports
Brings specific exported names into the current scope.
Syntax
import name1, name2 from path/to/module
// With quoted paths (allows spaces)
import mean from "core logic/math/stats"
import stats from "core logic/math" // infers stats.stn
Aliased
import name1 as local1, name2 as local2 from path/to/module
import mean as avg from "core logic/math/stats"
Example
import calcVelocity as vel,
calcAcceleration as accel
from physics/mechanics/SpeedCalcUtility
v = vel(100, 9.58)
a = accel(10, 2)
Rules
- Names must exist in target module's exports.
- Aliasing is optional.
- Selective imports introduce names into local scope.
- Single-specifier imports from quoted paths use directory inference.
3.2 Namespace Imports
Imports the entire module as a namespace.
Syntax
import path/to/module as Alias
// With quoted paths
import "core logic/math/stats" as mathLib
Automatic alias
If no alias is provided, the last path segment becomes the namespace.
import physics/mechanics/SpeedCalcUtility
SpeedCalcUtility.calcVelocity(5, 2)
// With quoted paths (auto-binds as 'stats')
import "core logic/math/stats"
stats.mean([1, 2, 3])
Rules
- Only the namespace binding is introduced.
- Exported names appear as fields.
- Namespace objects cannot be rebound.
- For quoted paths without alias, the last path segment becomes the namespace name.
4. Combined Imports
Selective and namespace imports may coexist:
import physics/mechanics/SpeedCalcUtility as Speed
import calcVelocity as vel from physics/mechanics/SpeedCalcUtility
This is allowed but rarely needed.
5. Standard Library Modules
Stone provides a standard library with modules for common operations. No std/ prefix required.
Note: Standard library modules must be explicitly imported. They are separate from the built-in functions (like print, len, sqrt, sin) which are auto-imported and always available.
// These require imports:
import hypot, clamp from math
import zeros, dot from linalg
import mean, std from stats
Quick Examples
// Math utilities
import PI, hypot, clamp from math
dist = hypot(3, 4) // 5
// Array operations
import linspace, reshape from array
t = linspace(0, 1, 100)
// Linear algebra
import dot, solve, eigvals from linalg
x = solve(A, b)
// Statistics
import mean, std, corr from stats
avg = mean(data)
// Signal processing
import fft from dynamics/fft
import hamming, filter from signal
// Control systems
import tf, step, bode from dynamics
G = tf([1], [1, 1])
6. Re-Exports (Exporting From Another Module)
Stone extends export to allow re-exporting bindings from another module. This enables clear, composable public APIs without requiring additional keywords.
Two re-exporting forms exist:
- Selective re-export — export specific names from another module
- Namespace re-export — export an entire module as a namespace
Re-exports do not introduce names into local scope. They only contribute to the module's exported API.
6.1 Selective Re-Export
export add, sub from ./math
Aliased:
export avg from ./math as calcAverage
Multiple names:
export add, sub, avg from ./math
export add as plus, sub as minus from ./math
Rules:
- Each forwarded name must exist in the target module's exports.
- The exported name (or alias) must not conflict with another export.
- Re-exported names do not appear in local scope unless separately imported.
6.2 Namespace Re-Export
Exports an entire module as a namespace.
export ./math as math
Without alias:
export ./physics/mechanics/SpeedCalcUtility
Exports a namespace named SpeedCalcUtility.
Rules:
- The exported namespace name must not conflict with another export.
- The namespace re-export does not introduce a local binding unless explicitly imported.
7. Barrel Modules (main.stn)
A folder may define a barrel module—typically named main.stn—to act as the folder's public API entrypoint. The barrel composes internal modules using re-exports.
Example folder structure:
utils/
main.stn
math.stn
string.stn
doc.md
Example main.stn:
# Namespace re-exports
export ./math as math
export ./string as string
# Selective helpers
export add, sub from ./math
export avg from ./math as calcAverage
export trim from ./string
export pad from ./string as padLeft
Consumer use:
import ./utils as utils
x = utils.add(1, 2)
y = utils.calcAverage([1, 2, 3])
z = utils.math.sub(10, 3)
s = utils.string.trim(" hi ")
Barrels:
- define controlled, stable package APIs
- prevent namespace leakage
- keep internal modules clean and focused
8. Unsupported Forms
To preserve clarity and prevent ambiguous resolution, Stone does not support:
- wildcard imports (
import *) - wildcard re-exports (
export * from ...) - default exports
- dynamic module paths
- dot-separated module paths (
a.b.c) - extracting import syntax (
{a, b})
All module relations remain static and explicit.
9. Summary
| Feature | Syntax |
|---|---|
| Export local binding | export fn f(...), export x = value |
| Selective import | import a, b as B from path/module |
| Namespace import | import path/module as Alias |
| Auto namespace name | import path/module |
| Quoted path import | import "path with spaces" |
| Directory inference | import stats from "dir" → dir/stats.stn |
| Selective re-export | export a, b as B from path/module |
| Namespace re-export | export path/module as Alias |
Stone's module system is:
- simple
- explicit
- immutable
- static — all paths resolved at compile time
- consistent across large and small codebases