PEGO

E010: Value-Free Rule Bodies

A rule can consume input without retaining the intermediate tree used to match its body. This removes Node and child-list construction when an action needs named captures but no positional body values.

Mechanism and Invariants

leanBody selects value-free lowering for an action that does not read positional body values ($n). Streaming bodies keep their general route. Captures still build the values their actions need.

type B = { B node[string] }
rule ws = [ ]+
rule b = [a-z]
rule a = ws b:b ws => B{B: $b}

a needs $b, but no positional body value. Both ws calls still match and consume whitespace; their unused Node values are omitted. Capture b still builds the value stored in B.B. If ws has its own action, ordinary parsing still evaluates it: an unused call result does not authorize skipping the callee's action. CST twins, Operators Rule line elision and recognition are separately analyzed mechanisms.

Scope and State

Applied by default to eligible bodies in closure, both VMs, generated Go Node, typed Go and TypeScript. It does not mean that every value inside a lean body is discarded.

Reference Control

No body-elision-only same-source control is maintained across all backends. Comparing recognition with a valued parse changes the requested operation and cannot isolate this mechanism.

Evidence and Implementation

Record 001 reports historical JSON from 442 to 144 ms and 183 to 76 MB for the combined body/twin/transient-rule change. That result cannot be attributed wholly to body elision; current isolated all-backend effects are unmeasured.

Evidence records: 001.

Source owners: leanBody, Walker.compileRule, body value lowering, direct body build mode, TypeScript body build mode.

The comparison policy distinguishes same-source controls, historical changes and full checkpoints.

Related mechanisms: E020, E030, E040, R120.

Optimization Catalog