From 2b882f11370d2049e5ec25a26343014b66f17438 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 17 Oct 2023 16:40:07 -0400 Subject: [PATCH] Implement transform loop --- examples/transform_loop.ds | 8 ++++++ src/abstract_tree/mod.rs | 3 ++- src/abstract_tree/statement.rs | 11 +++++--- src/abstract_tree/transform.rs | 47 ++++++++++++++++++++++++++++++++++ tree-sitter-dust | 2 +- 5 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 examples/transform_loop.ds create mode 100644 src/abstract_tree/transform.rs diff --git a/examples/transform_loop.ds b/examples/transform_loop.ds new file mode 100644 index 0000000..5f300d2 --- /dev/null +++ b/examples/transform_loop.ds @@ -0,0 +1,8 @@ +list = [1 2 3] + +new_list = transform i in list { + i + 1 +} + +(assert_equal [2 3 4] new_list) + diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 2c6a493..1b4e5f6 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -19,12 +19,13 @@ pub mod r#match; pub mod math; pub mod statement; pub mod tool; +pub mod transform; pub mod value_node; pub mod r#while; pub use { assignment::*, expression::*, function_call::*, identifier::*, if_else::*, item::*, logic::*, - math::*, r#async::*, r#for::*, r#match::*, r#while::*, statement::*, + 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 53068e6..8546ab0 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Assignment, Async, Error, Expression, For, IfElse, Match, Result, Value, - VariableMap, While, + AbstractTree, Assignment, Async, Error, Expression, For, IfElse, Match, Result, Transform, + Value, VariableMap, While, }; /// Abstract representation of a statement. @@ -19,6 +19,7 @@ pub enum Statement { While(Box), Async(Box), For(Box), + Transform(Box), } impl AbstractTree for Statement { @@ -49,8 +50,11 @@ impl AbstractTree for Statement { "for" => Ok(Statement::For(Box::new(For::from_syntax_node( source, child, )?))), + "transform" => Ok(Statement::Transform(Box::new(Transform::from_syntax_node( + source, child, + )?))), _ => Err(Error::UnexpectedSyntaxNode { - expected: "assignment, expression, if...else, while, tool or async", + expected: "assignment, expression, if...else, while, for, transform, tool or async", actual: child.kind(), location: child.start_position(), relevant_source: source[child.byte_range()].to_string(), @@ -67,6 +71,7 @@ impl AbstractTree for Statement { Statement::While(r#while) => r#while.run(source, context), Statement::Async(run) => run.run(source, context), Statement::For(r#for) => r#for.run(source, context), + Statement::Transform(transform) => transform.run(source, context), } } } diff --git a/src/abstract_tree/transform.rs b/src/abstract_tree/transform.rs new file mode 100644 index 0000000..9e982bd --- /dev/null +++ b/src/abstract_tree/transform.rs @@ -0,0 +1,47 @@ +use serde::{Deserialize, Serialize}; + +use crate::{AbstractTree, Expression, Identifier, Item, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub struct Transform { + identifier: Identifier, + expression: Expression, + item: Item, +} + +impl AbstractTree for Transform { + 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(Transform { + 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(); + let mut new_list = Vec::with_capacity(list.len()); + + for value in list { + context.set_value(key.clone(), value.clone())?; + + let value = self.item.run(source, &mut context)?; + + new_list.push(value); + } + + Ok(Value::List(new_list)) + } +} diff --git a/tree-sitter-dust b/tree-sitter-dust index 9fb89fc..6aab8e8 160000 --- a/tree-sitter-dust +++ b/tree-sitter-dust @@ -1 +1 @@ -Subproject commit 9fb89fcd8b29386735de0bad42232ef3d72e7e91 +Subproject commit 6aab8e8f65a29ada418b09c5cdae0583c37b7b23