1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use serde::{Deserialize, Serialize};
use tree_sitter::Node;

use crate::{AbstractTree, Expression, Item, Result, Value, VariableMap};

#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct While {
    expression: Expression,
    items: Vec<Item>,
}

impl AbstractTree for While {
    fn from_syntax_node(source: &str, node: Node) -> crate::Result<Self> {
        debug_assert_eq!("while", node.kind());

        let expression_node = node.child(1).unwrap();
        let expression = Expression::from_syntax_node(source, expression_node)?;

        let child_count = node.child_count();
        let mut items = Vec::with_capacity(child_count);

        for index in 3..child_count - 1 {
            let item_node = node.child(index).unwrap();
            let item = Item::from_syntax_node(source, item_node)?;

            items.push(item);
        }

        Ok(While { expression, items })
    }

    fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
        while self.expression.run(source, context)?.as_boolean()? {
            for item in &self.items {
                item.run(source, context)?;
            }
        }

        Ok(crate::Value::Empty)
    }
}

#[cfg(test)]
mod tests {
    use crate::evaluate;

    #[test]
    fn evalualate_while_loop() {
        assert_eq!(evaluate("while false { 'foo' }"), Ok(crate::Value::Empty))
    }
}