///|
/// Limits applied while executing a compiled rule.
///
/// The step budget makes evaluation time predictable for rules accepted from
/// external users. A step is consumed whenever an AST node is visited.
pub(all) struct EvaluationLimits {
max_steps : Int
} derive(Eq, Debug, ToJson, FromJson)
///|
/// A conservative budget that is far above ordinary API validation rules.
pub fn EvaluationLimits::default() -> EvaluationLimits {
{ max_steps: 100000 }
}
///|
priv struct EvaluationBudget {
max_steps : Int
mut consumed_steps : Int
}
///|
fn EvaluationBudget::new(limits : EvaluationLimits) -> EvaluationBudget {
{ max_steps: limits.max_steps, consumed_steps: 0 }
}
///|
fn EvaluationBudget::consume(
self : EvaluationBudget,
span : Span,
) -> Unit raise RuleFailure {
self.consumed_steps = self.consumed_steps + 1
if self.consumed_steps > self.max_steps {
eval_fail(
"E024",
"evaluation exceeded the configured step limit",
span,
hint="Simplify the expression or explicitly raise max_steps for trusted rules.",
)
}
}
///|
fn validate_evaluation_limits(
limits : EvaluationLimits,
) -> Result[Unit, Diagnostic] {
if limits.max_steps <= 0 {
Err(
Diagnostic::new(
Configure,
"C011",
"evaluation step limit must be a positive integer",
Span::new(0, 0),
hint="Set max_steps to at least 1.",
),
)
} else {
Ok(())
}
}