VolkanaDEV
Live demo · runs in your browser

Run it twice.
Get the same world.

Life only becomes science when you can replay it. Most languages hand you a slightly different answer every time threads race. Sanguis gives the same bytes on one thread or sixteen, on a PC, a C floor or bare metal. Push the buttons below and watch both worlds run.

Experiment 1 · fleets and crosstalk

Sixteen cells share heat. Only one world agrees with itself.

A rod of 16 living cells. Cell 0 is held at 100 degrees. Every tick each cell sends its heat to its neighbours and to itself, then reads its inbox. Spread the cells over worker threads the usual way and messages land in whatever order the threads finish. Sanguis delivers them at a barrier, in sender order, so the result is the same on any thread count.

Threads

Typical threaded runtime

worker pool · shared queue
tick 0 → 31
cell 0colour = threadcell 15
output fingerprint…
0runs
0unique outputs

Sanguis fleet

fleet rod cells 16 ticks 32;
tick 0 → 31
cell 0colour = threadcell 15
output fingerprint…
0runs
0unique outputs

What is real here. The Sanguis column prints the exact bytes of tests/fixtures/fleet_heat.expected from the 3.9.5 repo, which the test suite checks on every thread count and on the C floor and metal. The heat map is the same arithmetic recomputed in your browser. The left column is a simulation of the same program on an ordinary worker pool, where each inbox arrives in finishing order. Yellow lines differ from that side's previous run. With 1 thread it stops racing, which is the point: the usual fix for a race is to give up the threads.

Show the Sanguis program (fleet_heat.sanguis)
circuit fleet_heat;

// FLEETS (3.9.5): sixteen cells on a rod. Each keeps its own heat by sending
// it to itself and shares it with its two neighbours; cell 0 is held at 100.
// Messages arrive in sender order, so a cell's own value sits right after its
// left neighbour's.
cell rod(id: float, tick: float) -> float {
    let got = inbox();
    let mine = 0.0;
    gate id == 0.0 then { mine = 100.0; }
    let near = 0.0;
    let count = 0.0;
    gate tick > 0.0 then {
        let me_at = 1.0;
        gate id == 0.0 then { me_at = 0.0; }
        let k = 0.0;
        for v in got {
            gate k == me_at then { mine = v; } else { near = near + v; count = count + 1.0; }
            k = k + 1.0;
        }
    }
    gate id == 0.0 then { mine = 100.0; } else { mine = mine + 0.25 * (near - count * mine); }
    gate id > 0.0 then { send(id - 1.0, mine); }
    send(id, mine);
    gate id < 15.0 then { send(id + 1.0, mine); }
    let words = [];
    gate mod(tick, 8.0) == 7.0 then {
        words = push(words, concat("t", tick));
        words = push(words, concat("cell ", id));
        print(concat(concat(words[0.0], " "), concat(words[1.0], concat(" heat ", mine))));
    }
}

cell main() -> float {
    print("rod of 16 cells, 32 ticks");
    fleet rod cells 16 ticks 32;
    print("cooled");
    output 0.0;
}
Experiment 2 · tasks that take turns

while true {} cannot stop the world.

Five tasks share one machine. One of them, runaway, loops forever and never gives up its turn. In a cooperative runtime such as JavaScript promises or Python asyncio, a task that never awaits holds the loop until the process is stopped. In Sanguis a turn is 1,000 steps, and a step is a call or a loop going round, never time. Every task is switched out on schedule, and watchdog gets its turn to stop it.

Cooperative async loop

a task runs until it awaits

Sanguis tasks

turn = 1,000 steps

What is real here. The Sanguis column replays tests/fixtures/spawn_tasks.expected line for line, with two tasks renamed for this page. That's the output tests/tasks.rs checks on the bridge, the C floor and metal. The left column shows the order a cooperative loop would run the same tasks in. There's also a built-in limit: spawn f() limit 50000 stops a runaway by itself with task 'name' went past its limit and was stopped, while the others carry on.

Show the Sanguis program (spawn_tasks.sanguis)
circuit sp2;

cell sq(x: float) -> float { output x * x; }

