Skip to main content

microcad_lang/eval/statements/
if_statement.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! If statement evaluation.
5
6use microcad_lang_base::{PushDiag, SrcReferrer};
7
8use crate::{eval::*, model::*, syntax::*, value::*};
9
10impl Eval<Value> for IfStatement {
11    fn eval(&self, context: &mut crate::eval::EvalContext) -> crate::eval::EvalResult<Value> {
12        log::debug!("Evaluating if statement to value: {self}");
13
14        let cond = self.cond.eval(context)?;
15        match cond {
16            Value::Bool(true) => Ok(self.body.eval(context)?),
17            Value::Bool(false) => {
18                if let Some(body) = &self.body_else {
19                    Ok(body.eval(context)?)
20                } else if let Some(next) = &self.next_if {
21                    next.eval(context)
22                } else {
23                    Ok(Value::None)
24                }
25            }
26            _ => {
27                context.error(
28                    self,
29                    EvalError::IfConditionIsNotBool {
30                        condition: cond.to_string(),
31                        src_ref: self.cond.src_ref(),
32                    },
33                )?;
34                Ok(Value::None)
35            }
36        }
37    }
38}
39
40impl Eval<Option<Model>> for IfStatement {
41    fn eval(&self, context: &mut EvalContext) -> EvalResult<Option<Model>> {
42        log::debug!("Evaluating if statement to model: {self}");
43
44        let cond = self.cond.eval(context)?;
45        match cond {
46            Value::Bool(true) => Ok(self.body.eval(context)?),
47            Value::Bool(false) => {
48                if let Some(body) = &self.body_else {
49                    Ok(body.eval(context)?)
50                } else if let Some(next) = &self.next_if {
51                    next.eval(context)
52                } else {
53                    Ok(None)
54                }
55            }
56            _ => {
57                context.error(
58                    self,
59                    EvalError::IfConditionIsNotBool {
60                        condition: cond.to_string(),
61                        src_ref: self.cond.src_ref(),
62                    },
63                )?;
64                Ok(None)
65            }
66        }
67    }
68}