Skip to content

Repository files navigation

The Wyzer Programming Language

Wyzer is a statically typed, compiled, resource-oriented programming language with integrated distributed safety via choreographic programming and a perceus memory model.

"Simplicity is not the absence of power. It is power without pretense." ~ Atiksh Sharma

What is Choreographic Programming? In traditional distributed programming, you write separate code for the client and the server, and hope their communication protocols match up. Choreographic programming allows you to write a single, unified view of the entire distributed system. The compiler then mathematically projects this single script into deadlock-free, independent binaries for each physical node (e.g., Client and Server).

What is the Perceus Memory Model? Perceus is a fast, deterministic memory management strategy that avoids the unpredictable pauses of a Garbage Collector and the complex annotations of a borrow checker. It uses precise reference counting to know exactly when a value has a single owner, allowing the compiler to mutate the data directly in place (FBIP) without making copies or pausing the program.


Design Principles

  • One ownership rule for everything: Manage memory, threads, and network resources using the exact same ownership model.
  • No garbage collector: Predictable, low-latency performance using Perceus reference counting.
  • No borrow checker: Write safe functional-style code without fighting complex lifetime annotations.
  • Deadlock-free by design: Network choreographies are verified and generated by the compiler.
  • Avoid hidden magic: Network transfers happen through explicit assignment, keeping the control flow readable and obvious.
  • C ABI compatibility: Built for systems programming and seamless interoperability.

Quick Example: Distributed Key-Value Store

In Wyzer, you write one program that describes how multiple systems talk to each other. The compiler automatically infers network sends and verifies ownership across nodes.

role @Client;
role @Server;

struct KVRequest {
    op: u8, // 0 for Get, 1 for Put
    key: str,
    value: str
}

fn main() {
    // Lock-free state owned securely by the Server
    var _store_key: str@Server = "";
    var _store_value: str@Server = "";

    // Client creates a Put request
    let put_req: KVRequest@Client = KVRequest { 
        op: 1, 
        key: "username", 
        value: "alice" 
    };
    
    // It is safely sent across the network by transferring ownership
    let server_req: KVRequest@Server = put_req;

    // Server updates its state without needing mutexes
    if server_req.op == 1 {
        _store_key = server_req.key;
        _store_value = server_req.value;
    }
}

Because Wyzer merges Choreography with Perceus linear typing, a network transfer acts as an absolute linear move. Transferring ownership of a variable across the network consumes it locally. Attempting to use it again produces a compile-time error:

Error [E001]: use of moved variable `put_req`
╭─▶ example.wyz:31:22
│
│ 30 │     
│ 31 │     std::io::println(put_req);
│    │                      ╰────── variable `put_req` used here after being moved
│ 32 │ }
│
├─▶ note: `put_req` is a linear resource and can only be used once
├─▶ help: consider passing it by reference if you need to use it multiple times
╰─────────────────────────────────────────────────

Example: Request/Response Choreography

Choreographies make complex network handshakes read like a single sequential function. Here, a client queries a server, and the server returns the result back to the client:

fn fetch_data(query: str@Client) -> str@Client {
    // client transfers query to Server
    let server_query: str@Server = query;
    
    // server processes query securely
    let server_result: str@Server = db_lookup(server_query);
    
    // server transfers result back to Client
    let client_result: str@Client = server_result;
    
    return client_result;
}

Example: In-Place Mutation (Perceus)

Wyzer uses the Perceus memory model, which determines variable lifespans via precise reference counting. If a variable is uniquely owned (refcount == 1), the compiler safely mutates the data in-place rather than allocating new memory (known as FBIP: Functional But In-Place).

struct User { id: u32, name: str }

fn update_name(user: User, new_name: str) -> User {
    // In traditional functional languages, this allocates a new 'User' struct.
    // In Wyzer, if 'user' has exactly 1 owner, the compiler mutates the existing 
    // memory in-place, achieving C-like speeds without a borrow checker!
    return User {
        id: user.id,   // Value retained
        name: new_name // Value overwritten in-place
    };
}

Documentation & Community

Community: Join our Discord server: https://discord.gg/RhpPhkTrVu

Notable Examples

About

The Wyzer Programming Language

Topics

Resources

Contributing

Stars

188 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages