Ash is a minimalist, statically-typed systems language. Write readable code, compile to C, run native binaries — with a single dependency.
fn fib(n: int): int { if n <= 1 { return n } return fib(n - 1) + fib(n - 2) } fn main() { for i in 0..10 { print("fib(", i, ") =", fib(i)) } }
struct Person { name: string age: int } enum Status { Active, Inactive, } fn greet(p: Person): string { return "Hello, " + p.name } fn main() { alice := Person{ name: "Alice", age: 30 } print(greet(alice)) }
/tmp/ash_*.c.One dependency. Three platforms. Five minutes.
source ~/.bashrc ash version # should print: ...
ash init ash run main.ash
ash build main.ash ./main
Ash is a minimalist, statically-typed systems language that compiles to C via zig cc. It runs five phases — lexing, parsing, semantic analysis, C codegen, and zig cc — entirely in memory before producing a native binary.
Building a custom machine-code backend requires instruction selection, register allocation, and platform ABI handling for every target. Ash skips all that by emitting clean C99, then delegating to zig cc — a battle-tested LLVM-based compiler that ships as a single binary alongside Zig. Because Ash already requires Zig, every user has zig cc for free.
ash init # create main.ash ash run main.ash # compile + run ash build main.ash # compile to binary
Every Ash program has a main function. print is always available without an import.
fn main() { print("Hello, World!") }
ash run hello.ash # Hello, World!
Use := for inferred declaration, explicit annotation with name: type = value, or const for immutables.
// Inferred x := 10 name := "Ash" flag := true // Explicit count: int = 0 ratio: float = 3.14 // Constants const MAX = 100 const LIMIT: int = 50 x += 5 x -= 2
| Ash | C | Notes |
|---|---|---|
int | int64_t | 64-bit signed integer |
float | double | 64-bit IEEE 754 |
bool | int | true = 1, false = 0 |
string | const char* | UTF-8, null-terminated |
Functions can be defined in any order — a forward-declaration pass runs first.
fn add(a: int, b: int): int { return a + b }
fn divmod(a: int, b: int): (int, int) { return a / b, a % b } q, r := divmod(17, 5)
if x > 0 { print("positive") } else if x == 0 { print("zero") } else { print("negative") }
for i in 0..5 { print(i) } a := [10, 20, 30] for n in a { print(n) } i := 0 while i < 10 { i += 1 if i == 3 { continue } if i == 6 { break } print(i) }
switch lang { case "ash" => print("Ash!") default => print("unknown") }
a := [10, 20, 30] push(a, 40) last := pop(a) print(len(a), a[0])
b := ![1, 2, 3, 4, 5] b[2] = 77 for i in 0..5 { print(b[i]) }
struct Point { x: int; y: int } p := Point{ x: 10, y: 20 } print(p.x, p.y) p.x = 99
enum Direction { North, South, East, West, } dir := Direction.North print(dir)
import io name := io.input("Enter your name: ") io.write_file("out.txt", "Hello, " + name) content := io.read_file("out.txt") print(content)
import string s := "Hello, Ash!" print(str_upper(s)) // "HELLO, ASH!" print(str_slice(s, 0, 5)) // "Hello" print(str_contains(s, "Ash")) // 1 n := parse_int("123") // 123
import math print(sqrt(16.0)) // 4.0 print(abs(-42)) // 42 print(clamp(15, 0, 10)) // 10 print(sin(0.0)) // 0.0
import os print(argc()) home := getenv("HOME") print("HOME:", home)
Every release pulled live from GitHub. Stars, commits, and contributors update automatically.
mainAsh is open source under the MIT license. The compiler is written in Zig. Contributions, bug reports, and feature requests are welcome on GitHub.
View on GitHub →Ash is built in the open. Everyone is welcome.
good first issue on GitHub..ash programs to examples/ that show interesting patterns.Stuck? Here's where to start.
ash_runtime.c relative to its own executable. Make sure ash is inside a bin/ folder next to a runtime/ folder. Re-run install.sh to fix the layout.zig cc to compile programs. Install Zig 0.15+ from ziglang.org/download and make sure it's in your PATH.git pull, then re-run install.sh or install.bat. The installer overwrites the old binary and runtime files.xattr -d com.apple.quarantine ./yourprogram or allow it in System Preferences → Security & Privacy.zig cc is the C compiler Ash invokes. It is not optional. Zig is a single downloadable binary — installation takes under a minute.ash run, the generated C is written to /tmp/ash_main.c (Unix) or %TEMP%\ash_main.c (Windows). It is clean, human-readable C99.ash version), Zig version (zig version), OS, and the smallest .ash file that reproduces the problem. Open a discussion on GitHub. Describe what you expected, what happened, and include your platform and Ash version.
Open a Discussion →