makers 0.8.0

a POSIX-compatible make implemented in Rust
use eyre::{Result, WrapErr};
use std::io::{BufRead, Cursor};
use std::rc::Rc;

use super::{FinishedMakefileReader, MacroSet, MakefileReader};

pub struct DeferredEvalContext<'parent, 'args, 'grandparent, R: BufRead> {
    parent: &'parent MakefileReader<'args, 'grandparent, R>,
    children: Vec<FinishedMakefileReader>,
}

impl<'parent, 'args, 'grandparent, R: BufRead>
    DeferredEvalContext<'parent, 'args, 'grandparent, R>
{
    pub const fn new(parent: &'parent MakefileReader<'args, 'grandparent, R>) -> Self {
        Self {
            parent,
            children: Vec::new(),
        }
    }

    pub fn push(&mut self, child: FinishedMakefileReader) {
        self.children.push(child);
    }

    pub fn eval(&mut self, to_eval: String) -> Result<()> {
        let child_stack = self.parent.stack.with_scope(&self.parent.macros);
        let child_macros = MacroSet::new();
        let child = MakefileReader::read(
            self.parent.args,
            child_stack,
            child_macros,
            Cursor::new(to_eval),
            "<eval>",
            Rc::clone(&self.parent.file_names),
        )
        .context("while evaling")?
        .finish();
        self.push(child);
        Ok(())
    }
}

impl<'parent, 'args, 'grandparent, R: BufRead> IntoIterator
    for DeferredEvalContext<'parent, 'args, 'grandparent, R>
{
    type Item = FinishedMakefileReader;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.children.into_iter()
    }
}