cas_compute/numerical/eval/
break_expr.rs

1use cas_parser::parser::ast::loop_expr::Break;
2use crate::numerical::{ctxt::Ctxt, error::Error, eval::Eval, value::Value};
3
4/// Helper macro to call [`Eval::eval`], then check if the loop should be broken. Errors will also
5/// be propogated automatically with the `?` operator.
6///
7/// The return type of this macro is [`Value`]. It can also diverge if evaluation fails, or if
8/// `break_loop` is true, with type [`Result<Value, Error>`].
9#[macro_export]
10macro_rules! eval_break {
11    ($value:expr, $ctxt:expr) => {{
12        let value = $value.eval($ctxt)?;
13        if $ctxt.break_loop {
14            return Ok(value);
15        }
16        value
17    }};
18}
19
20impl Eval for Break {
21    fn eval(&self, ctxt: &mut Ctxt) -> Result<Value, Error> {
22        if let Some(value) = &self.value {
23            // evaluate the entire expression first, then begin breaking the loop
24            // `loop` expression will then set `break_loop` back to false once we propogate up
25            // the stack
26            let result = value.eval(ctxt)?;
27            ctxt.break_loop = true;
28            Ok(result)
29        } else {
30            ctxt.break_loop = true;
31            Ok(Value::Unit)
32        }
33    }
34}