use ir::GraphIr;

mod kind;
mod value;

/// Can collapse a [`GraphIr`] in meaningful ways and do interesting work on it.
///
/// It's surprisingly difficult to find a fitting description for this.
pub trait Evaluator {
    /// Take some [`GraphIr`] which will then be processed later.
    /// May be called multiple times, in which the [`GraphIr`]s should add up.
    // TODO: atm they definitely don't add up -- add some functionality to GraphIr to
    //       make it combine two graphs into one
    fn feed(&mut self, ir: GraphIr);

    /// Walk through the _whole_ [`GraphIr`] and run through each instruction.
    fn eval_full(&mut self);

    // TODO: for an LSP or the like, eval_single which starts at a given instr
}

/// The available [`Evaluator`]s.
///
/// Checklist for adding new ones:
///
/// 1. Create a new module under the [`kind`] module.
/// 2. Add a struct and implement [`Evaluator`] for it.
#[derive(Clone, Copy, Debug, Default, clap::ValueEnum, serde::Deserialize, serde::Serialize)]
pub enum Available {
    /// Runs fully on the CPU. Single-threaded, debug-friendly and quick to implement.
    #[default]
    Debug,
}

impl Available {
    /// Selects the [`Evaluator`] corresponding to this label.
    #[must_use]
    pub fn pick(&self) -> Box<dyn Evaluator> {
        match self {
            Self::Debug => Box::<kind::debug::Evaluator>::default(),
        }
    }
}
