From 5551f40ffda587db2721ac72596e4be128217aac Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 2 Oct 2023 23:19:01 -0400 Subject: [PATCH] Implement tables --- src/interface.rs | 133 ++++++++++++--------------- src/value/mod.rs | 224 +++++++++++++++++++++++++++++++-------------- src/value/table.rs | 46 +++++++--- 3 files changed, 241 insertions(+), 162 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 3176e05..5e714fc 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::{Parser, Tree as TSTree, TreeCursor}; +use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor}; use crate::{language, Error, Primitive, 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(source: &str, cursor: &mut TreeCursor) -> Result; + fn from_syntax_node(node: Node, source: &str) -> Result; /// Execute dust code by traversing the tree fn run(&self, context: &mut VariableMap) -> Result; @@ -109,10 +109,8 @@ impl<'context, 'code> Evaluator<'context, 'code> { assert_eq!(cursor_0.node().kind(), "root"); - cursor_1.goto_first_child(); - - for _ in node.children(&mut cursor_0) { - let item_result = Item::new(self.source, &mut cursor_1); + for item_node in node.children(&mut cursor_0) { + let item_result = Item::from_syntax_node(item_node, self.source); match item_result { Ok(item) => { @@ -140,12 +138,10 @@ pub enum Item { } impl EvaluatorTree for Item { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); - cursor.goto_first_child(); - let child = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { + debug_assert_eq!(node.kind(), "item"); - assert_eq!(node.kind(), "item"); + let child = node.child(0).unwrap(); if child.kind() == "comment" { let byte_range = child.byte_range(); @@ -153,7 +149,7 @@ impl EvaluatorTree for Item { Ok(Item::Comment(comment_text.to_string())) } else if child.kind() == "statement" { - Ok(Item::Statement(Statement::new(source, cursor)?)) + Ok(Item::Statement(Statement::from_syntax_node(child, source)?)) } else { Err(Error::UnexpectedSyntax { expected: "comment or statement", @@ -182,12 +178,15 @@ pub enum Statement { } impl EvaluatorTree for Statement { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - cursor.goto_first_child(); - let child = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { + debug_assert_eq!(node.kind(), "statement"); + + let child = node.child(0).unwrap(); match child.kind() { - "expression" => Ok(Self::Expression(Expression::new(source, cursor)?)), + "expression" => Ok(Self::Expression(Expression::from_syntax_node( + child, source, + )?)), _ => Err(Error::UnexpectedSyntax { expected: "expression", actual: child.kind(), @@ -214,20 +213,24 @@ pub enum Expression { } impl EvaluatorTree for Expression { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); - cursor.goto_first_child(); - let child = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { + debug_assert_eq!(node.kind(), "expression"); - assert_eq!(node.kind(), "expression"); + let child = node.child(0).unwrap(); let expression = match child.kind() { - "identifier" => Self::Identifier(Identifier::new(source, cursor)?), - "value" => Expression::Value(Value::from_source(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)?), + "identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?), + "value" => Expression::Value(Value::from_syntax_node(child, source)?), + "control_flow" => { + Expression::ControlFlow(Box::new(ControlFlow::from_syntax_node(child, source)?)) + } + "assignment" => { + Expression::Assignment(Box::new(Assignment::from_syntax_node(child, source)?)) + } + "math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)), + "function_call" => { + Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?) + } _ => return Err(Error::UnexpectedSyntax { expected: "identifier, operation, control_flow, assignment, math, function_call or value", @@ -265,9 +268,7 @@ impl Identifier { } impl EvaluatorTree for Identifier { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); - + fn from_syntax_node(node: Node, source: &str) -> Result { assert_eq!(node.kind(), "identifier"); let identifier = &source[node.byte_range()]; @@ -290,35 +291,26 @@ pub struct ControlFlow { } impl EvaluatorTree for ControlFlow { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { assert_eq!(node.kind(), "control_flow"); - println!("{node:?}"); - - // Skip the child nodes for the keywords "if", "then" and "else". - let if_node = node.child_by_field_name("if_expression").unwrap(); - - cursor.reset(if_node); - - let if_expression = Expression::new(source, cursor)?; - - println!("{:?}", cursor.node()); + let if_expression = Expression::from_syntax_node(if_node, source)?; let then_node = node.child_by_field_name("then_statement").unwrap(); + let then_statement = Statement::from_syntax_node(then_node, source)?; - cursor.reset(then_node); - - let position = cursor.node(); - let then_statement = Statement::new(source, cursor)?; - - cursor.reset(position); + let else_node = node.child_by_field_name("else_statement"); + let else_statement = if let Some(node) = else_node { + Some(Statement::from_syntax_node(node, source)?) + } else { + None + }; Ok(ControlFlow { if_expression, then_statement, - else_statement: None, + else_statement, }) } @@ -342,18 +334,14 @@ pub struct Assignment { } impl EvaluatorTree for Assignment { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); - cursor.goto_first_child(); + fn from_syntax_node(node: Node, source: &str) -> Result { assert_eq!(node.kind(), "assignment"); - cursor.goto_next_sibling(); - let identifier = Identifier::new(source, cursor)?; + let identifier_node = node.child(0).unwrap(); + let identifier = Identifier::from_syntax_node(identifier_node, source)?; - cursor.goto_next_sibling(); - let statement = Statement::new(source, cursor)?; - - cursor.goto_next_sibling(); + let statement_node = node.child(2).unwrap(); + let statement = Statement::from_syntax_node(statement_node, source)?; Ok(Assignment { identifier, @@ -379,15 +367,13 @@ pub struct Math { } impl EvaluatorTree for Math { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { assert_eq!(node.kind(), "math"); - cursor.goto_first_child(); - let left = Expression::new(source, cursor)?; + let left_node = node.child(0).unwrap(); + let left = Expression::from_syntax_node(left_node, source)?; - cursor.goto_next_sibling(); - let operator_node = cursor.node(); + let operator_node = left_node.next_sibling().unwrap(); let operator = match operator_node.kind() { "+" => MathOperator::Add, "-" => MathOperator::Subtract, @@ -403,8 +389,8 @@ impl EvaluatorTree for Math { } }; - cursor.goto_next_sibling(); - let right = Expression::new(source, cursor)?; + let right_node = operator_node.next_sibling().unwrap(); + let right = Expression::from_syntax_node(right_node, source)?; Ok(Math { left, @@ -444,22 +430,15 @@ pub struct FunctionCall { } impl EvaluatorTree for FunctionCall { - fn new(source: &str, cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); + fn from_syntax_node(node: Node, source: &str) -> Result { assert_eq!(node.kind(), "function_call"); - cursor.goto_first_child(); - let identifier = Identifier::new(source, cursor)?; + let identifier_node = node.child(0).unwrap(); + let identifier = Identifier::from_syntax_node(identifier_node, source)?; let mut expressions = Vec::new(); - for index in 2..node.child_count() - 1 { - cursor.goto_next_sibling(); - - let expression = Expression::new(source, cursor)?; - - expressions.push(expression); - } + todo!(); Ok(FunctionCall { identifier, diff --git a/src/value/mod.rs b/src/value/mod.rs index 9f2c4c9..6388f48 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -37,6 +37,50 @@ pub enum Primitive { Empty, } +impl Primitive { + fn from_syntax_node(node: Node, source: &str) -> Result { + match node.kind() { + "integer" => Primitive::integer_from_source(source, node.byte_range()), + "float" => Primitive::float_from_source(source, node.byte_range()), + "boolean" => Primitive::boolean_from_source(source, node.byte_range()), + "string" => Primitive::string_from_source(source, node.byte_range()), + "empty" => Ok(Primitive::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(Primitive::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(Primitive::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(Primitive::Boolean(raw)) + } + + pub fn string_from_source(source: &str, byte_range: Range) -> Result { + let value_snippet = &source[byte_range]; + let without_quotes = &value_snippet[1..value_snippet.len() - 1]; + + Ok(Primitive::String(without_quotes.to_string())) + } +} + impl Eq for Primitive {} impl Ord for Primitive { @@ -74,53 +118,90 @@ pub enum Value { } impl Value { - pub fn from_source(source: &str, mut cursor: &mut TreeCursor) -> Result { - let node = cursor.node(); - cursor.goto_first_child(); - let child = cursor.node(); + pub fn from_syntax_node(node: Node, source: &str) -> Result { + debug_assert_eq!(node.kind(), "value"); - assert_eq!(node.kind(), "value"); + let child = node.child(0).unwrap(); match child.kind() { - "integer" | "float" | "boolean" | "string" | "empty" => { - Value::simple_from_syntax_node(node, source) - } + "integer" | "float" | "boolean" | "string" | "empty" => Ok(Value::Primitive( + Primitive::from_syntax_node(child, source)?, + )), "list" => { - let list_length = child.named_child_count(); - let mut values = Vec::with_capacity(list_length); + let item_count = child.named_child_count(); + let mut values = Vec::with_capacity(item_count); + let mut current_node = child.child(1).unwrap(); - cursor.goto_first_child(); + while values.len() < item_count { + if current_node.is_named() { + let value = Value::from_syntax_node(current_node, source)?; - for value_node in child.children_by_field_name("item", &mut cursor) { - let value = Value::simple_from_syntax_node(value_node, source)?; + values.push(value); + } - values.push(value); + current_node = current_node.next_sibling().unwrap(); } Ok(Value::List(values)) } "table" => { - let mut column_names = Vec::new(); + let mut current_node = child.child(0).unwrap(); + let header_and_row_count = child.named_child_count(); - let mut table = Table::new(column_names); + 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)) } "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(); - for key_value_node in child.children_by_field_name("key_value_pair", &mut cursor) { - if key_value_node.kind() == "identifier" { - let identifier_text = &source[key_value_node.byte_range()]; + while map.len() < pair_count { + if current_node.kind() == "identifier" { + let identifier_text = &source[current_node.byte_range()]; current_key = identifier_text.to_string(); } - if key_value_node.kind() == "value" { - let value = Value::simple_from_syntax_node(key_value_node, source)?; + if current_node.kind() == "value" { + let value = Value::from_syntax_node(current_node, source)?; + map.set_value(current_key.to_string(), value)?; } + + if let Some(node) = current_node.next_sibling() { + current_node = node; + } else { + break; + } } Ok(Value::Map(map)) @@ -133,17 +214,17 @@ impl Value { for index in 0..child_count { let child = child.child(index).unwrap(); - if child.kind() == "identifier" { - let identifier = Identifier::new(source, cursor)?; + // if child.kind() == "identifier" { + // let identifier = Identifier::new(source, cursor)?; - identifiers.push(identifier) - } + // identifiers.push(identifier) + // } - if child.kind() == "statement" { - let statement = Statement::new(source, cursor)?; + // if child.kind() == "statement" { + // let statement = Statement::new(source, cursor)?; - statements.push(statement) - } + // statements.push(statement) + // } } Ok(Value::Function(Function::new(identifiers, statements))) @@ -156,56 +237,53 @@ impl Value { } } - /// Creates a simple value from the given source code and a node in the - /// syntax tree. - /// - /// - pub fn simple_from_syntax_node(node: Node, source: &str) -> Result { - let child = node.child(0).unwrap(); + pub fn list_from_syntax_node(node: Node, source: &str) -> Result { + debug_assert_eq!(node.kind(), "list"); - match child.kind() { - "integer" => Value::integer_from_source(source, child.byte_range()), - "float" => Value::float_from_source(source, child.byte_range()), - "boolean" => Value::boolean_from_source(source, child.byte_range()), - "string" => Value::string_from_source(source, child.byte_range()), - "empty" => Ok(Value::Primitive(Primitive::Empty)), - _ => Err(Error::UnexpectedSyntax { - expected: "integer, float, boolean, string or empty", - actual: child.kind(), - location: child.start_position(), - }), + let item_count = node.named_child_count(); + let mut values = Vec::with_capacity(item_count); + let mut current_node = node.child(1).unwrap(); + + while values.len() < item_count { + if current_node.is_named() { + let value = Value::from_syntax_node(current_node, source)?; + + values.push(value); + } + + current_node = current_node.next_sibling().unwrap(); } + + Ok(Value::List(values)) } - 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(); + // 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::Primitive(Primitive::Integer(raw))) - } + // Ok(Primitive::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(); + // 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::Primitive(Primitive::Float(raw))) - } + // Ok(Primitive::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(); + // 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::Primitive(Primitive::Boolean(raw))) - } + // Ok(Primitive::Boolean(raw)) + // } - pub fn string_from_source(source: &str, byte_range: Range) -> Result { - let value_snippet = &source[byte_range]; - let without_quotes = &value_snippet[1..value_snippet.len() - 1]; + // pub fn string_from_source(source: &str, byte_range: Range) -> Result { + // let value_snippet = &source[byte_range]; + // let without_quotes = &value_snippet[1..value_snippet.len() - 1]; - Ok(Value::Primitive(Primitive::String( - without_quotes.to_string(), - ))) - } + // Ok(Primitive::String(without_quotes.to_string())) + // } pub fn value_type(&self) -> ValueType { ValueType::from(self) @@ -532,7 +610,13 @@ impl Display for Value { Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int), Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean), Value::Primitive(Primitive::Empty) => write!(f, "()"), - Value::List(list) => Table::from(list).fmt(f), + Value::List(list) => { + write!(f, "(")?; + for value in list { + write!(f, " {value} ")?; + } + write!(f, ")") + } Value::Map(map) => write!(f, "{map}"), Value::Table(table) => write!(f, "{table}"), Value::Function(function) => write!(f, "{function}"), diff --git a/src/value/table.rs b/src/value/table.rs index ea744ba..fdae03e 100644 --- a/src/value/table.rs +++ b/src/value/table.rs @@ -8,26 +8,42 @@ use std::{ #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Table { - header: Vec, + headers: Vec, rows: Vec>, primary_key_index: usize, } impl Table { - pub fn new(column_names: Vec) -> Self { + pub fn new(headers: Vec) -> Self { Table { - header: column_names, + headers, rows: Vec::new(), primary_key_index: 0, } } + pub fn with_capacity(capacity: usize, headers: Vec) -> Self { + Table { + headers, + rows: Vec::with_capacity(capacity), + primary_key_index: 0, + } + } + + pub fn from_raw_parts(headers: Vec, rows: Vec>) -> Self { + Table { + headers, + rows, + primary_key_index: 0, + } + } + pub fn reserve(&mut self, additional: usize) { self.rows.reserve(additional); } pub fn column_names(&self) -> &Vec { - &self.header + &self.headers } pub fn rows(&self) -> &Vec> { @@ -47,9 +63,9 @@ impl Table { } pub fn insert(&mut self, row: Vec) -> Result<()> { - if row.len() != self.header.len() { + if row.len() != self.headers.len() { return Err(Error::WrongColumnAmount { - expected: self.header.len(), + expected: self.headers.len(), actual: row.len(), }); } @@ -82,10 +98,10 @@ impl Table { let mut new_row = Vec::new(); for (i, value) in row.iter().enumerate() { - let column_name = self.header.get(i).unwrap(); + let column_name = self.headers.get(i).unwrap(); let new_table_column_index = new_table - .header + .headers .iter() .enumerate() .find_map(|(index, new_column_name)| { @@ -125,7 +141,7 @@ impl Table { } pub fn filter(&self, column_name: &str, expected: &Value) -> Option { - let mut filtered = Table::new(self.header.clone()); + let mut filtered = Table::new(self.headers.clone()); let column_index = self.get_column_index(column_name)?; for row in &self.rows { @@ -140,7 +156,7 @@ impl Table { } pub fn get_column_index(&self, column_name: &str) -> Option { - let column_names = &self.header; + let column_names = &self.headers; for (i, column) in column_names.iter().enumerate() { if column == column_name { return Some(i); @@ -157,7 +173,7 @@ impl Display for Table { table .load_preset("││──├─┼┤│ ┬┴╭╮╰╯") .set_content_arrangement(ContentArrangement::Dynamic) - .set_header(&self.header); + .set_header(&self.headers); for row in &self.rows { let row = row.iter().map(|value| { @@ -209,7 +225,7 @@ impl Display for Table { table.add_row(row); } - if self.header.is_empty() { + if self.headers.is_empty() { table.set_header(["empty"]); } @@ -360,7 +376,7 @@ impl Eq for Table {} impl PartialEq for Table { fn eq(&self, other: &Self) -> bool { - if self.header != other.header { + if self.headers != other.headers { return false; } @@ -370,12 +386,12 @@ impl PartialEq for Table { impl PartialOrd for Table { fn partial_cmp(&self, other: &Self) -> Option { - self.header.partial_cmp(&other.header) + self.headers.partial_cmp(&other.headers) } } impl Ord for Table { fn cmp(&self, other: &Self) -> Ordering { - self.header.cmp(&other.header) + self.headers.cmp(&other.headers) } }