diff --git a/examples/table.ds b/examples/table.ds index f457d9b..4715bae 100644 --- a/examples/table.ds +++ b/examples/table.ds @@ -1,24 +1,26 @@ -table = create_table [ +my_table = table [ ["a", 1, true] ["b", 2, true] ["a", 3, true] ] -test_table = create_table [ +test_table = table [ ["a", true] ["b", true] ["a", true] ] -select = select from table +test_select = select from my_table -(assert_equal select, test_table) +(assert_equal test_select, test_table) -test_table = create_table [ +test_table = table [ ["a", 1, true] ["a", 3, true] ] -select_where = select * from table where text == "a" +test_select_where = select <> from my_table { + text == "a" +} -assert_equal(select_where, test_table); +(assert_equal test_select_where, test_table) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 7f159ff..4f38905 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -1,39 +1,22 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{tool::Tool, AbstractTree, Result, Value, VariableMap}; +use crate::{AbstractTree, Error, Result, Value, VariableMap, BUILT_IN_FUNCTIONS}; use super::{expression::Expression, identifier::Identifier}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct FunctionCall { - name: FunctionName, + name: Identifier, arguments: Vec, } -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub enum FunctionName { - Identifier(Identifier), - Tool(Tool), -} - impl AbstractTree for FunctionCall { 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(source, name_node)?) - } - "tool" => { - let tool_node = name_node.child(0).unwrap(); - let tool = Tool::new(tool_node.kind())?; - - FunctionName::Tool(tool) - } - _ => panic!(""), - }; + let name = Identifier::from_syntax_node(source, name_node)?; let mut arguments = Vec::new(); @@ -51,25 +34,17 @@ impl AbstractTree for FunctionCall { } fn run(&self, source: &str, context: &mut VariableMap) -> Result { - let identifier = match &self.name { - FunctionName::Identifier(identifier) => identifier, - FunctionName::Tool(tool) => { - let mut values = Vec::with_capacity(self.arguments.len()); - - for expression in &self.arguments { - let value = expression.run(source, context)?; - - values.push(value); - } - - return tool.run(&values); - } - }; - let key = identifier.inner(); + let key = self.name.inner(); let definition = if let Some(value) = context.get_value(key)? { value.as_function().cloned()? } else { - return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone())); + for function in BUILT_IN_FUNCTIONS { + if key == function.name() { + return function.run(source, context); + } + } + + return Err(Error::FunctionIdentifierNotFound(self.name.clone())); }; let id_expr_pairs = definition.identifiers().iter().zip(self.arguments.iter()); diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index c6355ff..7ce2cc0 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -8,6 +8,7 @@ pub mod assignment; pub mod r#async; +pub mod built_in_functions; pub mod expression; pub mod filter; pub mod find; @@ -20,16 +21,16 @@ pub mod logic; pub mod r#match; pub mod math; pub mod remove; +pub mod select; pub mod statement; -pub mod tool; pub mod transform; pub mod value_node; pub mod r#while; pub use { - assignment::*, expression::*, filter::*, find::*, function_call::*, identifier::*, if_else::*, - item::*, logic::*, math::*, r#async::*, r#for::*, r#match::*, r#while::*, remove::*, - statement::*, transform::*, + assignment::*, built_in_functions::*, expression::*, filter::*, find::*, function_call::*, + identifier::*, if_else::*, item::*, logic::*, math::*, r#async::*, r#for::*, r#match::*, + r#while::*, remove::*, select::*, statement::*, transform::*, }; use tree_sitter::Node; diff --git a/src/abstract_tree/remove.rs b/src/abstract_tree/remove.rs index 698c7c8..b019cf2 100644 --- a/src/abstract_tree/remove.rs +++ b/src/abstract_tree/remove.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::{expression, AbstractTree, Expression, Identifier, Item, Value}; +use crate::{AbstractTree, Expression, Identifier, Item, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Remove { diff --git a/src/abstract_tree/select.rs b/src/abstract_tree/select.rs new file mode 100644 index 0000000..75878e1 --- /dev/null +++ b/src/abstract_tree/select.rs @@ -0,0 +1,71 @@ +use serde::{Deserialize, Serialize}; + +use crate::{identifier, AbstractTree, Expression, Identifier, Item, Table, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct Select { + identifiers: Vec, + expression: Expression, + item: Option, +} + +impl AbstractTree for Select { + fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result { + let child_count = node.child_count(); + let mut identifiers = Vec::new(); + + for index in 2..child_count - 4 { + let node = node.child(index).unwrap(); + + if node.kind() == "identifier" { + let identifier = Identifier::from_syntax_node(source, node)?; + identifiers.push(identifier); + } + + if node.kind() == ">" { + break; + } + } + + let final_node = node.child(child_count - 1).unwrap(); + + let item = if final_node.kind() == "}" { + let item_node = node.child(child_count - 2).unwrap(); + + Some(Item::from_syntax_node(source, item_node)?) + } else { + None + }; + + let expression_node = if item.is_some() { + node.child(child_count - 4).unwrap() + } else { + node.child(child_count - 1).unwrap() + }; + + let expression = Expression::from_syntax_node(source, expression_node)?; + + Ok(Select { + identifiers, + expression, + item, + }) + } + + fn run(&self, source: &str, context: &mut crate::VariableMap) -> crate::Result { + let value = self.expression.run(source, context)?; + let table = value.as_table()?; + let column_names = if self.identifiers.len() > 0 { + self.identifiers + .iter() + .cloned() + .map(|identifierier| identifierier.take_inner()) + .collect() + } else { + table.column_names().clone() + }; + let new_table = table.select(&column_names); + + Ok(Value::Table(new_table)) + } +} diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index c1c6ce0..e281fad 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -3,7 +3,7 @@ use tree_sitter::Node; use crate::{ AbstractTree, Assignment, Async, Error, Expression, Filter, Find, For, IfElse, Match, Remove, - Result, Transform, Value, VariableMap, While, + Result, Select, Transform, Value, VariableMap, While, }; /// Abstract representation of a statement. @@ -23,6 +23,7 @@ pub enum Statement { Filter(Box), Find(Box), Remove(Box), + Select(Box