microcad-lang 0.5.0

µcad language
Documentation
// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
// SPDX-License-Identifier: AGPL-3.0-or-later

//! If statement evaluation.

use microcad_lang_base::{PushDiag, SrcReferrer};

use crate::{eval::*, lower::ir, model::*, value::*};

impl Eval<Value> for ir::IfStatement {
    fn eval(&self, context: &mut crate::eval::EvalContext) -> crate::eval::EvalResult<Value> {
        log::debug!("Evaluating if statement to value: {self}");

        let cond = self.cond.eval(context)?;
        match cond {
            Value::Bool(true) => Ok(self.body.eval(context)?),
            Value::Bool(false) => {
                if let Some(body) = &self.body_else {
                    Ok(body.eval(context)?)
                } else if let Some(next) = &self.next_if {
                    next.eval(context)
                } else {
                    Ok(Value::None)
                }
            }
            _ => {
                context.error(
                    self,
                    EvalError::IfConditionIsNotBool {
                        condition: cond.to_string(),
                        src_ref: self.cond.src_ref(),
                    },
                )?;
                Ok(Value::None)
            }
        }
    }
}

impl Eval<Option<Model>> for ir::IfStatement {
    fn eval(&self, context: &mut EvalContext) -> EvalResult<Option<Model>> {
        log::debug!("Evaluating if statement to model: {self}");

        let cond = self.cond.eval(context)?;
        match cond {
            Value::Bool(true) => Ok(self.body.eval(context)?),
            Value::Bool(false) => {
                if let Some(body) = &self.body_else {
                    Ok(body.eval(context)?)
                } else if let Some(next) = &self.next_if {
                    next.eval(context)
                } else {
                    Ok(None)
                }
            }
            _ => {
                context.error(
                    self,
                    EvalError::IfConditionIsNotBool {
                        condition: cond.to_string(),
                        src_ref: self.cond.src_ref(),
                    },
                )?;
                Ok(None)
            }
        }
    }
}