A general-purpose programming language built as a modern evolution of C.
Native compilation and direct control, rebuilt for modern software and tooling.
Website · Documentation · Releases · Community · Sponsor
C made native software portable, direct, and durable. Wave starts from those fundamentals and modernizes the language around them with modules, packages, generics, structured diagnostics, and cross-target tooling.
Wave is not a C dialect and does not aim for C source compatibility. It is a new general-purpose language with its own syntax, semantics, module system, and toolchain.
- General-purpose by design. Use the same language for applications, command-line tools, libraries, and freestanding software.
- Native and direct. Compile to executables, objects, assembly, LLVM IR, or bitcode without hiding target details.
- Machine access when needed. Use pointers, C ABI boundaries, inline assembly, and freestanding targets when system contracts must stay visible.
- Modern language structure. Organize code with modules,
pubvisibility, generics, structs, enums, variants,proto, and explicitvardeclarations. - Cross-target compilation. Generate code for x86-64, AArch64, and RISC-V 64 from supported compiler hosts.
- Tool-friendly interfaces. Query targets and compiler capabilities in human-readable or JSON form for build tools and editors.
Wave is under active pre-beta development. Syntax and toolchain contracts are being stabilized and may still change between releases.
fun main() {
var language: str = "Wave";
var count: i32 = 1;
println("Hello from {} #{}", language, count);
}
Save this as main.wave, then run it directly:
wavec run main.waveWave keeps each imported file in its own module namespace. A bare import names
a Vex dependency, a qualified package path names a source module, and ./
explicitly names a file relative to the importing module:
import("add");
import("add::math");
import("./helpers" as helpers);
import("add")::{sum, Point};
fun main() {
var qualified: i32 = add::sum(1, 2);
var selected: i32 = sum(1, 2);
var local: i32 = helpers::triple(3);
var point: Point = Point();
}
A Wave variable declaration always names its type; var value = ... is rejected.
A dependency named add resolves to its canonical src/lib.wave entry;
add::math resolves to src/math.wave. Only declarations marked pub can be
selected or accessed through another module:
fun internal_sum(a: i32, b: i32) -> i32 { return a + b; }
pub fun sum(a: i32, b: i32) -> i32 { return internal_sum(a, b); }
pub struct Point {}
pub controls Wave module visibility and is independent from export(c),
which controls the C ABI boundary. main is always a private entry point, so
pub fun main() is rejected. A module can deliberately forward public API with
pub import("module")::{symbol};.
Linux and macOS:
curl -fsSL https://wave-lang.dev/install.sh | bash -s -- latestWindows PowerShell:
irm https://wave-lang.dev/install.ps1 -OutFile install.ps1
powershell -ExecutionPolicy Bypass -File .\install.ps1 -LatestSee the installation guide for platform requirements and release selection.
# Check without producing a binary.
wavec check main.wave
# Build and run.
wavec run main.wave -- arg1 arg2
# Build an optimized hosted executable.
wavec -O2 build main.wave -o app
# Emit a freestanding RISC-V object.
wavec --target=riscv64-unknown-none-elf build kernel.wave --freestanding --emit=objThe compiler exposes its current capabilities instead of requiring tools to maintain hard-coded lists:
wavec print supported-targets
wavec print supported-input-types
wavec print supported-emit-kinds
wavec print target-spec --target riscv64-unknown-linux-gnu --format=jsonRun wavec --help for the complete CLI contract.
| Architecture | Hosted targets | Freestanding target |
|---|---|---|
| x86-64 | Linux GNU, macOS, Windows GNU | x86_64-unknown-none-elf |
| AArch64 | Linux GNU, macOS | aarch64-unknown-none-elf |
| RISC-V 64 | Linux GNU | riscv64-unknown-none-elf |
Hosted cross-linking requires a compatible linker, system libraries, and sysroot for the selected target. For Linux RISC-V 64, wavec discovers complete cross-toolchain sysroots automatically; an explicit --sysroot always takes precedence. Freestanding builds omit the default hosted runtime assumptions and are intended for kernels, firmware, boot code, and other no-OS environments.
Follow the Wave development setup, then build with the locked dependency graph:
git clone https://github.com/wavefnd/Wave.git
cd Wave
cargo build --lockedThe development compiler is written to target/debug/wavec. Before submitting compiler changes, run:
cargo fmt --all --check
cargo test --locked --all-targets
cargo clippy --locked --all-targets -- -D warnings
python3 tools/run_tests.py| Project | Role |
|---|---|
| Wave | Language frontend, compiler driver, LLVM backend, and standard library source |
| Vex | Manifest-based package manager and build tool |
| Whale | Native assembler, object tooling, and linker under development |
Useful project references:
Contributions are welcome through GitHub pull requests and email patches. Read CONTRIBUTING.md before submitting changes; all commits require a DCO Signed-off-by line.
- The compiler and repository components outside
std/are licensed under the Mozilla Public License 2.0. - The standard library in
std/is licensed separately under the Apache License 2.0, allowing modification, redistribution, and embedding under that license.
Wave is developed in public with support from individuals and organizations. You can contribute monthly or once through OpenCollective.
Thank you to everyone who contributes code, documentation, testing, funding, or time to Wave.