perf: add `etaReduceWithCache` for efficient eta reduction with explicit cache

`etaReduceWithCache` takes and returns a `HashMap ExprPtr Expr` cache
explicitly, enabling the canonicalizer to thread a single cache across
multiple expressions. The traversal eta-reduces lambdas eagerly: if a
lambda is eta-reducible, it visits the reduced form directly instead of
descending into the binder types.

`etaReduceAll` is now a thin wrapper around `etaReduceWithCache`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 file changed