From 9450e6dc968075c5c8eec0e29b1d368e7a1bf7f6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 10 Oct 2023 13:29:11 -0400 Subject: [PATCH] Implement new control flow syntax --- src/abstract_tree/assignment.rs | 16 +-- src/abstract_tree/expression.rs | 32 ++--- src/abstract_tree/function_call.rs | 19 +-- src/abstract_tree/identifier.rs | 4 +- src/abstract_tree/if_else.rs | 24 ++-- src/abstract_tree/item.rs | 12 +- src/abstract_tree/logic.rs | 14 +- src/abstract_tree/match.rs | 4 +- src/abstract_tree/math.rs | 18 +-- src/abstract_tree/mod.rs | 4 +- src/abstract_tree/statement.rs | 28 ++-- src/abstract_tree/while.rs | 13 +- src/error.rs | 9 +- src/evaluator.rs | 24 +--- src/value/mod.rs | 217 ++++++++++++----------------- src/value/value_type.rs | 68 +++++---- 16 files changed, 229 insertions(+), 277 deletions(-) diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 9a9c817..3f24bb4 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -20,9 +20,9 @@ pub enum AssignmentOperator { } impl AbstractTree for Assignment { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { let identifier_node = node.child(0).unwrap(); - let identifier = Identifier::from_syntax_node(identifier_node, source)?; + let identifier = Identifier::from_syntax_node(source, identifier_node)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -30,17 +30,17 @@ impl AbstractTree for Assignment { "+=" => AssignmentOperator::PlusEqual, "-=" => AssignmentOperator::MinusEqual, _ => { - return Err(Error::UnexpectedSyntax { + return Err(Error::UnexpectedSyntaxNode { expected: "=, += or -=", actual: operator_node.kind(), location: operator_node.start_position(), - relevant_source: source[node.byte_range()].to_string(), + relevant_source: source[operator_node.byte_range()].to_string(), }) } }; let statement_node = node.child(2).unwrap(); - let statement = Statement::from_syntax_node(statement_node, source)?; + let statement = Statement::from_syntax_node(source, statement_node)?; Ok(Assignment { identifier, @@ -49,9 +49,9 @@ impl AbstractTree for Assignment { }) } - fn run(&self, context: &mut VariableMap) -> Result { - let key = self.identifier.clone().take_inner(); - let mut value = self.statement.run(context)?; + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + let key = self.identifier.run(source, context)?.to_string(); + let mut value = self.statement.run(source, context)?; match self.operator { AssignmentOperator::PlusEqual => { diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index 3481be5..7424c25 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -1,39 +1,39 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Identifier, Result, Value, VariableMap}; +use crate::{value::ValueNode, AbstractTree, Error, Identifier, Result, Value, VariableMap}; use super::{function_call::FunctionCall, logic::Logic, math::Math}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Expression { + Value(ValueNode), Identifier(Identifier), - Value(Value), Math(Box), Logic(Box), FunctionCall(FunctionCall), } impl AbstractTree for Expression { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { debug_assert_eq!("expression", node.kind()); let child = node.child(0).unwrap(); let expression = match child.kind() { - "value" => Expression::Value(Value::from_syntax_node(child, source)?), - "identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?), - "math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)), - "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(child, source)?)), + "value" => Expression::Value(ValueNode::from_syntax_node(source, child)?), + "identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?), + "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), + "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), "function_call" => { - Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?) + Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?) } _ => { - return Err(Error::UnexpectedSyntax { + return Err(Error::UnexpectedSyntaxNode { expected: "value, identifier, math or function_call", actual: child.kind(), location: child.start_position(), - relevant_source: source[node.byte_range()].to_string(), + relevant_source: source[child.byte_range()].to_string(), }) } }; @@ -41,13 +41,13 @@ impl AbstractTree for Expression { Ok(expression) } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { match self { - Expression::Value(value) => Ok(value.clone()), - Expression::Identifier(identifier) => identifier.run(context), - Expression::Math(math) => math.run(context), - Expression::Logic(logic) => logic.run(context), - Expression::FunctionCall(function_call) => function_call.run(context), + Expression::Value(value_node) => value_node.run(source, context), + Expression::Identifier(identifier) => identifier.run(source, context), + Expression::Math(math) => math.run(source, context), + Expression::Logic(logic) => logic.run(source, context), + Expression::FunctionCall(function_call) => function_call.run(source, context), } } } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index f594733..dbc8c08 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -18,14 +18,14 @@ pub enum FunctionName { } impl AbstractTree for FunctionCall { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { debug_assert_eq!("function_call", node.kind()); let name_node = node.child(1).unwrap(); let name = match name_node.kind() { "identifier" => { - FunctionName::Identifier(Identifier::from_syntax_node(name_node, source)?) + FunctionName::Identifier(Identifier::from_syntax_node(source, name_node)?) } "tool" => { let tool_node = name_node.child(0).unwrap(); @@ -45,7 +45,7 @@ impl AbstractTree for FunctionCall { let mut current_index = 2; while current_index < node.child_count() - 1 { let expression_node = node.child(current_index).unwrap(); - let expression = Expression::from_syntax_node(expression_node, source)?; + let expression = Expression::from_syntax_node(source, expression_node)?; arguments.push(expression); @@ -55,20 +55,21 @@ impl AbstractTree for FunctionCall { Ok(FunctionCall { name, arguments }) } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { let identifier = match &self.name { FunctionName::Identifier(identifier) => identifier, FunctionName::Tool(tool) => { let value = self .arguments .first() - .map(|expression| expression.run(context)) + .map(|expression| expression.run(source, context)) .unwrap_or(Ok(Value::Empty))?; return tool.run(&value); } }; - let definition = if let Some(value) = context.get_value(identifier.inner())? { + let key = identifier.inner(); + let definition = if let Some(value) = context.get_value(key)? { value.as_function().cloned()? } else { return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone())); @@ -78,12 +79,12 @@ impl AbstractTree for FunctionCall { let mut function_context = context.clone(); for (identifier, expression) in id_expr_pairs { - let key = identifier.clone().take_inner(); - let value = expression.run(&mut function_context)?; + let key = identifier.run(source, context)?.to_string(); + let value = expression.run(source, &mut function_context)?; function_context.set_value(key, value)?; } - definition.body().run(&mut function_context) + definition.body().run(source, &mut function_context) } } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index d9d7c33..bcc07ca 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -21,13 +21,13 @@ impl Identifier { } impl AbstractTree for Identifier { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { let identifier = &source[node.byte_range()]; Ok(Identifier(identifier.to_string())) } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { let value = context.get_value(&self.0)?.unwrap_or_default(); Ok(value) diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index 352e0ef..c6fc256 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -13,12 +13,12 @@ pub struct IfElse { } impl AbstractTree for IfElse { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { let if_node = node.child(0).unwrap().child(1).unwrap(); - let if_expression = Expression::from_syntax_node(if_node, source)?; + let if_expression = Expression::from_syntax_node(source, if_node)?; let then_node = node.child(0).unwrap().child(3).unwrap(); - let then_statement = Statement::from_syntax_node(then_node, source)?; + let then_statement = Statement::from_syntax_node(source, then_node)?; let child_count = node.child_count(); let mut else_if_expressions = Vec::new(); @@ -31,19 +31,19 @@ impl AbstractTree for IfElse { if let Some(node) = child { if node.kind() == "else_if" { let expression_node = node.child(1).unwrap(); - let expression = Expression::from_syntax_node(expression_node, source)?; + let expression = Expression::from_syntax_node(source, expression_node)?; else_if_expressions.push(expression); let statement_node = node.child(3).unwrap(); - let statement = Statement::from_syntax_node(statement_node, source)?; + let statement = Statement::from_syntax_node(source, statement_node)?; else_if_statements.push(statement); } if node.kind() == "else" { let else_node = node.child(2).unwrap(); - else_statement = Some(Statement::from_syntax_node(else_node, source)?); + else_statement = Some(Statement::from_syntax_node(source, else_node)?); } } } @@ -57,26 +57,26 @@ impl AbstractTree for IfElse { }) } - fn run(&self, context: &mut VariableMap) -> Result { - let if_boolean = self.if_expression.run(context)?.as_boolean()?; + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + let if_boolean = self.if_expression.run(source, context)?.as_boolean()?; if if_boolean { - self.then_statement.run(context) + self.then_statement.run(source, context) } else { let expressions = &self.else_if_expressions; for (index, expression) in expressions.into_iter().enumerate() { - let if_boolean = expression.run(context)?.as_boolean()?; + let if_boolean = expression.run(source, context)?.as_boolean()?; if if_boolean { let statement = self.else_if_statements.get(index).unwrap(); - return statement.run(context); + return statement.run(source, context); } } if let Some(statement) = &self.else_statement { - statement.run(context) + statement.run(source, context) } else { Ok(Value::Empty) } diff --git a/src/abstract_tree/item.rs b/src/abstract_tree/item.rs index 2ba194f..555dc21 100644 --- a/src/abstract_tree/item.rs +++ b/src/abstract_tree/item.rs @@ -22,7 +22,7 @@ impl Item { } impl AbstractTree for Item { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { debug_assert_eq!("item", node.kind()); let child_count = node.child_count(); @@ -32,13 +32,13 @@ impl AbstractTree for Item { let child = node.child(index).unwrap(); let statement = match child.kind() { - "statement" => Statement::from_syntax_node(child, source)?, + "statement" => Statement::from_syntax_node(source, child)?, _ => { - return Err(Error::UnexpectedSyntax { + return Err(Error::UnexpectedSyntaxNode { expected: "comment or statement", actual: child.kind(), location: child.start_position(), - relevant_source: source[node.byte_range()].to_string(), + relevant_source: source[child.byte_range()].to_string(), }) } }; @@ -49,12 +49,12 @@ impl AbstractTree for Item { Ok(Item { statements }) } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, 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 = statement.run(source, context); } prev_result diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index f4d12e2..1f3c324 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -11,9 +11,9 @@ pub struct Logic { } impl AbstractTree for Logic { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { let left_node = node.child(0).unwrap(); - let left = Expression::from_syntax_node(left_node, source)?; + let left = Expression::from_syntax_node(source, left_node)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -25,7 +25,7 @@ impl AbstractTree for Logic { ">=" => LogicOperator::GreaterOrEqual, "<=" => LogicOperator::LessOrEqaul, _ => { - return Err(Error::UnexpectedSyntax { + return Err(Error::UnexpectedSyntaxNode { expected: "==, && or ||", actual: operator_node.kind(), location: operator_node.start_position(), @@ -35,7 +35,7 @@ impl AbstractTree for Logic { }; let right_node = node.child(2).unwrap(); - let right = Expression::from_syntax_node(right_node, source)?; + let right = Expression::from_syntax_node(source, right_node)?; Ok(Logic { left, @@ -44,9 +44,9 @@ impl AbstractTree for Logic { }) } - fn run(&self, context: &mut VariableMap) -> Result { - let left = self.left.run(context)?; - let right = self.right.run(context)?; + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + let left = self.left.run(source, context)?; + let right = self.right.run(source, context)?; let result = match self.operator { LogicOperator::Equal => { if let (Ok(left_num), Ok(right_num)) = (left.as_number(), right.as_number()) { diff --git a/src/abstract_tree/match.rs b/src/abstract_tree/match.rs index be19a9f..8e35e25 100644 --- a/src/abstract_tree/match.rs +++ b/src/abstract_tree/match.rs @@ -12,11 +12,11 @@ use crate::{AbstractTree, Result, Value, VariableMap}; pub struct Match {} impl AbstractTree for Match { - fn from_syntax_node(_node: Node, _source: &str) -> Result { + fn from_syntax_node(_source: &str, _node: Node) -> Result { todo!() } - fn run(&self, _context: &mut VariableMap) -> Result { + fn run(&self, _source: &str, _context: &mut VariableMap) -> Result { todo!() } } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 8b8d617..076d79a 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -11,9 +11,9 @@ pub struct Math { } impl AbstractTree for Math { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { let left_node = node.child(0).unwrap(); - let left = Expression::from_syntax_node(left_node, source)?; + let left = Expression::from_syntax_node(source, left_node)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -23,7 +23,7 @@ impl AbstractTree for Math { "/" => MathOperator::Divide, "%" => MathOperator::Modulo, _ => { - return Err(Error::UnexpectedSyntax { + return Err(Error::UnexpectedSyntaxNode { expected: "+, -, *, / or %", actual: operator_node.kind(), location: operator_node.start_position(), @@ -33,7 +33,7 @@ impl AbstractTree for Math { }; let right_node = node.child(2).unwrap(); - let right = Expression::from_syntax_node(right_node, source)?; + let right = Expression::from_syntax_node(source, right_node)?; Ok(Math { left, @@ -42,11 +42,11 @@ impl AbstractTree for Math { }) } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { match self.operator { MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => { - let left_value = self.left.run(context)?.as_int()?; - let right_value = self.right.run(context)?.as_int()?; + let left_value = self.left.run(source, context)?.as_int()?; + let right_value = self.right.run(source, context)?.as_int()?; let outcome = match &self.operator { MathOperator::Add => left_value + right_value, MathOperator::Subtract => left_value - right_value, @@ -57,8 +57,8 @@ impl AbstractTree for Math { Ok(Value::Integer(outcome)) } MathOperator::Divide | MathOperator::Modulo => { - let left_value = self.left.run(context)?.as_number()?; - let right_value = self.right.run(context)?.as_number()?; + let left_value = self.left.run(source, context)?.as_number()?; + let right_value = self.right.run(source, context)?.as_number()?; let outcome = match self.operator { MathOperator::Divide => left_value / right_value, MathOperator::Modulo => left_value % right_value, diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 98ee6b5..832a109 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -40,8 +40,8 @@ pub trait AbstractTree: Sized { /// /// If necessary, the source code can be accessed directly by getting the /// node's byte range. - fn from_syntax_node(node: Node, source: &str) -> Result; + fn from_syntax_node(source: &str, node: Node) -> Result; /// Execute dust code by traversing the tree - fn run(&self, context: &mut VariableMap) -> Result; + fn run(&self, source: &str, context: &mut VariableMap) -> Result; } diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index 3a791d5..b89f137 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -20,43 +20,43 @@ pub enum Statement { } impl AbstractTree for Statement { - fn from_syntax_node(node: Node, source: &str) -> Result { + fn from_syntax_node(source: &str, node: Node) -> Result { debug_assert_eq!("statement", node.kind()); let child = node.child(0).unwrap(); match child.kind() { "assignment" => Ok(Statement::Assignment(Box::new( - Assignment::from_syntax_node(child, source)?, + Assignment::from_syntax_node(source, child)?, ))), "expression" => Ok(Self::Expression(Expression::from_syntax_node( - child, source, + source, child, )?)), "if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( - child, source, + source, child, )?))), "tool" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( - child, source, + source, child, )?))), "while" => Ok(Statement::While(Box::new(While::from_syntax_node( - child, source, + source, child, )?))), - _ => Err(Error::UnexpectedSyntax { + _ => Err(Error::UnexpectedSyntaxNode { expected: "assignment, expression, if...else or tool", actual: child.kind(), location: child.start_position(), - relevant_source: source[node.byte_range()].to_string(), + relevant_source: source[child.byte_range()].to_string(), }), } } - fn run(&self, context: &mut VariableMap) -> Result { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { match self { - Statement::Assignment(assignment) => assignment.run(context), - Statement::Expression(expression) => expression.run(context), - Statement::IfElse(if_else) => if_else.run(context), - Statement::Match(r#match) => r#match.run(context), - Statement::While(r#while) => r#while.run(context), + Statement::Assignment(assignment) => assignment.run(source, context), + Statement::Expression(expression) => expression.run(source, context), + Statement::IfElse(if_else) => if_else.run(source, context), + Statement::Match(r#match) => r#match.run(source, context), + Statement::While(r#while) => r#while.run(source, context), } } } diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index 524370c..c6c139f 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use tree_sitter::Node; use crate::{AbstractTree, Expression, Item, Result, Value, VariableMap}; @@ -9,18 +10,18 @@ pub struct While { } impl AbstractTree for While { - fn from_syntax_node(node: tree_sitter::Node, source: &str) -> crate::Result { + fn from_syntax_node(source: &str, node: Node) -> crate::Result { debug_assert_eq!("while", node.kind()); let expression_node = node.child(1).unwrap(); - let expression = Expression::from_syntax_node(expression_node, source)?; + 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(item_node, source)?; + let item = Item::from_syntax_node(source, item_node)?; items.push(item); } @@ -28,10 +29,10 @@ impl AbstractTree for While { Ok(While { expression, items }) } - fn run(&self, context: &mut VariableMap) -> Result { - while self.expression.run(context)?.as_boolean()? { + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + while self.expression.run(source, context)?.as_boolean()? { for item in &self.items { - item.run(context)?; + item.run(source, context)?; } } diff --git a/src/error.rs b/src/error.rs index f62831b..88eb502 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,7 +12,7 @@ pub type Result = std::result::Result; #[derive(Clone, PartialEq)] #[non_exhaustive] pub enum Error { - UnexpectedSyntax { + UnexpectedSyntaxNode { expected: &'static str, actual: &'static str, location: tree_sitter::Point, @@ -533,15 +533,14 @@ impl fmt::Display for Error { f, "Wrong number of columns for this table. Expected {expected}, found {actual}." ), - UnexpectedSyntax { + UnexpectedSyntaxNode { expected, actual, location, - relevant_source: surrounding_text, + relevant_source } => write!( f, - "Unexpected syntax at {location}. Expected {expected}, but found {actual}. - >> {surrounding_text} <<" + "Unexpected syntax at {location}. Expected {expected}, but found {actual}. {relevant_source}" ), ExpectedFieldName => write!( f, diff --git a/src/evaluator.rs b/src/evaluator.rs index 884f62a..8241824 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -88,8 +88,8 @@ impl<'context, 'code> Evaluator<'context, 'code> { println!("{}", root_node.to_sexp()); for item_node in root_node.children(&mut cursor) { - let item = Item::from_syntax_node(item_node, self.source)?; - prev_result = item.run(self.context); + let item = Item::from_syntax_node(self.source, item_node)?; + prev_result = item.run(self.source, self.context); } prev_result @@ -98,10 +98,7 @@ impl<'context, 'code> Evaluator<'context, 'code> { #[cfg(test)] mod tests { - use crate::{ - abstract_tree::{expression::Expression, identifier::Identifier, statement::Statement}, - Function, Table, - }; + use crate::Table; use super::*; @@ -246,21 +243,6 @@ mod tests { ); } - #[test] - fn evaluate_function() { - let function = Function::new( - vec![Identifier::new("message".to_string())], - Item::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("message".to_string()), - ))]), - ); - - assert_eq!( - evaluate("function { message }"), - Ok(Value::Function(function)) - ); - } - #[test] fn evaluate_function_call() { let mut context = VariableMap::new(); diff --git a/src/value/mod.rs b/src/value/mod.rs index cf1054f..1202c1e 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,7 +1,7 @@ //! Types that represent runtime values. use crate::{ error::{Error, Result}, - AbstractTree, Function, Identifier, Item, Table, ValueType, VariableMap, + AbstractTree, Function, Identifier, Table, ValueType, VariableMap, }; use json::JsonValue; @@ -14,10 +14,11 @@ use tree_sitter::Node; use std::{ cmp::Ordering, + collections::BTreeMap, convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, - ops::{Add, AddAssign, Sub, SubAssign}, + ops::{Add, AddAssign, Range, Sub, SubAssign}, }; pub mod function; @@ -30,7 +31,7 @@ pub mod variable_map; /// Every whale variable has a key and a Value. Variables are represented by /// storing them in a VariableMap. This means the map of variables is itself a /// value that can be treated as any other. -#[derive(Clone, Debug, Default)] +#[derive(Debug, Clone, Default)] pub enum Value { List(Vec), Map(VariableMap), @@ -44,163 +45,121 @@ pub enum Value { Empty, } -impl Value { - pub fn from_syntax_node(node: Node, source: &str) -> Result { - let child = node.child(0).unwrap(); +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct ValueNode { + value_type: ValueType, + start_byte: usize, + end_byte: usize, +} - match child.kind() { - "integer" => { - let bytes = &source[child.byte_range()]; - let raw_value = bytes.parse::().unwrap(); +impl ValueNode { + pub fn byte_range(&self) -> Range { + self.start_byte..self.end_byte + } +} - Ok(Value::Integer(raw_value)) - } - "float" => { - let bytes = &source[child.byte_range()]; - let raw_value = bytes.parse::().unwrap(); - - Ok(Value::Float(raw_value)) - } - "string" => { - let byte_range_without_quotes = child.start_byte() + 1..child.end_byte() - 1; - let text = &source[byte_range_without_quotes]; - - Ok(Value::String(text.to_string())) - } - "boolean" => { - let bytes = &source[child.byte_range()]; - let raw_value = bytes.parse::().unwrap(); - - Ok(Value::Boolean(raw_value)) - } - "empty" => Ok(Value::Empty), +impl AbstractTree for ValueNode { + fn from_syntax_node(source: &str, node: Node) -> Result { + let value_type = match node.kind() { + "integer" => ValueType::Integer, + "float" => ValueType::Float, + "string" => ValueType::String, + "boolean" => ValueType::Boolean, + "empty" => ValueType::Empty, "list" => { - let item_count = child.named_child_count(); - let mut values = Vec::with_capacity(item_count); - let mut current_node = child.child(1).unwrap(); + let mut child_nodes = Vec::new(); - while values.len() < item_count { - if current_node.is_named() { - let value = Value::from_syntax_node(current_node, source)?; + for index in 0..node.child_count() - 1 { + let child_syntax_node = node.child(index).unwrap(); + let child_value = ValueNode::from_syntax_node(source, child_syntax_node)?; - values.push(value); - } - - current_node = current_node.next_sibling().unwrap(); + child_nodes.push(child_value); } - Ok(Value::List(values)) - } - "table" => { - let mut current_node = child.child(0).unwrap(); - let header_and_row_count = child.named_child_count(); - - let mut headers = Vec::new(); - let mut rows = Vec::new(); - - while headers.len() + rows.len() < header_and_row_count { - println!("{current_node:?}"); - - if current_node.kind() == "identifier" { - let identifier = Identifier::from_syntax_node(current_node, source)?; - let identifier_text = identifier.take_inner(); - - headers.push(identifier_text); - } - - if current_node.kind() == "list" { - let value = Value::list_from_syntax_node(current_node, source)?; - let row = value.into_inner_list()?; - - rows.push(row); - } - - if let Some(node) = current_node.next_sibling() { - current_node = node; - } else { - break; - } - } - - let table = Table::from_raw_parts(headers, rows); - - Ok(Value::Table(table)) + ValueType::ListExact(child_nodes) } + "table" => ValueType::Table, "map" => { - let mut map = VariableMap::new(); - let pair_count = child.named_child_count(); - let mut current_key = String::new(); - let mut current_node = child.child(0).unwrap(); + let mut child_nodes = BTreeMap::new(); + let mut current_key = "".to_string(); - while map.len() < pair_count { - if current_node.kind() == "identifier" { - let identifier_text = &source[current_node.byte_range()]; - current_key = identifier_text.to_string(); + for index in 0..node.child_count() - 1 { + let child_syntax_node = node.child(index).unwrap(); + + if child_syntax_node.kind() == "identifier" { + current_key = + Identifier::from_syntax_node(source, child_syntax_node)?.take_inner(); } - if current_node.kind() == "value" { - let value = Value::from_syntax_node(current_node, source)?; + if child_syntax_node.kind() == "value" { + let child_value = ValueNode::from_syntax_node(source, child_syntax_node)?; + let key = current_key.clone(); - map.set_value(current_key.to_string(), value)?; - } - - if let Some(node) = current_node.next_sibling() { - current_node = node; - } else { - break; + child_nodes.insert(key, child_value); } } - Ok(Value::Map(map)) + ValueType::Map(child_nodes) } - "function" => { - let child_count = child.child_count(); - let mut identifiers = Vec::new(); - let mut item = None; + "function" => ValueType::Function, + _ => { + return Err(Error::UnexpectedSyntaxNode { + expected: + "string, integer, float, boolean, list, table, map, function or empty", + actual: node.kind(), + location: node.start_position(), + relevant_source: source[node.byte_range()].to_string(), + }) + } + }; - for index in 0..child_count { - let child = child.child(index).unwrap(); + Ok(ValueNode { + value_type, + start_byte: node.start_byte(), + end_byte: node.end_byte(), + }) + } - if child.kind() == "identifier" { - let identifier = Identifier::from_syntax_node(child, source)?; + fn run(&self, source: &str, context: &mut VariableMap) -> Result { + let value_source = &source[self.byte_range()]; + let value = match &self.value_type { + ValueType::Any => todo!(), + ValueType::String => Value::String(value_source.to_owned()), + ValueType::Float => Value::Float(value_source.parse().unwrap()), + ValueType::Integer => Value::Integer(value_source.parse().unwrap()), + ValueType::Boolean => Value::Boolean(value_source.parse().unwrap()), + ValueType::ListExact(nodes) => { + let mut values = Vec::with_capacity(nodes.len()); - identifiers.push(identifier) - } + for node in nodes { + let value = node.run(source, context)?; - if child.kind() == "item" { - item = Some(Item::from_syntax_node(child, source)?); - } + values.push(value); } - Ok(Value::Function(Function::new(identifiers, item.unwrap()))) + Value::List(values) } - _ => Err(Error::UnexpectedSyntax { - expected: "string, integer, float, boolean, list, table, map, function or empty", - actual: child.kind(), - location: child.start_position(), - relevant_source: source[child.byte_range()].to_string(), - }), - } - } + ValueType::Empty => Value::Empty, + ValueType::Map(nodes) => { + let mut values = VariableMap::new(); - pub fn list_from_syntax_node(node: Node, source: &str) -> Result { - let item_count = node.named_child_count(); - let mut values = Vec::with_capacity(item_count); - let mut current_node = node.child(1).unwrap(); + for (key, node) in nodes { + let value = node.run(source, context)?; - while values.len() < item_count { - if current_node.is_named() { - let value = Value::from_syntax_node(current_node, source)?; + values.set_value(key.clone(), value)?; + } - values.push(value); + Value::Map(values) } + ValueType::Table => todo!(), + ValueType::Function => todo!(), + }; - current_node = current_node.next_sibling().unwrap(); - } - - Ok(Value::List(values)) + Ok(value) } +} +impl Value { pub fn value_type(&self) -> ValueType { ValueType::from(self) } diff --git a/src/value/value_type.rs b/src/value/value_type.rs index a78ca34..25eb41b 100644 --- a/src/value/value_type.rs +++ b/src/value/value_type.rs @@ -1,23 +1,27 @@ -use std::fmt::{self, Debug, Display, Formatter}; +use std::{ + collections::BTreeMap, + fmt::{self, Debug, Display, Formatter}, +}; + +use serde::{Deserialize, Serialize}; use crate::Value; +use super::ValueNode; + /// The type of a `Value`. -#[derive(Clone)] +#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)] pub enum ValueType { Any, String, Float, Integer, Boolean, - List, - ListOf(Box), - ListExact(Vec), + ListExact(Vec), Empty, - Map, + Map(BTreeMap), Table, Function, - Time, } impl Eq for ValueType {} @@ -32,21 +36,10 @@ impl PartialEq for ValueType { (ValueType::Integer, ValueType::Integer) => true, (ValueType::Boolean, ValueType::Boolean) => true, (ValueType::ListExact(left), ValueType::ListExact(right)) => left == right, - (ValueType::ListExact(_), ValueType::List) => true, - (ValueType::List, ValueType::ListExact(_)) => true, - (ValueType::ListOf(left), ValueType::ListOf(right)) => left == right, - (ValueType::ListOf(_), ValueType::List) => true, - (ValueType::List, ValueType::ListOf(_)) => true, - (ValueType::ListOf(value_type), ValueType::ListExact(exact_list)) - | (ValueType::ListExact(exact_list), ValueType::ListOf(value_type)) => exact_list - .iter() - .all(|exact_type| exact_type == value_type.as_ref()), - (ValueType::List, ValueType::List) => true, (ValueType::Empty, ValueType::Empty) => true, - (ValueType::Map, ValueType::Map) => true, + (ValueType::Map(left), ValueType::Map(right)) => left == right, (ValueType::Table, ValueType::Table) => true, (ValueType::Function, ValueType::Function) => true, - (ValueType::Time, ValueType::Time) => true, _ => false, } } @@ -60,10 +53,6 @@ impl Display for ValueType { ValueType::Float => write!(f, "float"), ValueType::Integer => write!(f, "integer"), ValueType::Boolean => write!(f, "boolean"), - ValueType::List => write!(f, "list"), - ValueType::ListOf(value_type) => { - write!(f, "({value_type}s)") - } ValueType::ListExact(list) => { write!(f, "(")?; for (index, item) in list.into_iter().enumerate() { @@ -71,16 +60,15 @@ impl Display for ValueType { write!(f, ", ")?; } - write!(f, "{item}")?; + write!(f, "{item:?}")?; } write!(f, ")") } ValueType::Empty => write!(f, "empty"), - ValueType::Map => write!(f, "map"), + ValueType::Map(map) => write!(f, "map"), ValueType::Table => write!(f, "table"), ValueType::Function => write!(f, "function"), - ValueType::Time => write!(f, "time"), } } } @@ -100,11 +88,33 @@ impl From<&Value> for ValueType { Value::Boolean(_) => ValueType::Boolean, Value::Empty => ValueType::Empty, Value::List(list) => { - let values = list.iter().map(|value| value.value_type()).collect(); + let value_nodes = list + .iter() + .map(|value| ValueNode { + value_type: value.value_type(), + start_byte: 0, + end_byte: 0, + }) + .collect(); - ValueType::ListExact(values) + ValueType::ListExact(value_nodes) + } + Value::Map(map) => { + let mut value_nodes = BTreeMap::new(); + + for (key, value) in map.inner() { + let value_type = ValueType::from(value); + let value_node = ValueNode { + value_type, + start_byte: 0, + end_byte: 0, + }; + + value_nodes.insert(key.to_string(), value_node); + } + + ValueType::Map(value_nodes) } - Value::Map(_) => ValueType::Map, Value::Table { .. } => ValueType::Table, Value::Function(_) => ValueType::Function, }