Skip to main content

Module expr

Module expr 

Source
Expand description

A tiny pure expression language over the audio-analysis variables, compiled once at preset load and evaluated per parameter per frame.

Grammar (recursive descent, standard precedence):

expr   := sum  (('>' | '<' | '>=' | '<=' | '==' | '!=') sum)*
sum    := term  (('+' | '-') term)*
term   := unary (('*' | '/') unary)*
unary  := ('-' | '+')? primary
primary:= number | ident | ident '(' expr (',' expr)* ')' | '(' expr ')'

Comparisons sit at the lowest precedence and yield 1.0/0.0, so they compose with arithmetic (0.4 + (bass > 0.2) * 0.3) and with select. There are no boolean operators: with clean 0/1 results, min is and, max is or, and 1 - c is not.

One thing an expression reads is not a function of this frame’s analysis: a [latch] variable (ADR-0137). Its value is armed-and-fired state held in the render layer and written into the reserved slots of Variables once per preset per frame, before the params that read it. That leaves everything here intact — evaluation is still a pure, re-entrant function of the bundle it is handed, which is what lets one compiled expression run once per vertex or once per element — while making the bundle depend on the frames before it. A caller that runs no bank, and that is every probe and every single-frame capture, reads a latch at its rest value of 0.

Variables: bass mid treb onset beat bar time tempo novelty index, the per-vertex position x y rad ang, the absolute-level escapes bass_raw mid_raw treb_raw onset_raw, and the musical clock beat_index time_since_beat beat_in_bar bar_index bar_phase. The first four are normalized against their own recent peak (ADR-0049), so a threshold on them means “loud for this track” rather than naming a magnitude. bar is beat phase under a historical name; bar_phase is the real thing (ADR-0050). Constants: pi tau. Functions: sin cos abs floor sqrt log min max pow mod clamp lerp smoothstep select bin hash noise. Compilation is fallible (a malformed expression is rejected with a surfaced error, never a panic); evaluation of a compiled expression is total, panic-free, and allocation-free — it walks a prebuilt AST returning f32, so it is safe to call every frame (hot-path §5).

bin(x) is the one function that reads something other than its arguments: it samples the analysis frame’s log-spaced spectrum, which Variables carries by borrow (ADR-0036). The language stays scalar-only — there is no array type and no indexing syntax; the band array is reachable only through this call, at a normalized position, interpolated.

hash(x) and noise(x) are the grammar’s only randomness (ADR-0051), and they are random the way a shader is: pure functions of (argument, salt), where the salt is a per-preset constant Variables carries. Nothing here reads a clock or draws from an RNG — two evaluations of the same argument under the same salt are bit-identical, which is exactly what NFR §6 asks of visual randomness. Who supplies the salt is the preset’s business (see schema::Preset); this module only mixes it in.

Structs§

Expr
A compiled expression: parse once, eval every frame.
GateFlag
A gate that a run never exercised, with the source text that names it.
Observations
Per-AST-node reachability accumulated across a run of probed evaluations (ADR-0042). One of these belongs to one Expr.
Variables
A bound set of variable values for one evaluation. Field order matches VAR_NAMES; beat is the caller’s bool coerced to 0.0/1.0.

Enums§

ExprError
Why an expression failed to compile. Evaluation never errors.
GateKind
The four structural findings Expr::flag_gates reports.
NodeObservation
What one AST node did across a run.

Constants§

LATCH_CAP
How many [latch] entries one preset may declare (ADR-0137).
SATURATED_OCCUPANCY
Occupancy at or above which a clamp() is reported as Saturated — the fraction of hops its inner value may spend pinned at the upper bound before the binding stops being a function of the audio and becomes a constant (ADR-0062).
VAR_COUNT
Number of expression variables.
VAR_NAMES
The analysis variables an expression may reference, in slot order.

Functions§

compile
Compile a source expression into an evaluatable Expr, with no latch names in scope.
compile_with_latches
compile, with a preset’s [latch] names in scope (ADR-0137).
constant_names
Every bare identifier that resolves to a literal, in declaration order.
function_names
Every built-in function name, in declaration order.
is_identifier
Whether name lexes as a single identifier — [A-Za-z_][A-Za-z0-9_]*, the rule tokenize applies.
is_reserved_ident
Bare identifiers that resolve to a literal. Resolved before the variable lookup so they cannot be shadowed; an unknown bare name still errors. Whether name is already resolved by the grammar — a built-in variable (the reserved [latch] placeholders included), a named constant, or a function.
variable_names
Every variable name an expression may write, in VAR_NAMES order.