From 13289e5a59ea9a2a977976eed3e7f1574aa709ca Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 18 Oct 2023 18:26:45 -0400 Subject: [PATCH] Implement find loop logic --- examples/find_loop.ds | 7 +++++ src/abstract_tree/find.rs | 48 ++++++++++++++++++++++++++++++++++ src/abstract_tree/mod.rs | 6 +++-- src/abstract_tree/statement.rs | 7 ++++- src/lib.rs | 2 +- 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 examples/find_loop.ds create mode 100644 src/abstract_tree/find.rs diff --git a/examples/find_loop.ds b/examples/find_loop.ds new file mode 100644 index 0000000..f13733b --- /dev/null +++ b/examples/find_loop.ds @@ -0,0 +1,7 @@ +list = [1 2 1 3] + +found = find i in list { + i == 3 +} + +(assert_equal 3 found) diff --git a/src/abstract_tree/find.rs b/src/abstract_tree/find.rs new file mode 100644 index 0000000..5d7efca --- /dev/null +++ b/src/abstract_tree/find.rs @@ -0,0 +1,48 @@ +use serde::{Deserialize, Serialize}; + +use crate::{AbstractTree, Expression, Identifier, Item, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct Find { + identifier: Identifier, + expression: Expression, + item: Item, +} + +impl AbstractTree for Find { + fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result { + let identifier_node = node.child(1).unwrap(); + let identifier = Identifier::from_syntax_node(source, identifier_node)?; + + let expression_node = node.child(3).unwrap(); + let expression = Expression::from_syntax_node(source, expression_node)?; + + let item_node = node.child(5).unwrap(); + let item = Item::from_syntax_node(source, item_node)?; + + Ok(Find { + identifier, + expression, + item, + }) + } + + fn run(&self, source: &str, context: &mut crate::VariableMap) -> crate::Result { + let value = self.expression.run(source, context)?; + let list = value.as_list()?; + let key = self.identifier.inner(); + let mut context = context.clone(); + + for value in list { + context.set_value(key.clone(), value.clone())?; + + let should_return = self.item.run(source, &mut context)?.as_boolean()?; + + if should_return { + return Ok(value.clone()); + } + } + + Ok(Value::Empty) + } +} diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index fab6300..8d0d21c 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -10,6 +10,7 @@ pub mod assignment; pub mod r#async; pub mod expression; pub mod filter; +pub mod find; pub mod r#for; pub mod function_call; pub mod identifier; @@ -25,8 +26,9 @@ pub mod value_node; pub mod r#while; pub use { - assignment::*, expression::*, filter::*, function_call::*, identifier::*, if_else::*, item::*, - logic::*, math::*, r#async::*, r#for::*, r#match::*, r#while::*, statement::*, transform::*, + assignment::*, expression::*, filter::*, find::*, function_call::*, identifier::*, if_else::*, + item::*, logic::*, math::*, r#async::*, r#for::*, r#match::*, r#while::*, statement::*, + transform::*, }; use tree_sitter::Node; diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index b5065cb..e2c51ff 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Assignment, Async, Error, Expression, Filter, For, IfElse, Match, Result, + AbstractTree, Assignment, Async, Error, Expression, Filter, Find, For, IfElse, Match, Result, Transform, Value, VariableMap, While, }; @@ -21,6 +21,7 @@ pub enum Statement { For(Box), Transform(Box), Filter(Box), + Find(Box), } impl AbstractTree for Statement { @@ -57,6 +58,9 @@ impl AbstractTree for Statement { "filter" => Ok(Statement::Filter(Box::new(Filter::from_syntax_node( source, child, )?))), + "find" => Ok(Statement::Find(Box::new(Find::from_syntax_node( + source, child, + )?))), _ => Err(Error::UnexpectedSyntaxNode { expected: "assignment, expression, if...else, while, for, transform, filter, tool or async", actual: child.kind(), @@ -77,6 +81,7 @@ impl AbstractTree for Statement { Statement::For(r#for) => r#for.run(source, context), Statement::Transform(transform) => transform.run(source, context), Statement::Filter(filter) => filter.run(source, context), + Statement::Find(find) => find.run(source, context), } } } diff --git a/src/lib.rs b/src/lib.rs index 58ff61a..6cbb42d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub fn language() -> Language { /// The content of the [`node-types.json`][] file for this grammar. /// /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types -pub const NODE_TYPES: &'static str = include_str!("../../tree-sitter-dust/src/node-types.json"); +pub const NODE_TYPES: &'static str = include_str!("../tree-sitter-dust/src/node-types.json"); // Uncomment these to include any queries that this grammar contains