knave-expand 0.13.2

The reading, scoping and expansion stages of knave
Documentation
use super::step_budget::StepBudget;
use crate::diagnostic::{Diagnostic, DiagnosticCode, Label};
use crate::source::Span;

pub struct LimitProblems;

impl LimitProblems {
    pub const BUILT_LIST_NESTS_TOO_DEEP: &'static str = "macro code built a list nested too deeply";
    const RAISED_LIMIT_FACTOR: u64 = 10;

    pub fn too_many_steps(limit: u64, span: Span) -> Diagnostic {
        Diagnostic::error(
            DiagnosticCode::MACRO_STEP_LIMIT,
            "macro code ran too many steps",
            Label::new(span, format!("this call passed {limit} macro steps")),
        )
        .with_note(format!(
            "the macro calls in one top-level form run at most {limit} steps: a step is one function call or one `recur`"
        ))
        .with_help(format!(
            "make the macro stop, or wrap the top-level form in `(with-macro-steps {} ...)`",
            limit
                .saturating_mul(Self::RAISED_LIMIT_FACTOR)
                .max(StepBudget::DEFAULT_LIMIT)
        ))
    }

    pub fn list_too_large(limit: usize, span: Span) -> Diagnostic {
        Diagnostic::error(
            DiagnosticCode::EXPANSION_TOO_LARGE,
            "macro code used a list too large to read as code",
            Label::new(span, format!("this call reads a list past {limit} forms")),
        )
        .with_note(format!(
            "a list that macro code passes to a built-in reads as at most {limit} forms, counting each shared part once per use"
        ))
        .with_help("build a smaller list, or stop repeating the same list inside itself")
    }

    pub fn value_nests_too_deep(limit: usize, span: Span) -> Diagnostic {
        Diagnostic::error(
            DiagnosticCode::EXPANSION_NESTS_TOO_DEEP,
            Self::BUILT_LIST_NESTS_TOO_DEEP,
            Label::new(span, format!("this call builds a list past {limit} levels")),
        )
        .with_note(format!(
            "lists that macro code builds nest at most {limit} deep"
        ))
        .with_help("make the macro stop nesting, or build a flatter list")
    }
}