diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 4c71f34..6589bba 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -19,6 +19,8 @@ pub enum AssignmentOperator { impl AbstractTree for Assignment { fn from_syntax_node(source: &str, node: Node) -> Result { + Error::expect_syntax_node(source, "assignment", node)?; + let identifier_node = node.child(0).unwrap(); let identifier = Identifier::from_syntax_node(source, identifier_node)?; diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index c8c44b6..4093f5e 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -5,9 +5,9 @@ use crate::{AbstractTree, Error, Expression, List, Map, Result, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Index { - collection: Expression, - index: Expression, - index_end: Option, + pub collection: Expression, + pub index: Expression, + pub index_end: Option, } impl AbstractTree for Index { @@ -50,7 +50,7 @@ impl AbstractTree for Index { Ok(item) } - Value::Map(mut map) => { + Value::Map(map) => { let value = if let Expression::Identifier(identifier) = &self.index { let key = identifier.inner(); diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index be23bee..061c690 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -19,6 +19,8 @@ pub enum AssignmentOperator { impl AbstractTree for IndexAssignment { fn from_syntax_node(source: &str, node: Node) -> Result { + Error::expect_syntax_node(source, "index_assignment", node)?; + let index_node = node.child(0).unwrap(); let index = Index::from_syntax_node(source, index_node)?; @@ -48,14 +50,43 @@ impl AbstractTree for IndexAssignment { } fn run(&self, source: &str, context: &mut Map) -> Result { - let mut left = self.index.run(source, context)?; - let right = self.statement.run(source, context)?; + let index_collection = self.index.collection.run(source, context)?; + let index_context = index_collection.as_map().unwrap_or(&context); + let index_key = if let crate::Expression::Identifier(identifier) = &self.index.index { + identifier.inner() + } else { + return Err(Error::VariableIdentifierNotFound( + self.index.index.run(source, context)?.to_string(), + )); + }; - match self.operator { - AssignmentOperator::PlusEqual => left += right, - AssignmentOperator::MinusEqual => left -= right, - AssignmentOperator::Equal => left = right, - } + let value = self.statement.run(source, &mut context.clone())?; + + let new_value = match self.operator { + AssignmentOperator::PlusEqual => { + if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned() + { + previous_value += value; + previous_value + } else { + Value::Empty + } + } + AssignmentOperator::MinusEqual => { + if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned() + { + previous_value -= value; + previous_value + } else { + Value::Empty + } + } + AssignmentOperator::Equal => value, + }; + + context + .variables_mut()? + .insert(index_key.clone(), new_value); Ok(Value::Empty) } diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 213e53d..5efc724 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -17,6 +17,7 @@ pub mod function_call; pub mod identifier; pub mod if_else; pub mod index; +pub mod index_assignment; pub mod insert; pub mod logic; pub mod r#match; @@ -30,8 +31,9 @@ pub mod r#while; pub use { assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*, - function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*, r#for::*, - r#match::*, r#while::*, remove::*, select::*, statement::*, transform::*, value_node::*, + function_call::*, identifier::*, if_else::*, index::*, index_assignment::*, insert::*, + logic::*, math::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*, + transform::*, value_node::*, }; use tree_sitter::Node; diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index 6baf6c7..8821950 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, Block, Error, Expression, Filter, Find, For, IfElse, Insert, Map, - Match, Remove, Result, Select, Transform, Value, While, + AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, IndexAssignment, + Insert, Map, Match, Remove, Result, Select, Transform, Value, While, }; /// Abstract representation of a statement. @@ -25,12 +25,11 @@ pub enum Statement { Remove(Box), Select(Box