Skip to content

A compiled language for people who like Python

v1.20 Concurrency, fast and out of the box — read the release notes →

Feels like Python.Runs like C.Ships as one binary.

Wyn compiles to C and links a tiny runtime - no VM, no garbage collector. Memory is managed by reference counting, concurrency is spawn/await on coroutines, and a dependency is just a git URL.

struct Job {
    name: string
    ms: int

    fn report(self) -> string {
        return "${self.name} finished in ${self.ms}ms"
    }
}

fn run_job(name: string) -> int {
    return name.len() * 3   // stand-in for real work
}

fn main() {
    f1 = spawn run_job("resize")
    f2 = spawn run_job("transcode")

    jobs = [
        Job{name: "resize", ms: await f1},
        Job{name: "transcode", ms: await f2},
    ]

    for j in jobs {
        print(j.report())
    }
}
$ wyn run jobs.wyn
Compiled in 344ms
resize finished in 18ms
transcode finished in 27ms

Real program, real output - compiled on an Apple M3 Pro before publishing.

~290ms
hello-world build
~1.2s
release build
~2μs
spawn + await
50KB
hello-world binary
23,000
req/s · keep-alive, c=100

Measured on Apple M3 Pro - regenerate the req/s figure yourself with ./benchmarks/http_load.sh; method and details on the benchmarks page.

Zero to running

Project, tests, binary. The terminal transcripts below are unedited.

wyn new
$ wyn new myapp --template cli
✓ Created cli project: myapp/
myapp/wyn.toml
myapp/src/main.wyn
myapp/tests/test_main.wyn
myapp/README.md
wyn test
$ cd myapp && wyn test
Scanning: tests/
✓ starts_with
✓ upper
✓ split
✓ file roundtrip
4 tests passed
wyn build
$ wyn build src/main.wyn
✓ Built: src/main (51KB, 295ms)
$ ./src/main
myapp v0.1.0
Usage: myapp <command> [options]

The language in five tabs

Every tab compiles as shown. The output pane is the program's actual output.

fn count_primes(lo: int, hi: int) -> int {
    count = 0
    for n in lo..hi {
        if n < 2 { continue }
        prime = true
        d = 2
        while d * d <= n {
            if n % d == 0 { prime = false; break }
            d = d + 1
        }
        if prime { count = count + 1 }
    }
    return count
}

fn main() {
    // four cores, zero ceremony
    a = spawn count_primes(0, 1000000)
    b = spawn count_primes(1000000, 2000000)
    c = spawn count_primes(2000000, 3000000)
    d = spawn count_primes(3000000, 4000000)

    total = await a + await b + await c + await d
    print("primes below 4M: ${total}")
}
$ wyn run example.wyn
primes below 4M: 283146
Edit in playground ↗

Everything is an object - chain anything

Strings, arrays, and lambda results all chain through methods. Each snippet compiles as shown; the output line is the program's actual output.

strings.wynedit ↗
result = "wyn, is, neat".split(",").map((s) => s.trim().upper()).join(" > ")
print(result)
$ wyn run strings.wyn
WYN > IS > NEAT
arrays.wynedit ↗
nums = [5, 3, 8, 1, 9, 2]
top = nums.sort().reverse().slice(0, 3).sum()
print(top)
$ wyn run arrays.wyn
22
pipeline.wynedit ↗
words = ["compiler", "is", "an", "object", "pipeline"]
caps = words.filter((s) => s.len() > 2).map((s) => s.upper()).join(" ")
print(caps)
$ wyn run pipeline.wyn
COMPILER OBJECT PIPELINE

No VM, no GC

Automatic reference counting frees memory deterministically at scope exit. No pauses, no tuning flags, no runtime to install on the target machine.

Concurrency, fast and built in

spawn f() starts a coroutine; awaited tasks overlap cooperatively by default - no thread pool to size, no async coloring. Fire-and-forget spawn dispatches 1M tasks in ~0.7s.

Packages are git repos

wyn add web resolves to github.com/wynlang/web. Any host works, wyn.lock pins exact commits. No registry, no account, no publish step.

C is one import away

wyn bind header.h generates FFI bindings from a C header - proven against SQLite, lz4, and zstd. Forty years of C libraries, available directly.

Tooling in the box

Formatter, test runner, REPL, doc generator, LSP for VS Code and Neovim. One binary installs all of it.

Cross-compile anywhere

Linux, macOS, Windows targets from one machine - plus iOS, Android, and WebAssembly builds from the same source.

GPU dispatch (experimental)

Opt in with [gpu] in wyn.toml and [float].map runs on Metal or OpenCL. Experimental: float32, single-op, off by default; a runtime cost model falls back to CPU, and on our M3 Pro it has not yet beaten the CPU path end-to-end, so treat it as a spike rather than a speedup. Binaries still run with no GPU.

A web server is a for loop

The official web package is a thin layer over Wyn's native HTTP: parse the request, respond with a helper, spawn a handler per connection. The handler below loops, so the connection is reused: that sustains ~23,000 req/s with HTTP/1.1 keep-alive, and ~6,600 req/s when the client opens a fresh connection per request - zero failed requests either way, on an Apple M3 Pro. Reproduce both with ./benchmarks/http_load.sh.

$ wyn pkg add web
$ wyn run server.wyn
http://localhost:8080
server.wyn
import web

fn handle(conn: int) {
    // One coroutine per CONNECTION: keep serving it
    // until the client hangs up (read_request -> "").
    while true {
        req = web.read_request(conn)
        if req.len() == 0 { return }
        if web.is(req, "GET", "/") == 1 {
            web.html(req, 200,
                web.page("Hello", "<h1>Hello from Wyn</h1>", ""))
        } else {
            web.not_found(req)
        }
    }
}

fn main() {
    server = web.listen(8080)
    print("http://localhost:8080")
    while true {
        conn = web.accept(server)
        if conn > 0 { spawn handle(conn) }
    }
}

Where Wyn stands

An honest snapshot - including the rows we lose.

TraitWynGoRustPython
Native binary, no runtime install
No garbage collector
Sub-second buildssmall crates only-
List comprehensions, slices, in
Lightweight spawn/await tasks
Generators with yield
Mature ecosystem
Production track recordearly
Wynter - the Wyn wyvern emblem

Meet Wynter

Every Wyn install ships with a wyvern in the error messages. Install it, break something, and Wynter will point you at the line.

MIT License - v1.20.0