//! The top level of Dust's API with functions to interpret Dust code. //! //! You can use this library externally by calling either of the "eval" //! functions or by constructing your own Evaluator. use tree_sitter::{Parser, Tree as TSTree}; use crate::{language, AbstractTree, Error, Map, Result, Root, Value}; /// Interpret the given source code. /// /// Returns a vector of results from evaluating the source code. Each comment /// and statemtent will have its own result. /// /// # Examples /// /// ```rust /// # use dust_lang::*; /// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6))); /// ``` pub fn interpret(source: &str) -> Result { let mut context = Map::new(); interpret_with_context(source, &mut context) } /// Interpret the given source code with the given context. /// /// # Examples /// /// ```rust /// # use dust_lang::*; /// let mut context = Map::new(); /// /// context.set("one".into(), 1.into(), None); /// context.set("two".into(), 2.into(), None); /// context.set("three".into(), 3.into(), None); /// /// let dust_code = "four = 4 one + two + three + four"; /// /// assert_eq!( /// interpret_with_context(dust_code, &mut context), /// Ok(Value::Integer(10)) /// ); /// ``` pub fn interpret_with_context(source: &str, context: &mut Map) -> Result { let mut parser = Parser::new(); parser.set_language(language())?; let mut interpreter = Interpreter::new(context, source)?; let value = interpreter.run()?; Ok(value) } /// A source code interpreter for the Dust language. pub struct Interpreter<'c, 's> { parser: Parser, context: &'c mut Map, source: &'s str, syntax_tree: Option, abstract_tree: Option, } impl<'c, 's> Interpreter<'c, 's> { pub fn new(context: &'c mut Map, source: &'s str) -> Result { let mut parser = Parser::new(); parser.set_language(language())?; Ok(Interpreter { parser, context, source, syntax_tree: None, abstract_tree: None, }) } pub fn set_source(&mut self, source: &'s str) { self.source = source; } pub fn parse_only(&mut self) { self.syntax_tree = self.parser.parse(self.source, self.syntax_tree.as_ref()); } pub fn run(&mut self) -> Result { self.syntax_tree = self.parser.parse(self.source, self.syntax_tree.as_ref()); self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree { Some(Root::from_syntax_node( self.source, syntax_tree.root_node(), &self.context, )?) } else { return Err(Error::ParserCancelled); }; if let Some(abstract_tree) = &self.abstract_tree { abstract_tree.run(self.source, &self.context) } else { Ok(Value::Option(None)) } } pub fn syntax_tree(&self) -> Result { if let Some(syntax_tree) = &self.syntax_tree { Ok(syntax_tree.root_node().to_sexp()) } else { Err(Error::ParserCancelled) } } }