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)
}
}
}
}