cell worker(tag: string, steps: float, every: float) -> string {
    let i = 0.0;
    let acc = [];
    while i < steps {
        acc = push(acc, sq(i));
        gate mod(i, every) == 0.0 then {
            print(concat(tag, concat(" at ", concat(i, concat(" sum ", total(acc))))));
        }
        i = i + 1.0;
    }
    let last = concat(tag, " finished");
    emit last;
}

cell total(xs: list) -> float {
    let s = 0.0;
    for x in xs { s = s + x; }
    output s;
}

cell parent() -> float {
    print("parent spawns a child");
    spawn worker("child", 300.0, 100.0);
    let k = 0.0;
    while k < 3.0 { print(concat("parent ", k)); k = k + 1.0; yield; }
    output 0.0;
}

cell runaway() -> float {
    let n = 0.0;
    while true { n = n + 1.0; gate mod(n, 500.0) == 0.0 then { print(concat("runaway ", n)); } }
    output 0.0;
}

cell main() -> float {
    spawn worker("w1", 900.0, 150.0);
    spawn worker("w2", 600.0, 200.0);
    spawn parent();
    let v = spawn runaway();
    spawn watchdog(v);
    run_all();
    print(last);
    print("done");
    output 0.0;
}

cell watchdog(id: float) -> float {
    let j = 0.0;
    while j < 2500.0 { j = j + 1.0; }
    print("watchdog steps in");
    kill(id);
    output 0.0;
}
Experiment 3 · three executors

A JIT, a C interpreter and bare metal. One output.

The same compiled BloodCode runs on three completely different executors: the bridge compiles it to machine code on the PC, the C floor interprets it, and the metal executor runs it with no operating system underneath. Task switches happen at the same step on all three, so the bytes match exactly.

BridgeJIT to x86-64 machine code
fingerprint…
C floorboot/bc_exec.c interpreter
fingerprint…
Bare metalfreestanding, no OS
fingerprint…
Waiting for three outputs
Program (benchmark v3, 3.9.4)Bridge msC floor msMetal msIdentical
fib_25 · 242,785 calls137.84152.6085.23yes
loop_1m · 1,000,000 iterations76.79519.69245.74yes
tasks_4x250k · 4 tasks taking turns76.70513.61263.16yes
tasks_spawn_demo76.2613.3023.00yes
exp_80pts76.226.7821.19yes

From the 3.9.4 benchmark (Windows 11, Intel 12th gen, median of 5 runs, process start included). Bridge times carry about 61 ms of process start; take that off and the million-iteration loop runs in about 16 ms, and so does the same work split over four tasks taking turns.

Experiment 4 · the compiler eats its own tail

It compiles itself to the same bytes.

The Sanguis compiler is written in Sanguis. Feed its source to the compiled compiler and it rebuilds itself, bit for bit, in both tiers. A self-hosting compiler that reproduces itself exactly is a proof that nothing in the toolchain drifts.

sourcelib/compiler.sanguis · 3,181 lines
generation 19fbca034b41df05b93780079e9d325744e7932955bb9b92514cf47b04649ada9
generation 2
generation 3

SHA-256 of the shipped lib/compiler.bc in the 3.9.5 repo. Each rebuild of the compiler by itself gives this file back; the lines below fill in as the loop comes round, matching character by character.

The measured numbers

Fast as well as exact.

Compiling the 17,000-line linker

18× faster
v2.5
15,505 ms
v3.9.4
843 ms

Benchmark v3, 2026-10-27, median of 1 run for the linker compile. Bars to scale.

Fleets: more threads, same bytes

1 thread
1.0×
2 threads
1.9×
4 threads
3.3×
8 threads
4.1×
20 threads
4.8×

3.9.5 on our Intel 12th-gen PC, 64 cells, speed-up over 1 thread; bars run 0 to 5×. Every run printed the same bytes, and so did the C floor and metal. Past 8 threads the gain flattens on this chip's slower efficiency cores. A separate 4-core run measured 1.90× on 2 and 3.01× on 4.

452 / 0tests passed / failed in 3.9.5, including the self-host check
4.4e-15median relative error of the pure-Sanguis exp over 80 points, same bytes on all three executors
29frozen BloodCode instructions. Tasks and fleets added no new ones.
Why an artificial life company built a language

A living thing you can rewind.

We grow beings that live in time, many cells at once, talking to each other every tick. If the same life lived twice comes out different, nothing about it can be checked. Sanguis makes every tick replayable on every machine.

See the numbers