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.
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.
Typical threaded runtime
worker pool · shared queueSanguis fleet
fleet rod cells 16 ticks 32;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; }
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 awaitsSanguis tasks
turn = 1,000 stepsWhat 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; }
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.
| Program (benchmark v3, 3.9.4) | Bridge ms | C floor ms | Metal ms | Identical |
|---|---|---|---|---|
| fib_25 · 242,785 calls | 137.84 | 152.60 | 85.23 | yes |
| loop_1m · 1,000,000 iterations | 76.79 | 519.69 | 245.74 | yes |
| tasks_4x250k · 4 tasks taking turns | 76.70 | 513.61 | 263.16 | yes |
| tasks_spawn_demo | 76.26 | 13.30 | 23.00 | yes |
| exp_80pts | 76.22 | 6.78 | 21.19 | yes |
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.
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.
lib/compiler.sanguis · 3,181 lines9fbca034b41df05b93780079e9d325744e7932955bb9b92514cf47b04649ada9SHA-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.
Fast as well as exact.
Compiling the 17,000-line linker
Benchmark v3, 2026-10-27, median of 1 run for the linker compile. Bars to scale.
Fleets: more threads, same bytes
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.
exp over 80 points, same bytes on all three executorsA 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.