Source Cells
Grammar
source_decl = "source" identifier cell_type_init [ cell_filter ] [ require_block ] ";".
A source declaration looks exactly like a cell
declaration: the same cell_type_init (a type, an initializer, or both), evaluated the same
way, with no cell scope; the same optional trailing filter clause and require
block. source and cell even share one namespace with out, so declaring source width and
cell width in the same sheet is the same “duplicate cell” error two cell width declarations
would be.
sheet resize {
source width: i32 = 1920;
source height: i32 = 1080;
out area := width * height;
}
Both width and height above are declared source: ordinary inputs to the out that
multiplies them, with nothing in this sheet ever claiming either as a relationship or
conditional output.
Always a source, never derived
A source cell is the mirror image of an out cell. Where an out cell is
always derived by its own fixed writer, a source cell is always left alone by the solver:
never claimable as a relationship binding’s output, a conditional branch’s output, or an
out’s own writer target. Naming a source cell on a binding’s left-hand side is an error.
A plain cell’s source/derived status is a per-round decision the solver makes from
strength — the same cell might be a
source in one round and derived in the next, depending on what’s been written recently. A
source cell opts out of that entirely: whatever a host last wrote to it (or its own declared
initializer, before any write) is always its value, unconditionally.
A source cell can be filtered too
A source cell is ordinary in every other respect: it can be read anywhere a plain cell
can, written directly at any time (that’s the whole point — a source cell always reflects
whatever was last supplied from outside the sheet), can carry a require block for domain
diagnostics, exactly like a cell or out:
sheet s {
source width: i32 = 1920 require {
@positive width > 0;
};
}
and can carry a filter clause, exactly like a cell or out: whatever a host
writes to a filtered source cell is conformed the same way a filtered plain cell’s value
is, live, whenever the sheet resolves:
sheet s {
source level: i32 = 50 filter 0..=100;
}
See the filters chapter for filter’s full rules — everything there applies to a source
cell unchanged.