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}