Skip to main content

Modules

Oxide uses Rust's module system with intuitive keywords and visibility modifiers.

Inline Modules

Define modules within a file:

module utils {
public fn helper(): Int { 42 }

fn privateHelper(): Int { 0 } // Private to module
}

// Access module items using dot syntax
let x = utils.helper()

Transpiles to:

mod utils {
pub fn helper() -> isize { 42 }

fn private_helper() -> isize { 0 }
}

let x = utils::helper();

Nested Modules

module outer {
public module inner {
public fn deepFunc(): String { "deep" }
}

public fn outerFunc(): Int { 100 }
}

// Access nested items using dot syntax
let s = outer.inner.deepFunc()

External Modules

Load code from separate files:

// In main.ox - loads utils.ox or utils/mod.ox
external module utils
external module api

fn main() {
utils.doSomething()
api.endpoint()
}

Transpiles to:

mod utils;
mod api;

fn main() {
utils::do_something();
api::endpoint();
}

File Resolution

External modules are resolved as:

  • utils.ox - Single file module
  • utils/mod.ox - Directory module with submodules

Visibility Modifiers

Oxide uses intuitive visibility keywords:

OxideRustVisibility
(none) or private(none)Module-private
publicpubPublic everywhere
internalpub(crate)Crate-wide
protectedpub(super)Parent module

Basic Visibility

module helpers {
public fn publicFn(): Int { 42 } // Public everywhere
internal fn crateFn(): Int { 1 } // Crate-wide
protected fn parentFn(): Int { 2 } // Parent module only
private fn privateFn(): Int { 0 } // Module-private (explicit)
fn implicitPrivate(): Int { 0 } // Module-private (default)
}

Transpiles to:

mod helpers {
pub fn public_fn() -> isize { 42 }
pub(crate) fn crate_fn() -> isize { 1 }
pub(super) fn parent_fn() -> isize { 2 }
fn private_fn() -> isize { 0 }
fn implicit_private() -> isize { 0 }
}

Internal (Crate-Wide)

Use internal for items visible throughout the crate but not publicly:

module utils {
internal fn internalHelper(): Int { 42 }

internal struct InternalConfig(
debug: Bool,
maxRetries: Int
)
}

// Accessible from any module in the crate
fn main() {
let result = utils.internalHelper()
}

Protected (Parent Module)

Use protected for items visible only to the parent module:

module parent {
module child {
protected fn childHelper(): Int { 100 }
private fn privateToChild(): Int { 0 }
}

fn useChild(): Int {
child.childHelper() // OK - parent can access
}
}

// parent.child.childHelper() // Error! Not visible outside parent

Re-exports

Re-export items from other modules:

module internal {
public fn helper(): Int { 42 }
}

// Re-export at current level
public import internal.helper

// Re-export from standard library
public import std.collections.HashMap

Transpiles to:

mod internal {
pub fn helper() -> isize { 42 }
}

pub use internal::helper;
pub use std::collections::HashMap;

Import Statements

Import items for easier access using the import keyword with dot-separated paths:

import std.collections.HashMap
import std.io.{Read, Write}
import crate.utils.helper

fn main() {
let map = HashMap.new()
}

Aliased Imports

import std.collections.HashMap as Map
import crate.very_long_module_name.Type as ShortType

Glob Imports

import std.collections.*  // Import all public items

Glob-Except Imports

Exclude specific items from a glob import:

import std.prelude.* except (Vec, String)  // Import all except Vec and String

Type-Only Imports

Import only for type checking (no runtime effect):

import type serde.Serialize
import type serde.{Deserialize, Serialize}

Constants and Statics

const MAX_SIZE: Int = 1024
const PI: Float64 = 3.14159

static COUNTER: Int = 0
static var MUTABLE_COUNTER: Int = 0

Transpiles to:

const MAX_SIZE: isize = 1024;
const PI: f64 = 3.14159;

static COUNTER: isize = 0;
static mut MUTABLE_COUNTER: isize = 0;

Type Aliases

type Result<T> = std.result.Result<T, String>
type IntList = Vec<Int>
type Handler = fn(Request) -> Response

Project Structure

Typical Oxide project layout:

my-project/
├── Cargo.toml
├── src/
│ ├── main.ox # Binary entry point
│ ├── lib.ox # Library entry point (optional)
│ ├── utils.ox # Single file module
│ └── api/ # Directory module
│ ├── mod.ox # Module root
│ ├── routes.ox # Submodule
│ └── handlers.ox
├── tests/
│ └── integration.ox
└── examples/
└── demo.ox

main.ox

external module utils
external module api

fn main() {
utils.init()
api.start()
}

lib.ox

public external module utils
public external module api

public fn version(): String { "1.0.0" }

api/mod.ox

public external module routes
public external module handlers

public fn start() {
routes.register()
}

Prelude

Oxide automatically imports the stdlib prelude:

// These are automatically available:
// - StringExt, OptionExt, ResultExt
// - Array, Map, IteratorExt
// - abs, min, max, clamp
// - readFile, writeFile, etc.

To disable:

@file:[no_prelude]
// Manual imports required

Migration from Old Syntax

If you have code using the old use keyword with :: separators:

// Old syntax (deprecated, produces error)
use std::collections::HashMap
use std::io::*
use crate::utils::{helper, format}

// New syntax
import std.collections.HashMap
import std.io.*
import crate.utils.{helper, format}

See Also