pub struct ExecutionBounds {
pub max_call_depth: usize,
pub max_steps: Option<usize>,
pub max_alloc_bytes: Option<u64>,
pub guest_max_alloc_bytes: Option<u64>,
pub max_dispatch_steps: Option<usize>,
}Expand description
How much a blue program may do before it is refused: nested calls, evaluation steps and live bytes.
Each is a BOUND in the sense blue-lang-cli’s config module admits: a
terminating program under bounds above its cost returns the same value, and
one that exceeds either is refused with a catchable depth-exceeded or
fuel-exhausted error naming the limit and the function — never a process
abort, which is what exceeding the host stack was before tatara-lisp-eval
0.3.63. The walker and the VM run under the same bounds and refuse with the
same message. The two memory bounds refuse with a fatal memory-exhausted
(memory); a process past one exits a runaway.
Fields§
§max_call_depth: usizeNested (non-tail) calls alive at once. Tail calls do not count.
max_steps: Option<usize>Evaluation steps per run; None is unbounded.
max_alloc_bytes: Option<u64>Live bytes one evaluation of code its caller wrote may hold (blue run, an appliance, each test of blue test); None is unbounded.
Each process it spawns is held to the same bound, on its own account.
guest_max_alloc_bytes: Option<u64>Live bytes one evaluation may hold at a door that runs code it did not
write: a session (eval, repl, serve), live evaluation in the
editor, a project rule, a Bluefile. None is unbounded.
max_dispatch_steps: Option<usize>Implementations§
Source§impl ExecutionBounds
impl ExecutionBounds
Sourcepub const DEFAULT: Self
pub const DEFAULT: Self
Depth at tatara-lisp-eval’s DEFAULT_MAX_DEPTH, steps unbounded.
The two defaults differ for one reason: whether a program that works
today keeps working. A recursion past 100k frames never worked — it
aborted the process — so bounding depth removes no behaviour. A run
longer than any finite step count did work (simulations, tools on
nodes), so a default step bound would remove it; for a few hours of
2026-09-29 blue shipped 50M (~3 s) and did exactly that. A host that
runs code it did not write, or a test that must see a runaway end,
sets max_steps itself.
Memory follows the same test, door by door: a run holding more than
any finite count worked, so max_alloc_bytes is unbounded; a door
that runs code it did not write never promised that, so
guest_max_alloc_bytes is memory::GUEST_MAX_ALLOC_BYTES.
Sourcepub const UNBOUNDED: Self
pub const UNBOUNDED: Self
No bound at all: what Self::meet leaves any bounds as, so a
project that declares one bound states it over this.
Sourcepub fn meet(self, other: Self) -> Self
pub fn meet(self, other: Self) -> Self
The lesser of each bound in self and other, where None is no
bound: neither side can widen what the other bounds.
Sourcepub fn narrow<H: 'static>(self, interp: &mut Interpreter<H>)
pub fn narrow<H: 'static>(self, interp: &mut Interpreter<H>)
Hold interp to these bounds as well as its own budget: its depth
becomes the lesser of the two, and its steps the lesser of
max_steps and the steps its budget has left, counted from here.
Trait Implementations§
Source§impl Clone for ExecutionBounds
impl Clone for ExecutionBounds
impl Copy for ExecutionBounds
Source§impl Debug for ExecutionBounds
impl Debug for ExecutionBounds
impl Eq for ExecutionBounds
Source§impl PartialEq for ExecutionBounds
impl PartialEq for ExecutionBounds
impl StructuralPartialEq for ExecutionBounds
Auto Trait Implementations§
impl Freeze for ExecutionBounds
impl RefUnwindSafe for ExecutionBounds
impl Send for ExecutionBounds
impl Sync for ExecutionBounds
impl Unpin for ExecutionBounds
impl UnsafeUnpin for ExecutionBounds
impl UnwindSafe for ExecutionBounds
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.