2023-12-29 19:01:54 +00:00
|
|
|
//! 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.
|
2023-12-31 16:46:56 +00:00
|
|
|
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
2023-12-29 19:01:54 +00:00
|
|
|
|
2023-12-29 19:35:52 +00:00
|
|
|
use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
|
2023-12-29 19:01:54 +00:00
|
|
|
|
|
|
|
/// 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<Value> {
|
2023-12-29 19:52:51 +00:00
|
|
|
interpret_with_context(source, Map::new())
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Interpret the given source code with the given context.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # use dust_lang::*;
|
2023-12-29 19:52:51 +00:00
|
|
|
/// let context = Map::new();
|
2023-12-29 19:01:54 +00:00
|
|
|
///
|
|
|
|
/// 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!(
|
2023-12-29 19:52:51 +00:00
|
|
|
/// interpret_with_context(dust_code, context),
|
2023-12-29 19:01:54 +00:00
|
|
|
/// Ok(Value::Integer(10))
|
|
|
|
/// );
|
|
|
|
/// ```
|
2023-12-29 19:52:51 +00:00
|
|
|
pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> {
|
2023-12-30 17:02:58 +00:00
|
|
|
let mut interpreter = Interpreter::new(context);
|
2023-12-29 21:27:13 +00:00
|
|
|
let value = interpreter.run(source)?;
|
2023-12-29 19:01:54 +00:00
|
|
|
|
|
|
|
Ok(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A source code interpreter for the Dust language.
|
2023-12-29 21:27:13 +00:00
|
|
|
pub struct Interpreter {
|
2023-12-29 19:35:52 +00:00
|
|
|
parser: Parser,
|
2023-12-29 19:52:51 +00:00
|
|
|
context: Map,
|
2023-12-29 19:01:54 +00:00
|
|
|
syntax_tree: Option<TSTree>,
|
|
|
|
abstract_tree: Option<Root>,
|
|
|
|
}
|
|
|
|
|
2023-12-29 21:27:13 +00:00
|
|
|
impl Interpreter {
|
2023-12-30 17:02:58 +00:00
|
|
|
pub fn new(context: Map) -> Self {
|
2023-12-29 19:01:54 +00:00
|
|
|
let mut parser = Parser::new();
|
|
|
|
|
2023-12-30 17:02:58 +00:00
|
|
|
parser
|
|
|
|
.set_language(language())
|
|
|
|
.expect("Language version is incompatible with tree sitter version.");
|
2023-12-29 19:01:54 +00:00
|
|
|
|
2023-12-30 17:02:58 +00:00
|
|
|
Interpreter {
|
2023-12-29 19:35:52 +00:00
|
|
|
parser,
|
2023-12-29 19:01:54 +00:00
|
|
|
context,
|
|
|
|
syntax_tree: None,
|
|
|
|
abstract_tree: None,
|
2023-12-30 17:02:58 +00:00
|
|
|
}
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 16:46:56 +00:00
|
|
|
pub fn parse(&mut self, source: &str) -> Result<()> {
|
|
|
|
fn check_for_error(source: &str, node: Node, cursor: &mut TreeCursor) -> Result<()> {
|
|
|
|
if node.is_error() {
|
|
|
|
Err(Error::Syntax {
|
|
|
|
source: source[node.byte_range()].to_string(),
|
|
|
|
location: node.start_position(),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
for child in node.children(&mut cursor.clone()) {
|
|
|
|
check_for_error(source, child, cursor)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let syntax_tree = self.parser.parse(source, None);
|
|
|
|
|
|
|
|
if let Some(tree) = &syntax_tree {
|
|
|
|
let root = tree.root_node();
|
|
|
|
let mut cursor = root.walk();
|
|
|
|
|
|
|
|
check_for_error(source, root, &mut cursor)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.syntax_tree = syntax_tree;
|
|
|
|
|
|
|
|
Ok(())
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
|
|
|
|
2023-12-29 21:27:13 +00:00
|
|
|
pub fn run(&mut self, source: &str) -> Result<Value> {
|
2023-12-31 16:46:56 +00:00
|
|
|
self.parse(source)?;
|
|
|
|
|
2023-12-29 19:01:54 +00:00
|
|
|
self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree {
|
|
|
|
Some(Root::from_syntax_node(
|
2023-12-29 21:27:13 +00:00
|
|
|
source,
|
2023-12-29 19:01:54 +00:00
|
|
|
syntax_tree.root_node(),
|
|
|
|
&self.context,
|
|
|
|
)?)
|
|
|
|
} else {
|
2023-12-29 19:35:52 +00:00
|
|
|
return Err(Error::ParserCancelled);
|
2023-12-29 19:01:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(abstract_tree) = &self.abstract_tree {
|
2024-01-06 03:26:37 +00:00
|
|
|
abstract_tree.check_type(source, &self.context)?;
|
2023-12-29 21:27:13 +00:00
|
|
|
abstract_tree.run(source, &self.context)
|
2023-12-29 19:01:54 +00:00
|
|
|
} else {
|
2023-12-30 14:29:33 +00:00
|
|
|
Ok(Value::none())
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-29 19:35:52 +00:00
|
|
|
pub fn syntax_tree(&self) -> Result<String> {
|
2023-12-29 19:01:54 +00:00
|
|
|
if let Some(syntax_tree) = &self.syntax_tree {
|
2023-12-29 19:35:52 +00:00
|
|
|
Ok(syntax_tree.root_node().to_sexp())
|
2023-12-29 19:01:54 +00:00
|
|
|
} else {
|
2023-12-29 19:35:52 +00:00
|
|
|
Err(Error::ParserCancelled)
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-06 10:00:36 +00:00
|
|
|
|
|
|
|
pub fn format(&self) -> String {
|
|
|
|
if let Some(root_node) = &self.abstract_tree {
|
|
|
|
root_node.to_string()
|
|
|
|
} else {
|
|
|
|
"".to_string()
|
|
|
|
}
|
|
|
|
}
|
2023-12-29 19:01:54 +00:00
|
|
|
}
|
2023-12-30 17:02:58 +00:00
|
|
|
|
|
|
|
impl Default for Interpreter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Interpreter::new(Map::new())
|
|
|
|
}
|
|
|
|
}
|