Expand description
Canonicalisation of composition graphs.
Rewrites a CompositionNode into its canonical form so that
semantically equivalent graphs produce the same byte representation
(and therefore the same composition ID). The rules implemented here
are justified in docs/architecture/semantics.md; the property tests
in crates/noether-engine/tests/laws.rs check every law.
Rules (M1):
- Flatten nested
Sequentialinto a single list, left-to-right. - Collapse singleton
Sequential[s]tos. Retry { s, 1, _ }→s.Retry { Retry { s, n, d }, m, d }→Retry { s, n·m, d }when both delays match.Let { {}, body }→body.BTreeMapinParallel.branchesandLet.bindingsalready guarantees alphabetical ordering in the serialised form; no active rewrite needed.
What is not done in M1 (see semantics.md):
- Stage-level identity detection (needs stage metadata, M2).
Constabsorption (f >> Const→Const) — deferred to M2 so this module remains purely structural.- Dead-branch elimination when
Branch.predicateisConst(optimizer territory, M3).
Canonicalisation is idempotent: canonicalise(canonicalise(g)) == canonicalise(g). That’s tested as a law.
Functions§
- canonicalise
- Rewrite a node into its canonical form. Recurses through the tree bottom-up so each parent sees already-canonical children.