Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

One Structured Pipeline, Fully Traced

Consider open people.json | where active | get name | first 10.

1. Parsing produces calls and typed shapes

The parser resolves declarations from a working set, checks command signatures, and produces a block. Spans connect each expression and error to original source. Parser/type errors can accumulate before evaluation begins.

2. Evaluation separates global and local state

EngineState holds declarations, blocks, files, configuration, signals, and long-lived services. Stack holds variables, environment changes, redirection, and call-local state. eval_call borrows the engine, mutably borrows the stack, and moves pipeline input.

3. Commands receive one closed data enum

Command::run accepts PipelineData and returns Result<PipelineData, ShellError>. Each stage can preserve streaming, intentionally collect, or reject an incompatible input.

4. Iterator adapters keep rows lazy

ListStream owns a boxed Iterator<Item = Value> + Send. where, get, and first can wrap it with filter/map/take behavior. Upstream produces only when downstream calls next; first 10 naturally prevents parsing the remainder.

5. The sink chooses materialization

Display consumes values incrementally; assignment or a command needing a whole list calls into_value and collects. PipelineMetadata and spans travel beside the data so rendering and errors retain provenance.