statically typed · batteries included · native binaries

The Ξ programming
language.

A language for building microservices and enterprise software, with dependency injection, function intent, and refined types as first-class citizens. Compiled to native binaries.

$ brew install code-by-sia/xi/xi
◇ batteries included DI, decision tables, state machines, typed events, a web framework and a test runner ship with the language. Building a service needs no packages.
The language

What makes Ξ different.

Ideas that usually live in frameworks and conventions are, in Ξ, features of the language itself.

01

Refined types

Constraints live in the type. Values are checked at construction, so a partially-valid instance can never exist.

Number where value >= 0
02

Function intent

Every function declares its kind: mapper, predicate, consumer, producer and more. Purity and effects are part of the signature, and the compiler enforces them.

mapper · predicate · consumer
03

Dependency injection

Declare deps { } and the compiler wires it. No container, no registration, no reflection.

deps { logger: Logger } · how it works ↓
04

Guarded overloading

One name, many bodies: the first where guard that holds wins. It is exactly how std/web routing works.

where res.status == 200
05

Decision tables

Business rules as first-class DxT tables, alongside atoms, state machines, interrupts and pub/sub events.

DxT · atoms · machines ↓
06

Errors as values

T! result types, ok/err, and ? propagation. Failures are values you handle, not surprises.

let row = load(id)?
07

Concurrency

async spawns a worker and returns a Future immediately. await all joins them, in order.

await all jobs
08

No null

Absence is typed. Optionals (T?) unwrap with if let; empty gives the zero value. null does not exist.

if let row = find(7) { … }
09

Sum types & match

Algebraic types with payload-binding match. Lowered to plain tagged unions.

match s { Circle c -> … }
10

Interrupts

Resumable conditions. A function signals and suspends while the caller decides whether to resume or abandon it.

signal · recover · skip ↓
11

Typed events

Built-in pub/sub. Producers publish a DTO; listeners receive the typed value. No JSON inside the process.

publish · listener · Events.run ↓
12

Native output and WASM

Compiles to a standalone binary, or to WebAssembly with --target wasm. No VM, no garbage collector.

xc app.xi → ./build/app
◇ the heart of Ξ

Dependency injection is the language.

Every serious codebase ends up bolting on an IoC framework with annotations and a runtime registry. In Ξ the compiler does the injection: you declare what you need and the wiring is derived from your code.

01

Declare, never construct

A class lists what it needs in a deps { } block. It never news up its own collaborators, so constructor plumbing disappears from the codebase.

02

Discovery over registration

Implementations are discovered and wired automatically at compile time. There is no container to configure and no reflection involved. A missing dependency is a build error rather than a runtime surprise.

03

Everything is injectable

The entry takes dependencies as parameters. Classes, listeners and even decision tables declare deps. Lifetimes are explicit: singleton or transient.

04

bind is the override, not the rule

You only write bind to choose between implementations or swap in a test double. Zero bindings is the normal case.

checkout.xi XI
{{ diCodeHtml }}
Machinery

Rules, state, and flow are built in.

Rules engines, state stores and state machines are language constructs in Ξ. All three are ordinary values, and all three are injectable.

DxT · decision tables

Business rules as tables.

A decision is a function kind whose body is a set of when → result arms, read top to bottom until the first match wins. The rule set your product owner writes on a whiteboard is the code.

Two forms: when <cond> => <result> arms, or a tabular grid of in columns and an out column
A declared hit policy: with hit first the first matching arm wins
A function kind like any other: injectable, and arms can call predicates
quote.xi XI
{{ dxtHtml }}
Atoms · active-state stores

State without setters.

An atom holds an immutable state that can only change through transition reducers, so every change is named and typed.

Read with .current; the state is immutable and there are no setters
transition reducers take the state and return a new one; call them with just the extra args
.undo() / .canUndo() give you history for free
cart.xi XI
{{ atomHtml }}
Machines · finite state machines

State machines as values.

A machine declares named states, machine-wide data, and transitions with parameters. Machines are immutable: every transition returns a new value.

where guards and update clauses on every transition
Ask before you leap with .can(...)
An illegal move raises IllegalTransition, a resumable interrupt you can recover from
door.xi XI
{{ machineHtml }}
Interrupts · resumable conditions

Errors you can resume.

A function signals a condition and suspends. The enclosing try/catch decides what happens next. Where an exception unwinds the stack, an interrupt lets the caller repair the situation and continue.

interrupt declares a typed condition with a payload
recover runs the restart and resumes at the signal point
skip abandons the suspended computation instead
api.xi XI
{{ interruptHtml }}
Events · typed pub/sub

Publish typed values.

Producers publish(topic, dto); a listener receives the typed value with zero serialization in process. Bind a transport to cross the network; producers and listeners never change.

The listener kind subscribes with on "topic"; each delivery resolves fresh deps
In-memory queue by default; drain with Events.run() or Events.runAsync()
Bind PublisherService / ConsumerService to go external
shop.xi XI
{{ eventHtml }}
Batteries included

The framework is in the box.

A typed web framework, a test runner, configuration and C interop ship with the toolchain. Building a service needs no packages.

std/web

A web framework in the standard library.

Implement WebRequestHandler and match requests with web.route in where guards. Params and bodies decode into your types; responses serialize themselves. HTTPS and HTTP/2 are opt-in flags.

users.xi XI
{{ webHtml }}
xt · testing

Tests live next to the code.

test blocks are excluded from normal builds and run with xt. Tests get dependencies injected, and module Test bindings swap in test doubles without a mocking library.

calc_test.xi XI
{{ testHtml }}
Typed configuration

Config is an interface bound to a file: bind AppConfig -> readConfig("app.yaml"). YAML, JSON or XML, with hot-reload included.

C interop

Port a C library by declaring it: an extern "C" block plus a link directive. The signatures are the binding.

Collections

List, Map, Set, Stack, Queue, SortedQueue are built-in generics. No imports needed.

Standard library

math · text · json · yaml · xml · crypto · fs · net · http · thread · process · time

The toolchain
xc app.xicompile to a native binary
xirun tool + interactive REPL
xt calc_test.xirun the tests
xi installfetch module dependencies
xi packpackage a library for others
loadtest --bench app.xiload & perf testing
xc --target wasmcompile to WebAssembly
xi updateself-update the toolchain
◇ showcase

eXstream is a music-streaming service built in Ξ: microservices behind an API gateway, JWT auth, a React front end, Docker deployment.

code-by-sia/eXstream ↗
Examples

A taste of Ξ.

{{ activeFilename }} XI
{{ activeLineNumbers }}
{{ activeHtml }}
Getting started

Up and running in a minute.

On macOS (Apple Silicon & Intel) and Linux. You just need a C compiler on your PATH.

01

Install with Homebrew

Or grab a prebuilt tarball from the releases page and put its bin/ on your PATH.

$ brew install code-by-sia/xi/xi
02

Two tools, one toolchain

You get xc, the compiler, and xi, the run tool and REPL.

$ xc --version
$ xi repl
03

Write a program

Save a file with the .xi extension. Every program has an entry and a module.

{{ startCodeHtml }}
04

Compile & run

One command compiles to a native binary and runs it.

$ xc greeting.xi && ./build/greeting
Playground

Try Ξ in the browser.

A simulated editor. Pick an example, edit it, and run to see the compiler output.

console
{{ playOutputHtml }}
// press Run to compile and execute