diff --git a/src/interface.rs b/src/interface.rs index 2647131..f6b0f9a 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -2,9 +2,9 @@ use std::ops::Range; -use tree_sitter::{Parser, TreeCursor}; +use tree_sitter::{Node, Parser, Tree, TreeCursor}; -use crate::{language, token, tree, Error, Result, Value, VariableMap}; +use crate::{language, Error, Result, Value, VariableMap}; /// Evaluate the given expression string. /// @@ -34,51 +34,103 @@ pub fn eval(source: &str) -> Result { /// context.set_value("three".into(), 3.into()).unwrap(); // Do proper error handling here /// assert_eq!(eval_with_context("one + two + three", &mut context), Ok(Value::from(6))); /// ``` -pub fn eval_with_context(input: &str, context: &mut VariableMap) -> Result { +pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Result { let mut parser = Parser::new(); parser.set_language(language()).unwrap(); - let tree = parser.parse(input, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let sexp = tree.root_node().to_sexp(); println!("{sexp}"); + let evaluator = Evaluator::new(tree.clone(), source).unwrap(); let mut cursor = tree.walk(); - cursor.goto_first_child(); + let results = evaluator.run(context, &mut cursor, source); - let statement = Statement::from_cursor(cursor); - - println!("{statement:?}"); + println!("{evaluator:?}"); + println!("{results:?}"); Ok(Value::Empty) } #[derive(Debug)] -struct EvalTree { - root: Source, +struct Evaluator { + items: Vec, +} + +impl Evaluator { + fn new(tree: Tree, source: &str) -> Result { + let mut cursor = tree.walk(); + let root_node = cursor.node(); + let mut items = Vec::new(); + + for node in root_node.children(&mut cursor) { + let item = Item::new(node, source)?; + items.push(item); + } + + Ok(Evaluator { items }) + } + + fn run( + &self, + context: &mut VariableMap, + mut cursor: &mut TreeCursor, + source: &str, + ) -> Vec> { + let mut results = Vec::with_capacity(self.items.len()); + + for root in &self.items { + match root { + Item::Comment(comment) => results.push(Ok(Value::String(comment.clone()))), + Item::Statement(statement) => { + results.push(statement.run(context, &mut cursor, source)) + } + } + } + + results + } } #[derive(Debug)] -enum Source { +enum Item { Comment(String), Statement(Statement), } +impl Item { + fn new(node: Node, source: &str) -> Result { + if node.kind() == "comment" { + let byte_range = node.byte_range(); + let value_string = &source[byte_range]; + + Ok(Item::Comment(value_string.to_string())) + } else if node.kind() == "statement" { + Ok(Item::Statement(Statement::new(node, source)?)) + } else { + Err(Error::UnexpectedSourceNode { + expected: "comment or statement", + actual: node.kind(), + }) + } + } +} + #[derive(Debug)] enum Statement { Closed(Expression), } impl Statement { - fn from_cursor(mut cursor: TreeCursor) -> Result { - let node = cursor.node(); - - cursor.goto_first_child(); - + fn new(node: Node, source: &str) -> Result { if node.kind() == "statement" { - Ok(Statement::Closed(Expression::from_cursor(cursor)?)) + Ok(Statement::Closed(Expression::new( + node.child(0).unwrap(), + source, + )?)) } else { Err(Error::UnexpectedSourceNode { expected: "statement", @@ -86,42 +138,117 @@ impl Statement { }) } } + + fn run( + &self, + context: &mut VariableMap, + mut cursor: &mut TreeCursor, + source: &str, + ) -> Result { + match self { + Statement::Closed(expression) => expression.run(context, &mut cursor, source), + } + } } #[derive(Debug)] enum Expression { Identifier(&'static str), - Value(Range), + Value(Value), + Operation(Operation), } impl Expression { - fn from_cursor(mut cursor: TreeCursor) -> Result { - let parent = cursor.node(); + fn new(node: Node, source: &str) -> Result { + if node.kind() != "expression" { + return Err(Error::UnexpectedSourceNode { + expected: "expression", + actual: node.kind(), + }); + } - cursor.goto_first_child(); + let child = node.child(0).unwrap(); - let child = cursor.node(); - - if parent.kind() == "expression" { - if child.kind() == "identifier" { - if let Some(name) = cursor.field_name() { - Ok(Expression::Identifier(name)) - } else { - Err(Error::ExpectedFieldName) - } - } else if child.kind() == "value" { - Ok(Self::Value(child.byte_range())) - } else { - Err(Error::UnexpectedSourceNode { - expected: "identifier or value", - actual: child.kind(), - }) - } + if child.kind() == "identifier" { + todo!() + } else if child.kind() == "value" { + Ok(Expression::Value(Value::new(child, source)?)) + } else if child.kind() == "operation" { + Ok(Expression::Operation(Operation::new(child, source)?)) } else { Err(Error::UnexpectedSourceNode { - expected: "expression", - actual: parent.kind(), + expected: "identifier, operation or value", + actual: child.kind(), }) } } + + fn run( + &self, + context: &mut VariableMap, + mut cursor: &mut TreeCursor, + source: &str, + ) -> Result { + match self { + Expression::Identifier(identifier) => { + let value = context.get_value(&identifier)?; + + if let Some(value) = value { + Ok(value) + } else { + Ok(Value::Empty) + } + } + Expression::Value(value) => Ok(value.clone()), + Expression::Operation(operation) => operation.run(context, &mut cursor, source), + } + } +} + +#[derive(Debug)] +struct Operation { + left: Box, + operator: &'static str, + right: Box, +} + +impl Operation { + fn new(node: Node, source: &str) -> Result { + let first_child = node.child(0).unwrap(); + let second_child = node.child(1).unwrap(); + let third_child = node.child(2).unwrap(); + let left = { Box::new(Expression::new(first_child, source)?) }; + let operator = { second_child.child(0).unwrap().kind() }; + let right = { Box::new(Expression::new(third_child, source)?) }; + + Ok(Operation { + left, + operator, + right, + }) + } + + fn run( + &self, + context: &mut VariableMap, + mut cursor: &mut TreeCursor, + source: &str, + ) -> Result { + let left = self.left.run(context, &mut cursor, source)?; + let right = self.right.run(context, &mut cursor, source)?; + + match self.operator { + "+" => { + let integer_result = left.as_int()? + right.as_int()?; + + Ok(Value::Integer(integer_result)) + } + "-" => { + let integer_result = left.as_int()? - right.as_int()?; + + Ok(Value::Integer(integer_result)) + } + _ => Ok(Value::Empty), + } + } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 4b981d6..c89ccde 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -10,6 +10,7 @@ use serde::{ ser::SerializeTuple, Deserialize, Serialize, Serializer, }; +use tree_sitter::{Node, TreeCursor}; use std::{ cmp::Ordering, @@ -46,6 +47,31 @@ pub enum Value { } impl Value { + pub fn new(node: Node, source: &str) -> Result { + let child = node.child(0).unwrap(); + + if node.kind() != "value" { + return Err(Error::UnexpectedSourceNode { + expected: "value", + actual: node.kind(), + }); + } + + let value_snippet = &source[child.byte_range()]; + + match child.kind() { + "integer" => { + let raw = value_snippet.parse::().unwrap_or_default(); + + Ok(Value::Integer(raw)) + } + _ => Err(Error::UnexpectedSourceNode { + expected: "raw value", + actual: child.kind(), + }), + } + } + pub fn value_type(&self) -> ValueType { ValueType::from(self) }