Modules and Imports
Mux uses Python-style imports for code organization and reuse.
Basic Import Syntax
import math
import shapes.circle
import utils.logger as log
import std.math
import std.datetime
- Python-style imports only
- Module paths map directly to file paths
- Imported symbols can be used immediately
Standard Library Imports
The stdlib uses the std namespace:
import std
import std.assert
import std.math
import std.io
import std.random
import std.datetime
import std.sync
import std.net
import std.(math, random as r)
import std.*
import stdexposes module namespaces likestd.assert,std.math,std.io,std.random,std.datetime,std.sync, andstd.netimport std.<module>imports a single stdlib module namespaceimport std.*performs a flat import of stdlib items into the current scope
Module Resolution
Module paths map to file paths:
import math // math.mux in same directory
import shapes.circle // shapes/circle.mux
import lib.core.util // lib/core/util.mux
File Structure:
project/
├── main.mux
├── math.mux
├── shapes/
│ ├── circle.mux
│ └── rectangle.mux
└── lib/
└── core/
└── util.mux
Using Imports
Basic Usage
// math.mux
func add(int a, int b) returns int {
return a + b
}
func multiply(int a, int b) returns int {
return a * b
}
const float PI = 3.14159
// main.mux
import math
func main() returns void {
auto sum = math.add(5, 3)
auto product = math.multiply(4, 7)
auto circumference = 2.0 * math.PI * 5.0
print(sum.to_string())
print(product.to_string())
}
Aliased Imports
Use as to rename imported modules:
import shapes.circle as circle
import utils.logger as log
func main() returns void {
auto c = circle.new(5.0)
log.info("Created circle")
}
Imports for Side Effects
Use _ when importing only for side effects:
import utils.logger as _ // imported but not directly used
Name Mangling
Functions from imported modules use mangled names to prevent conflicts:
// math.mux
func fibonacci(int n) returns int {
if n <= 1 {
return n
}
return fibonacci(n - 1) + fibonacci(n - 2)
}
// main.mux
import math
func main() returns void {
auto result = math.fibonacci(10) // Calls math_fibonacci
print(result.to_string())
}
Generates LLVM function: math_fibonacci (not just fibonacci)
This prevents conflicts when multiple modules define functions with the same name.
Module Initialization
Top-level statements in modules become initialization functions:
// config.mux
const int MAX_USERS = 100
auto initialized = false
func initialize() returns void {
initialized = true
print("Config initialized")
}
// Top-level code runs on import
print("Loading config module...")
initialize()
The compiler:
- Generates a module init function
- Calls it before
main()executes - Ensures each module initializes only once
Dependency Resolution
The compiler processes modules in dependency order:
// a.mux
import b
func useB() returns void {
b.doSomething()
}
// b.mux
import c
func doSomething() returns void {
c.helper()
}
// c.mux
func helper() returns void {
print("helper called")
}
Initialization order: c -> b -> a -> main
Module Scope
Public by Default
All functions and types are public by default:
// math.mux
func add(int a, int b) returns int { // Public
return a + b
}
const float PI = 3.14159 // Public
Module-Level Variables
// config.mux
const string VERSION = "1.0.0"
auto request_count = 0
func increment_requests() returns void {
request_count++
}
func get_request_count() returns int {
return request_count
}
// main.mux
import config
func main() returns void {
print("Version: " + config.VERSION)
config.increment_requests()
print(config.get_request_count().to_string())
}
Circular Dependencies
Warning: Avoid circular imports:
// a.mux
import b // ERROR: a imports b, b imports a
func useB() returns void {
b.doSomething()
}
// b.mux
import a // ERROR: circular dependency
func doSomething() returns void {
a.useB()
}
Solution: Restructure to remove circular dependencies or extract shared code to a third module.
Common Module Patterns
Utility Module
// utils.mux
func max(int a, int b) returns int {
if a > b {
return a
}
return b
}
func min(int a, int b) returns int {
if a < b {
return a
}
return b
}
func clamp(int value, int low, int high) returns int {
if value < low {
return low
}
if value > high {
return high
}
return value
}
Type Module
// types.mux
class Point {
int x
int y
func distance_to(Point other) returns float {
auto dx = self.x - other.x
auto dy = self.y - other.y
auto sum = dx * dx + dy * dy
return sum.to_float() // Simplified, needs sqrt
}
}
enum Color {
Red
Green
Blue
}
Constants Module
// constants.mux
const int MAX_CONNECTIONS = 100
const float TIMEOUT_SECONDS = 30.0
const string API_VERSION = "v2"
const bool DEBUG_MODE = true
Module Organization
Flat Structure
For small projects:
project/
├── main.mux
├── math.mux
├── utils.mux
└── constants.mux
Hierarchical Structure
For larger projects:
project/
├── main.mux
├── lib/
│ ├── core/
│ │ ├── math.mux
│ │ └── utils.mux
│ ├── data/
│ │ ├── parser.mux
│ │ └── validator.mux
│ └── net/
│ ├── http.mux
│ └── tcp.mux
└── config/
└── settings.mux
Import Best Practices
- Import at the top - All imports at file beginning
- Avoid circular dependencies - Restructure if needed
- Use descriptive module names -
mathnotm - Alias long names -
import very.long.module.path as path - Group related functions - Put related utilities in same module
- One module per file - Keep file structure simple
- Document public APIs - Comment exported functions
- Avoid deep nesting - Keep module hierarchy shallow
Example Project
calculator/
├── main.mux
├── operations/
│ ├── basic.mux
│ └── advanced.mux
└── utils/
└── format.mux
// operations/basic.mux
func add(int a, int b) returns int {
return a + b
}
func subtract(int a, int b) returns int {
return a - b
}
// operations/advanced.mux
func power(int base, int exp) returns int {
auto result = 1
for _ in range(0, exp) {
result = result * base
}
return result
}
// utils/format.mux
func format_result(int value) returns string {
return "result: " + value.to_string()
}
// main.mux
import operations.basic as basic
import operations.advanced as advanced
import utils.format as fmt
func main() returns void {
auto sum = basic.add(5, 3)
print(fmt.format_result(sum))
auto powered = advanced.power(2, 10)
print(fmt.format_result(powered))
}
Technical Implementation
Module Compilation
- Parse imports - Extract all import statements
- Build dependency graph - Determine module order
- Process modules - Parse and analyze in topological order
- Generate init functions - Create module initialization code
- Link modules - Combine into final executable
Name Mangling Details
Module functions are prefixed with their module path:
// shapes/circle.mux
func area(float radius) returns float {
return 3.14159 * radius * radius
}
Generates: shapes_circle_area (module path becomes prefix)