From 41483f6b84b83488ff02512bfad8719cd62481fc Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 2 Oct 2023 15:19:48 -0400 Subject: [PATCH] Implement lists --- src/interface.rs | 141 ++++++++++++++++++++------------ src/tools/collections.rs | 6 +- src/value/mod.rs | 165 ++++++++++++++++++-------------------- src/value/variable_map.rs | 25 +++--- 4 files changed, 184 insertions(+), 153 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 6bf5a59..68dc794 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Formatter}; use serde::{Deserialize, Serialize}; -use tree_sitter::{Node, Parser, Tree as TSTree}; +use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor}; use crate::{language, Error, Result, Value, VariableMap}; @@ -63,7 +63,7 @@ pub trait EvaluatorTree: Sized { /// /// If necessary, the source code can be accessed directly by getting the /// node's byte range. - fn new(node: Node, source: &str) -> Result; + fn new(source: &str, cursor: &mut TreeCursor) -> Result; /// Execute dust code by traversing the tree fn run(&self, context: &mut VariableMap) -> Result; @@ -99,17 +99,20 @@ impl<'context, 'code> Evaluator<'context, 'code> { } fn run(self) -> Vec> { - let mut cursor = self.tree.walk(); - let node = cursor.node(); + let mut cursor_0 = self.tree.walk(); + let mut cursor_1 = self.tree.walk(); + let node = cursor_0.node(); let item_count = node.child_count(); let mut results = Vec::with_capacity(item_count); println!("{}", node.to_sexp()); - assert_eq!(cursor.node().kind(), "root"); + assert_eq!(cursor_0.node().kind(), "root"); - for item_node in node.children(&mut cursor) { - let item_result = Item::new(item_node, self.source); + cursor_1.goto_first_child(); + + for item_node in node.named_children(&mut cursor_0) { + let item_result = Item::new(self.source, &mut cursor_1); match item_result { Ok(item) => { @@ -137,10 +140,12 @@ pub enum Item { } impl EvaluatorTree for Item { - fn new(node: Node, source: &str) -> Result { - assert_eq!(node.kind(), "item"); + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); + let child = cursor.node(); - let child = node.child(0).unwrap(); + assert_eq!(node.kind(), "item"); if child.kind() == "comment" { let byte_range = child.byte_range(); @@ -148,7 +153,7 @@ impl EvaluatorTree for Item { Ok(Item::Comment(comment_text.to_string())) } else if child.kind() == "statement" { - Ok(Item::Statement(Statement::new(child, source)?)) + Ok(Item::Statement(Statement::new(source, cursor)?)) } else { Err(Error::UnexpectedSyntax { expected: "comment or statement", @@ -177,12 +182,15 @@ pub enum Statement { } impl EvaluatorTree for Statement { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); + let child = cursor.node(); + assert_eq!(node.kind(), "statement"); - let child = node.child(0).unwrap(); match child.kind() { - "expression" => Ok(Self::Expression(Expression::new(child, source)?)), + "expression" => Ok(Self::Expression(Expression::new(source, cursor)?)), _ => Err(Error::UnexpectedSyntax { expected: "expression", actual: child.kind(), @@ -209,17 +217,20 @@ pub enum Expression { } impl EvaluatorTree for Expression { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); + let child = cursor.node(); + assert_eq!(node.kind(), "expression"); - let child = node.child(0).unwrap(); let expression = match child.kind() { - "identifier" => Self::Identifier(Identifier::new(child, source)?), - "value" => Expression::Value(Value::new(child, source)?), - "control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(child, source)?)), - "assignment" => Expression::Assignment(Box::new(Assignment::new(child, source)?)), - "math" => Expression::Math(Box::new(Math::new(child, source)?)), - "function_call" => Expression::FunctionCall(FunctionCall::new(child, source)?), + "identifier" => Self::Identifier(Identifier::new(source, cursor)?), + "value" => Expression::Value(Value::new(source, cursor)?), + "control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)), + "assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)), + "math" => Expression::Math(Box::new(Math::new(source, cursor)?)), + "function_call" => Expression::FunctionCall(FunctionCall::new(source, cursor)?), _ => return Err(Error::UnexpectedSyntax { expected: "identifier, operation, control_flow, assignment, math, function_call or value", @@ -257,7 +268,9 @@ impl Identifier { } impl EvaluatorTree for Identifier { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + assert_eq!(node.kind(), "identifier"); let identifier = &source[node.byte_range()]; @@ -280,23 +293,31 @@ pub struct ControlFlow { } impl EvaluatorTree for ControlFlow { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); + let child = cursor.node(); + assert_eq!(node.kind(), "control_flow"); // Skip the child nodes for the keywords "if", "then" and "else". - let if_expression_node = node.child(1).unwrap(); - let then_statement_node = node.child(3).unwrap(); - let else_statement_node = node.child(5); + let if_expression_node = child.next_named_sibling().unwrap(); + let if_expression = Expression::new(source, cursor)?; + + let then_statement_node = node.next_named_sibling().unwrap(); + let then_statement = Statement::new(source, cursor)?; + + let else_statement_node = node.next_named_sibling(); let else_statement = if let Some(child) = else_statement_node { - Some(Statement::new(child, source)?) + Some(Statement::new(source, cursor)?) } else { None }; Ok(ControlFlow { - if_expression: Expression::new(if_expression_node, source)?, - then_statement: Statement::new(then_statement_node, source)?, + if_expression, + then_statement, else_statement, }) } @@ -321,22 +342,30 @@ pub struct Assignment { } impl EvaluatorTree for Assignment { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); assert_eq!(node.kind(), "assignment"); - let identifier_node = node.child(0).unwrap(); - let statement_node = node.child(2).unwrap(); + cursor.goto_next_sibling(); + let identifier = Identifier::new(source, cursor)?; + + cursor.goto_next_sibling(); + let statement = Statement::new(source, cursor)?; + + cursor.goto_next_sibling(); Ok(Assignment { - identifier: Identifier::new(identifier_node, source)?, - statement: Statement::new(statement_node, source)?, + identifier, + statement, }) } fn run(&self, context: &mut VariableMap) -> Result { + let key = self.identifier.clone().take_inner(); let value = self.statement.run(context)?; - context.set_value(self.identifier.inner(), value)?; + context.set_value(key, value)?; Ok(Value::Empty) } @@ -350,12 +379,15 @@ pub struct Math { } impl EvaluatorTree for Math { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); assert_eq!(node.kind(), "math"); - let left_node = node.child(0).unwrap(); - let operator_node = node.child(1).unwrap().child(0).unwrap(); - let right_node = node.child(2).unwrap(); + cursor.goto_first_child(); + let left = Expression::new(source, cursor)?; + + cursor.goto_next_sibling(); + let operator_node = cursor.node(); let operator = match operator_node.kind() { "+" => MathOperator::Add, "-" => MathOperator::Subtract, @@ -371,10 +403,13 @@ impl EvaluatorTree for Math { } }; + cursor.goto_next_sibling(); + let right = Expression::new(source, cursor)?; + Ok(Math { - left: Expression::new(left_node, source)?, + left, operator, - right: Expression::new(right_node, source)?, + right, }) } @@ -409,23 +444,25 @@ pub struct FunctionCall { } impl EvaluatorTree for FunctionCall { - fn new(node: Node, source: &str) -> Result { + fn new(source: &str, cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); assert_eq!(node.kind(), "function_call"); - let identifier_node = node.child(0).unwrap(); + cursor.goto_first_child(); + let identifier = Identifier::new(source, cursor)?; + let mut expressions = Vec::new(); for index in 2..node.child_count() - 1 { - let child = node.child(index).unwrap(); - if child.kind() == "expression" { - let expression = Expression::new(node, source)?; + cursor.goto_next_sibling(); - expressions.push(expression); - } + let expression = Expression::new(source, cursor)?; + + expressions.push(expression); } Ok(FunctionCall { - identifier: Identifier::new(identifier_node, source)?, + identifier, expressions, }) } @@ -504,8 +541,8 @@ mod tests { fn evaluate_map() { let mut map = VariableMap::new(); - map.set_value("x", Value::Integer(1)).unwrap(); - map.set_value("foo", Value::String("bar".to_string())) + map.set_value("x".to_string(), Value::Integer(1)).unwrap(); + map.set_value("foo".to_string(), Value::String("bar".to_string())) .unwrap(); assert_eq!(eval("map { x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]); diff --git a/src/tools/collections.rs b/src/tools/collections.rs index 0cb6ff8..273dda2 100644 --- a/src/tools/collections.rs +++ b/src/tools/collections.rs @@ -57,7 +57,7 @@ impl Tool for Transform { for value in list { let mut context = VariableMap::new(); - context.set_value("input", value.clone())?; + context.set_value("input".to_string(), value.clone())?; let mapped_value = function.run_with_context(&mut context)?; @@ -321,7 +321,7 @@ impl Tool for Select { for (key, value) in map.inner() { if column_names.contains(key) { - selected.set_value(key, value.clone())?; + selected.set_value(key.to_string(), value.clone())?; } } @@ -402,7 +402,7 @@ impl Tool for Where { for (column_index, cell) in row.iter().enumerate() { let column_name = table.column_names().get(column_index).unwrap(); - context.set_value(column_name, cell.clone())?; + context.set_value(column_name.to_string(), cell.clone())?; } let keep_row = function.run_with_context(&mut context)?.as_boolean()?; diff --git a/src/value/mod.rs b/src/value/mod.rs index bac95a3..9ff755f 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -10,14 +10,14 @@ use serde::{ ser::SerializeTuple, Deserialize, Serialize, Serializer, }; -use tree_sitter::Node; +use tree_sitter::{Node, TreeCursor}; use std::{ cmp::Ordering, convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, - ops::{Add, Sub}, + ops::{Add, Range, Sub}, }; pub mod function; @@ -48,129 +48,79 @@ pub enum Value { } impl Value { - pub fn new(node: Node, source: &str) -> Result { - assert!( - node.kind() == "value" || node.kind() == "list", - "{}", - node.kind() - ); + pub fn new(source: &str, mut cursor: &mut TreeCursor) -> Result { + let node = cursor.node(); + cursor.goto_first_child(); + let child = cursor.node(); - let child = node.child(0).unwrap(); - let value_snippet = &source[node.byte_range()]; + assert_eq!(node.kind(), "value"); match child.kind() { - "integer" => { - let raw = value_snippet.parse::().unwrap_or_default(); - - Ok(Value::Integer(raw)) - } - "string" => { - let quote_str = &value_snippet.chars().nth(0).unwrap(); - let without_quotes = value_snippet.trim_matches(*quote_str); - - Ok(Value::String(without_quotes.to_string())) - } - "boolean" => { - let raw = value_snippet.parse::().unwrap_or_default(); - - Ok(Value::Boolean(raw)) - } - "float" => { - let raw = value_snippet.parse::().unwrap_or_default(); - - Ok(Value::Float(raw)) + "integer" | "float" | "boolean" | "string" | "empty" => { + Value::from_syntax_node(child, source) } "list" => { - let grandchild_count = child.child_count(); - let mut values = Vec::with_capacity(grandchild_count); + let list_length = child.named_child_count(); + let mut values = Vec::with_capacity(list_length); - let mut previous_grandchild = child.child(0).unwrap(); + cursor.goto_first_child(); - for _ in 0..grandchild_count { - if let Some(current_node) = previous_grandchild.next_sibling() { - if current_node.kind() == "value" { - let value = Value::new(current_node, source)?; + for value_node in child.children_by_field_name("item", &mut cursor) { + let value = Value::from_syntax_node(value_node.child(0).unwrap(), source)?; - values.push(value); - } - previous_grandchild = current_node - } + values.push(value); } Ok(Value::List(values)) } "table" => { - let child_count = node.child_count(); let mut column_names = Vec::new(); - let mut rows = Vec::new(); - - // Skip the first and last nodes because they are pointy braces. - for index in 0..child_count { - let child = node.child(index).unwrap(); - - if child.kind() == "identifier" { - let identifier = Identifier::new(child, source)?; - - column_names.push(identifier.take_inner()) - } - - if child.kind() == "list" { - let child_value = Value::new(node, source)?; - - if let Value::List(row) = child_value { - rows.push(row); - } - } - } let mut table = Table::new(column_names); - table.reserve(rows.len()); - - for row in rows { - table.insert(row)?; - } Ok(Value::Table(table)) } "map" => { - let child_count = node.child_count(); + let grandchild_count = child.child_count(); let mut map = VariableMap::new(); + + let mut previous_grandchild = child.child(0).unwrap(); let mut key = String::new(); - for index in 0..child_count { - let child = node.child(index).unwrap(); + for _ in 0..grandchild_count { + if let Some(current_node) = previous_grandchild.next_sibling() { + if current_node.kind() == "identifier" { + key = Identifier::new(source, cursor)?.take_inner(); + } - if child.kind() == "identifier" { - let identifier = Identifier::new(child, source)?; + if current_node.kind() == "value" { + let value = Value::new(source, cursor)?; - key = identifier.take_inner() - } + map.set_value(key.clone(), value)?; + } - if child.kind() == "value" { - let value = Value::new(child, source)?; - - map.set_value(key.as_str(), value)?; + previous_grandchild = current_node } } Ok(Value::Map(map)) } "function" => { - let child_count = node.child_count(); + let child_count = child.child_count(); let mut identifiers = Vec::new(); let mut statements = Vec::new(); for index in 0..child_count { - let child = node.child(index).unwrap(); + let child = child.child(index).unwrap(); if child.kind() == "identifier" { - let identifier = Identifier::new(child, source)?; + let identifier = Identifier::new(source, cursor)?; identifiers.push(identifier) } if child.kind() == "statement" { - let statement = Statement::new(child, source)?; + let statement = Statement::new(source, cursor)?; statements.push(statement) } @@ -178,15 +128,58 @@ impl Value { Ok(Value::Function(Function::new(identifiers, statements))) } - "empty" => Ok(Value::Empty), _ => Err(Error::UnexpectedSyntax { - expected: "integer, string, boolean, float, list, table, function or empty", + expected: "integer, float, boolean, string list, table, map, function or empty", actual: child.kind(), location: child.start_position(), }), } } + pub fn from_syntax_node(node: Node, source: &str) -> Result { + match node.kind() { + "integer" => Value::integer_from_source(source, node.byte_range()), + "float" => Value::integer_from_source(source, node.byte_range()), + "boolean" => Value::integer_from_source(source, node.byte_range()), + "string" => Value::integer_from_source(source, node.byte_range()), + "empty" => Ok(Value::Empty), + _ => Err(Error::UnexpectedSyntax { + expected: "integer, float, boolean, string or empty", + actual: node.kind(), + location: node.start_position(), + }), + } + } + + pub fn integer_from_source(source: &str, byte_range: Range) -> Result { + let value_snippet = &source[byte_range]; + let raw = value_snippet.parse::().unwrap_or_default(); + + Ok(Value::Integer(raw)) + } + + pub fn float_from_source(source: &str, byte_range: Range) -> Result { + let value_snippet = &source[byte_range]; + let raw = value_snippet.parse::().unwrap_or_default(); + + Ok(Value::Float(raw)) + } + + pub fn boolean_from_source(source: &str, byte_range: Range) -> Result { + let value_snippet = &source[byte_range]; + let raw = value_snippet.parse::().unwrap_or_default(); + + Ok(Value::Boolean(raw)) + } + + pub fn string_from_source(source: &str, byte_range: Range) -> Result { + let value_snippet = &source[byte_range]; + let quote_str = &value_snippet.chars().nth(0).unwrap(); + let without_quotes = value_snippet.trim_matches(*quote_str); + + Ok(Value::String(without_quotes.to_string())) + } + pub fn value_type(&self) -> ValueType { ValueType::from(self) } @@ -612,7 +605,7 @@ impl TryFrom for Value { for (key, node_value) in object.iter() { let value = Value::try_from(node_value)?; - map.set_value(key, value)?; + map.set_value(key.to_string(), value)?; } Ok(Value::Map(map)) @@ -650,7 +643,7 @@ impl TryFrom<&JsonValue> for Value { for (key, node_value) in object.iter() { let value = Value::try_from(node_value)?; - map.set_value(key, value)?; + map.set_value(key.to_string(), value)?; } Ok(Value::Map(map)) diff --git a/src/value/variable_map.rs b/src/value/variable_map.rs index e92fd73..04d8ecf 100644 --- a/src/value/variable_map.rs +++ b/src/value/variable_map.rs @@ -49,7 +49,7 @@ impl VariableMap { if let Ok(function) = value.as_function() { let mut context = self.clone(); - context.set_value("input", argument.clone())?; + context.set_value("input".to_string(), argument.clone())?; return function.run_with_context(&mut context); } @@ -95,8 +95,8 @@ impl VariableMap { /// Assigns a variable with a Value and the identifier as its key, allowing dot notation to /// assign nested lists and maps. Returns an error if a List or Map is indexed incorrectly. - pub fn set_value(&mut self, identifier: &str, value: Value) -> Result<()> { - let split = identifier.split_once('.'); + pub fn set_value(&mut self, key: String, value: Value) -> Result<()> { + let split = key.split_once('.'); if let Some((identifier, next_identifier)) = split { let get_value = self.variables.get_mut(identifier); @@ -121,7 +121,7 @@ impl VariableMap { Ok(()) } else if let Value::Map(map) = found_value { - map.set_value(next_identifier, value) + map.set_value(next_identifier.to_string(), value) } else { Err(Error::ExpectedMap { actual: found_value.clone(), @@ -130,7 +130,7 @@ impl VariableMap { } else { let mut new_map = VariableMap::new(); - new_map.set_value(next_identifier, value)?; + new_map.set_value(next_identifier.to_string(), value)?; self.variables .insert(identifier.to_string(), Value::Map(new_map)); @@ -138,7 +138,7 @@ impl VariableMap { Ok(()) } } else { - self.variables.insert(identifier.to_string(), value); + self.variables.insert(key.to_string(), value); Ok(()) } @@ -177,7 +177,7 @@ impl From<&Table> for VariableMap { let mut map = VariableMap::new(); for (row_index, row) in value.rows().iter().enumerate() { - map.set_value(&row_index.to_string(), Value::List(row.clone())) + map.set_value(row_index.to_string(), Value::List(row.clone())) .unwrap(); } @@ -193,7 +193,7 @@ mod tests { fn get_and_set_simple_value() { let mut map = VariableMap::new(); - map.set_value("x", Value::Integer(1)).unwrap(); + map.set_value("x".to_string(), Value::Integer(1)).unwrap(); assert_eq!(Value::Integer(1), map.get_value("x").unwrap().unwrap()); } @@ -202,12 +202,13 @@ mod tests { fn get_and_set_nested_maps() { let mut map = VariableMap::new(); - map.set_value("x", Value::Map(VariableMap::new())).unwrap(); - map.set_value("x.x", Value::Map(VariableMap::new())) + map.set_value("x".to_string(), Value::Map(VariableMap::new())) .unwrap(); - map.set_value("x.x.x", Value::Map(VariableMap::new())) + map.set_value("x.x".to_string(), Value::Map(VariableMap::new())) .unwrap(); - map.set_value("x.x.x.x", Value::Map(VariableMap::new())) + map.set_value("x.x.x".to_string(), Value::Map(VariableMap::new())) + .unwrap(); + map.set_value("x.x.x.x".to_string(), Value::Map(VariableMap::new())) .unwrap(); assert_eq!(