//! Top-level unit of Dust code. use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{AbstractTree, Error, Result, Statement, Value, VariableMap}; /// An abstractiton of an independent unit of source code, or a comment. /// /// Items are either comments, which do nothing, or statements, which can be run /// to produce a single value or interact with a context by creating or /// referencing variables. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Item { statements: Vec, } impl Item { pub fn new(statements: Vec) -> Self { Self { statements } } } impl AbstractTree for Item { fn from_syntax_node(node: Node, source: &str) -> Result { debug_assert_eq!("item", node.kind()); let child_count = node.child_count(); let mut statements = Vec::with_capacity(child_count); for index in 0..child_count { let child = node.child(index).unwrap(); let statement = match child.kind() { "statement" => Statement::from_syntax_node(child, source)?, _ => { return Err(Error::UnexpectedSyntax { expected: "comment or statement", actual: child.kind(), location: child.start_position(), relevant_source: source[node.byte_range()].to_string(), }) } }; statements.push(statement); } Ok(Item { statements }) } fn run(&self, context: &mut VariableMap) -> Result { let mut prev_result = Ok(Value::Empty); for statement in &self.statements { prev_result?; prev_result = statement.run(context); } prev_result } }