Skip to main content

Module when

Module when 

Source
Expand description

The when expression language — bounded DSL for gating rules on facts.

Grammar (hand-written recursive-descent; no parser combinator):

expr       := or_expr
or_expr    := and_expr ('or' and_expr)*
and_expr   := not_expr ('and' not_expr)*
not_expr   := ['not'] cmp_expr
cmp_expr   := primary [cmp_op primary]
cmp_op     := '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'matches'
primary    := literal | ident_or_call | '(' expr ')'
literal    := STRING | INT | BOOL | 'null' | list
list       := '[' [expr (',' expr)*] ']'
ident_or_call := NS '.' NAME ['(' [expr (',' expr)*] ')']
NS         := 'facts' | 'vars' | 'iter'

Design choices (all load-bearing):

  • No arithmetic. Only comparison.
  • Function calls limited to a fixed set on the iter namespace. iter.has_file("Cargo.toml") is supported; arbitrary user-defined calls are not. Use declared facts: for repo-level computation.
  • iter.* is only meaningful in iteration contexts (per-iteration when_iter: on for_each_*, and nested rules’ when:). Outside those, iter.X evaluates to null and iter.has_file(_) to false.
  • matches RHS must be a string literal. This lets us compile the regex at parse time; dynamic patterns stay out of the hot path.
  • Short-circuit and / or. Unevaluated branches don’t even touch their subtree.
  • Type coercion is explicit, not silent. Comparing Int to String is an error, not false.

Structs§

IterEnv
Iteration context exposed to when: expressions through the iter.* namespace. Built once per iterated entry by for_each_* rules and threaded into both the outer when_iter: filter and any nested rule’s when:.
WhenEnv

Enums§

CmpOp
Namespace
Value
WhenError
WhenExpr

Functions§

parse