Execution Model

Tick cycle, parallel semantics, termination, and scalar formatting.

The Sweep

The engine runs in sweeps. Each sweep:

1. Evaluate. Every switch computes its logic from its input wires, all at once.
2. Propagate. Every wire picks up the state of the switch driving it. Wires with conduction delay hold their previous state and count down before latching.
3. Check. If nothing changed, the grid has stabilized. That stable state is the program's output.

A program that holds a feedback loop never stabilizes: it oscillates. That is not an error. A sustained pulse is how a Sanguis program stays alive.

Parallel Semantics

All switches evaluate against the same snapshot: the wire states at the start of the sweep. So:

• Switch A's change is NOT visible to switch B until the next sweep.
• Regions run many local sweeps between global synchronizations (block-Jacobi iteration).

Deliberate. This is how hardware behaves. It is not a simulation of parallelism; it is parallelism.

Termination

The engine stops when:

• The grid stabilizes: no switch changed state in a sweep
• The maximum sweep count is reached, in which case the result is reported as oscillating rather than failed
• You close it. A running program that holds a pulse stops only when someone stops it, and the last state is kept.

Scalar Formatting

Scalars are formatted as %.4f (4 decimal places): 1.0000, 3.5000, 0.0000.

GPU Execution

The grid is uploaded to the GPU as buffer data. One fixed kernel evaluates switches and propagates wires: regions run many local sweeps between global synchronization barriers. The kernel is the same for every program; programs are data, never code. File I/O bridges to the CPU, the only operation that leaves the GPU.

Examples

Echo

Read a file and print its contents:

circuit echo;

cell main() -> float {
    let src = read_file("input.txt");
    print(src);
    emit 0.0;
}

Character Scanner

Iterate through text character by character:

circuit scanner;

cell main() -> float {
    let src = "Hello VANA!";
    let i = 0.0;
    while i < len(src) {
        print(char_at(src, i));
        i = i + 1.0;
    }
    emit 0.0;
}

Conditional Accumulator

Add numbers until a limit is reached:

circuit accumulator;

cell main() -> float {
    let total = 0.0;
    let step = 1.0;
    while total < 10.0 {
        total = total + step;
    }
    print(total);
    emit 0.0;
}

Note: Five operators: <, >, =, <=, >=.

File Processor

Read, transform, and write:

circuit file_processor;

cell main() -> float {
    let input = read_file("data.txt");
    let output = replace(input, "old", "new");
    write_file("result.txt", output);
    emit 0.0;
}