use crate::compile::{
    block::{Compile, CompileContext, CompileValue},
    error::CompileError,
    syntax::{LetExpression, SetqExpression},
};

impl Compile for LetExpression {
    fn compile(&self, cx: &mut CompileContext) -> Result<CompileValue, CompileError> {
        cx.push_scope();
        let mut binding_indices = vec![];
        for binding in self.bindings.iter() {
            let index = cx.bind_local(binding.identifier.clone())?;
            let value = binding.value.compile(cx)?;

            cx.push(value)?;

            if self.sequential {
                // Mark initialized
                cx.init_local(index);
            } else {
                binding_indices.push(index);
            }
        }
        if !self.sequential {
            for index in binding_indices {
                // Mark initialized
                cx.init_local(index);
            }
        }
        let value = self.body.compile(cx)?;
        cx.pop_scope(Some(value))?;
        Ok(CompileValue::Stack)
    }
}

impl Compile for SetqExpression {
    fn compile(&self, cx: &mut CompileContext) -> Result<CompileValue, CompileError> {
        for assignment in self.pairs.iter() {
            let value = assignment.value.compile(cx)?;
            cx.compile_assign(assignment.identifier.clone(), value)?;
        }
        Ok(CompileValue::Nil)
    }
}
