graphcal_compiler/stack.rs
1//! Stack-growth helper for recursive walkers over user expressions.
2//!
3//! The compiler pipeline (desugar, HIR lowering, dependency
4//! collection, dimension inference), the evaluators, the formatter, and the
5//! LSP symbol walker all recurse once per expression-tree level. Structural
6//! *nesting* is bounded by the parser
7//! ([`crate::syntax::parser::MAX_NESTING_DEPTH`]), but left-nested operator
8//! *chains* (`1.0 + 1.0 + …`) are parsed iteratively and produce trees whose
9//! depth equals the chain length — a few hundred terms is realistic in
10//! engineering files and used to overflow the stack in debug builds.
11//!
12//! Every recursive walker calls [`with_stack_growth`] once per recursion
13//! level so the stack grows on demand instead of aborting the process.
14
15/// Red zone: grow when less than this much stack remains.
16const RED_ZONE: usize = 64 * 1024;
17
18/// Size of each new stack segment allocated by [`stacker::maybe_grow`].
19const STACK_PER_GROWTH: usize = 1024 * 1024;
20
21/// Run `f`, growing the stack on demand when the remaining stack is low.
22///
23/// Call this at the entry of every function that recurses once per
24/// expression-tree level. The check is a cheap stack-pointer comparison in
25/// the common (no-growth) case.
26pub fn with_stack_growth<T>(f: impl FnOnce() -> T) -> T {
27 stacker::maybe_grow(RED_ZONE, STACK_PER_GROWTH, f)
28}