Skip to main content

runmat_vm/ops/
control_flow.rs

1use crate::interpreter::stack::pop_value;
2use runmat_builtins::Value;
3use runmat_runtime::RuntimeError;
4
5pub enum ControlFlowAction {
6    Next,
7    Jump(usize),
8    Return,
9}
10
11#[inline]
12pub fn and_and(stack: &mut Vec<Value>, target: usize) -> Result<ControlFlowAction, RuntimeError> {
13    let lhs: f64 = (&pop_value(stack)?).try_into()?;
14    if lhs == 0.0 {
15        Ok(ControlFlowAction::Jump(target))
16    } else {
17        Ok(ControlFlowAction::Next)
18    }
19}
20
21#[inline]
22pub fn or_or(stack: &mut Vec<Value>, target: usize) -> Result<ControlFlowAction, RuntimeError> {
23    let lhs: f64 = (&pop_value(stack)?).try_into()?;
24    if lhs != 0.0 {
25        Ok(ControlFlowAction::Jump(target))
26    } else {
27        Ok(ControlFlowAction::Next)
28    }
29}
30
31#[inline]
32pub fn jump_if_false(cond: bool, target: usize) -> ControlFlowAction {
33    if cond {
34        ControlFlowAction::Next
35    } else {
36        ControlFlowAction::Jump(target)
37    }
38}
39
40#[inline]
41pub fn jump(target: usize) -> ControlFlowAction {
42    ControlFlowAction::Jump(target)
43}
44
45#[inline]
46pub fn enter_try(
47    try_stack: &mut Vec<(usize, Option<usize>)>,
48    catch_pc: usize,
49    catch_var: Option<usize>,
50) {
51    try_stack.push((catch_pc, catch_var));
52}
53
54#[inline]
55pub fn pop_try(try_stack: &mut Vec<(usize, Option<usize>)>) {
56    let _ = try_stack.pop();
57}
58
59#[inline]
60pub fn enter_scope(locals: &mut Vec<Value>, local_count: usize) {
61    for _ in 0..local_count {
62        locals.push(Value::Num(0.0));
63    }
64}
65
66pub fn exit_scope<OnPop>(locals: &mut Vec<Value>, local_count: usize, mut on_pop: OnPop)
67where
68    OnPop: FnMut(&Value),
69{
70    for _ in 0..local_count {
71        if let Some(value) = locals.pop() {
72            on_pop(&value);
73        }
74    }
75}
76
77#[inline]
78pub fn return_value(stack: &mut Vec<Value>) -> Result<ControlFlowAction, RuntimeError> {
79    let value = pop_value(stack)?;
80    stack.push(value);
81    Ok(ControlFlowAction::Return)
82}
83
84#[inline]
85pub fn return_void() -> ControlFlowAction {
86    ControlFlowAction::Return
87}