Features · Sandboxed

Sandboxed

A Program never reaches out and does something directly. Every effect is emitted as plain data into a named channel, and a driver, the only code that touches the outside world, drains that channel and carries it out. Your program logic stays pure and sandboxed.

State in, emissions out

Seen from the outside, a Program is a pure function of one cycle. Its state goes in; nothing else does. What comes out is a set of context emissions — typed values dropped into named channels: a line for the console, a tree for the interface, a request for the network. The program itself touches nothing. Drivers, sitting at the edge, drain those channels and do the real work, and they are the only impure part of the system.

state in program pure emissions channels drivers impure drivers write bindings back — into state, or a reverse
State in, emissions out, and back again — drivers are the only part that touches the world.

That boundary is the sandbox. Because only typed data crosses it — state in, emissions out — the logic can be run anywhere, against any set of drivers, with nothing of the outside world baked in.

Effects go through drivers

Writing a line, drawing the interface, making a request: each one is a value emitted into a channel, not an action taken on the spot. On every reactive cycle the runtime hands each driver the effects on its channel, and the driver does the real work. Swap the drivers and the same program runs in a terminal, a browser or a test harness, untouched.

STATE Text name = "world"
LET Text greeting = Text.Append "Hello, " name
Console.Line greeting

Console.Line does not print anything itself; it appends to the Console.Lines channel, and the console driver prints it on the next cycle.

A very simple interface

Because effects are just data, a driver is tiny: a factory that takes a callback for feeding values back in, and returns a process function called once per cycle with that channel's emissions. A new capability is just a new driver, nothing more.

const ConsoleDriver = {
  Driver: function (emit) {
    return function process(lines) {
      for (const line of lines) console.log(line);
    };
  }
};

Register it against a channel (here, Console.Lines) and every Console.Line in the program flows to it. Output-only drivers ignore emit; input drivers, such as a GPS receiver or a WebSocket, call it to push fresh values back into the reactive graph.

Driving values back in

So far this is all one direction: state in, emissions out. The way the world gets back in is that an emission can carry a binding — a handle the driver may write to. When a driver has a result (a typed line, a clicked button, a response off the network) it writes it into that binding, and that write is the only way anything outside the program reaches back inside.

A binding is one of two things. It may be backed directly by state, and the write simply sets that state. Or it may be a reverse binding, and the write triggers a reverse tree: the change runs backwards through the calculations behind it and fans out onto the state at its leaves. Either way the next cycle re-runs the program with the new state, and fresh emissions go out.

driver impure reverse binding state state writes
Writing a reverse binding builds a reverse tree — the change fans out to the state at its leaves. A plain state binding is just a direct write.

This is the join between the two features. Sandboxing decides what may cross the boundary — typed emissions out, binding writes in — and reversibility decides where a write lands. A driver never touches state directly; it writes a binding, and the program works out the rest.

Snapshots

Because the logic is pure and nothing of the outside world lives inside it, the state of a running application is easy to snapshot at any point. The snapshot is just data: capture it, set it aside, and later restart the program from exactly that state. The drivers reconnect, read what the program now wants done, and carry on from where it left off, as if it had never stopped.

That one capability covers a lot of ground: