From 0d549b1c36797e3f42343c38aeb4b8fb6a874bc9 Mon Sep 17 00:00:00 2001 From: Ben Weinstein-Raun Date: Fri, 2 Jun 2023 18:56:04 -0700 Subject: [PATCH 1/5] add mutable iteration over identifiers --- src/tree/iter.rs | 49 +++++++++++++++- src/tree/mod.rs | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 2 deletions(-) diff --git a/src/tree/iter.rs b/src/tree/iter.rs index acf64f7..931f42e 100644 --- a/src/tree/iter.rs +++ b/src/tree/iter.rs @@ -1,5 +1,5 @@ -use crate::Node; -use std::slice::Iter; +use crate::{Node, operator::Operator}; +use std::slice::{Iter, IterMut}; /// An iterator that traverses an operator tree in pre-order. pub struct NodeIter<'a> { @@ -41,9 +41,54 @@ impl<'a> Iterator for NodeIter<'a> { } } +pub struct NodeIterMut<'a> { + stack: Vec>, +} + +impl<'a> NodeIterMut<'a> { + fn new(node: &'a mut Node) -> Self { + NodeIterMut { + stack: vec![node.children.iter_mut()] + } + } +} + +impl<'a> Iterator for NodeIterMut<'a> { + type Item = &'a mut Operator; + + fn next(&mut self) -> Option { + loop { + let mut result = None; + + if let Some(last) = self.stack.last_mut() { + if let Some(next) = last.next() { + result = Some(next); + } else { + // Can not fail because we just borrowed last. + // We just checked that the iterator is empty, so we can safely discard it. + let _ = self.stack.pop().unwrap(); + } + } else { + return None; + } + + if let Some(result) = result { + self.stack.push(result.children.iter_mut()); + return Some(&mut result.operator); + } + } + } +} + impl Node { /// Returns an iterator over all nodes in this tree. pub fn iter(&self) -> impl Iterator { NodeIter::new(self) } + + /// Returns a mutable iterator over all operators in this tree. + pub fn iter_operator_mut(&mut self) -> impl Iterator { + NodeIterMut::new(self) + } } + diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 347f787..35a3f96 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -76,6 +76,36 @@ impl Node { }) } + /// Returns an iterator over all identifiers in this expression, allowing mutation. + /// Each occurrence of an identifier is returned separately. + /// # Examples + /// + /// ```rust + /// use evalexpr::*; + /// + /// let mut tree = build_operator_tree("a + b + c * f()").unwrap(); // Do proper error handling here + /// + /// for identifier in tree.iter_identifiers_mut() { + /// *identifier = String::from("x"); + /// } + /// + /// let mut iter = tree.iter_identifiers(); + /// + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter_identifiers_mut(&mut self) -> impl Iterator { + self.iter_operator_mut().filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } + | Operator::VariableIdentifierRead { identifier } + | Operator::FunctionIdentifier { identifier } => Some(identifier), + _ => None + }) + } + /// Returns an iterator over all variable identifiers in this expression. /// Each occurrence of a variable identifier is returned separately. /// @@ -99,6 +129,36 @@ impl Node { }) } + /// Returns an iterator over all variable identifiers in this expression, allowing mutation. + /// Each occurrence of a variable identifier is returned separately. + /// + /// # Examples + /// + /// ```rust + /// use evalexpr::*; + /// + /// let mut tree = build_operator_tree("a + b + c * f()").unwrap(); // Do proper error handling here + /// + /// for identifier in tree.iter_variable_identifiers_mut() { + /// *identifier = String::from("x"); + /// } + /// + /// let mut iter = tree.iter_identifiers(); + /// + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("f")); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter_variable_identifiers_mut(&mut self) -> impl Iterator { + self.iter_operator_mut().filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } + | Operator::VariableIdentifierRead { identifier } => Some(identifier), + _ => None, + }) + } + /// Returns an iterator over all read variable identifiers in this expression. /// Each occurrence of a variable identifier is returned separately. /// @@ -121,6 +181,36 @@ impl Node { }) } + /// Returns an iterator over all read variable identifiers in this expression, allowing mutation. + /// Each occurrence of a variable identifier is returned separately. + /// + /// # Examples + /// + /// ```rust + /// use evalexpr::*; + /// + /// let mut tree = build_operator_tree("d = a + f(b + c)").unwrap(); // Do proper error handling here + /// + /// for identifier in tree.iter_read_variable_identifiers_mut() { + /// *identifier = String::from("x"); + /// } + /// + /// let mut iter = tree.iter_identifiers(); + /// + /// assert_eq!(iter.next(), Some("d")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("f")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter_read_variable_identifiers_mut(&mut self) -> impl Iterator { + self.iter_operator_mut().filter_map(|operator| match operator { + Operator::VariableIdentifierRead { identifier } => Some(identifier), + _ => None, + }) + } + /// Returns an iterator over all write variable identifiers in this expression. /// Each occurrence of a variable identifier is returned separately. /// @@ -141,6 +231,36 @@ impl Node { }) } + /// Returns an iterator over all write variable identifiers in this expression, allowing mutation. + /// Each occurrence of a variable identifier is returned separately. + /// + /// # Examples + /// + /// ```rust + /// use evalexpr::*; + /// + /// let mut tree = build_operator_tree("d = a + f(b + c)").unwrap(); // Do proper error handling here + /// + /// for identifier in tree.iter_write_variable_identifiers_mut() { + /// *identifier = String::from("x"); + /// } + /// + /// let mut iter = tree.iter_identifiers(); + /// + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("a")); + /// assert_eq!(iter.next(), Some("f")); + /// assert_eq!(iter.next(), Some("b")); + /// assert_eq!(iter.next(), Some("c")); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter_write_variable_identifiers_mut(&mut self) -> impl Iterator { + self.iter_operator_mut().filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } => Some(identifier), + _ => None, + }) + } + /// Returns an iterator over all function identifiers in this expression. /// Each occurrence of a function identifier is returned separately. /// @@ -161,6 +281,36 @@ impl Node { }) } + /// Returns an iterator over all function identifiers in this expression, allowing mutation. + /// Each occurrence of a variable identifier is returned separately. + /// + /// # Examples + /// + /// ```rust + /// use evalexpr::*; + /// + /// let mut tree = build_operator_tree("d = a + f(b + c)").unwrap(); // Do proper error handling here + /// + /// for identifier in tree.iter_function_variable_identifiers_mut() { + /// *identifier = String::from("x"); + /// } + /// + /// let mut iter = tree.iter_identifiers(); + /// + /// assert_eq!(iter.next(), Some("d")); + /// assert_eq!(iter.next(), Some("a")); + /// assert_eq!(iter.next(), Some("x")); + /// assert_eq!(iter.next(), Some("b")); + /// assert_eq!(iter.next(), Some("c")); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter_function_variable_identifiers_mut(&mut self) -> impl Iterator { + self.iter_operator_mut().filter_map(|operator| match operator { + Operator::FunctionIdentifier { identifier } => Some(identifier), + _ => None, + }) + } + /// Evaluates the operator tree rooted at this node with the given context. /// /// Fails, if one of the operators in the expression tree fails. From d45cb7c42018e5b44bccc14459af842403332fcd Mon Sep 17 00:00:00 2001 From: Ben Weinstein-Raun Date: Fri, 2 Jun 2023 18:59:56 -0700 Subject: [PATCH 2/5] rename iterators to indicate that they're iterating over operators rather than nodes --- src/tree/iter.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tree/iter.rs b/src/tree/iter.rs index 931f42e..abae1ad 100644 --- a/src/tree/iter.rs +++ b/src/tree/iter.rs @@ -41,19 +41,20 @@ impl<'a> Iterator for NodeIter<'a> { } } -pub struct NodeIterMut<'a> { +/// An iterator that mutably traverses an operator tree in pre-order. +pub struct OperatorIterMut<'a> { stack: Vec>, } -impl<'a> NodeIterMut<'a> { +impl<'a> OperatorIterMut<'a> { fn new(node: &'a mut Node) -> Self { - NodeIterMut { + OperatorIterMut { stack: vec![node.children.iter_mut()] } } } -impl<'a> Iterator for NodeIterMut<'a> { +impl<'a> Iterator for OperatorIterMut<'a> { type Item = &'a mut Operator; fn next(&mut self) -> Option { @@ -88,7 +89,7 @@ impl Node { /// Returns a mutable iterator over all operators in this tree. pub fn iter_operator_mut(&mut self) -> impl Iterator { - NodeIterMut::new(self) + OperatorIterMut::new(self) } } From 1646a070a90f115d2b7aa91dc9edb20f95b1ac49 Mon Sep 17 00:00:00 2001 From: Ben Weinstein-Raun Date: Fri, 2 Jun 2023 19:00:42 -0700 Subject: [PATCH 3/5] cargo format --- src/tree/iter.rs | 5 ++--- src/tree/mod.rs | 51 ++++++++++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/tree/iter.rs b/src/tree/iter.rs index abae1ad..d812001 100644 --- a/src/tree/iter.rs +++ b/src/tree/iter.rs @@ -1,4 +1,4 @@ -use crate::{Node, operator::Operator}; +use crate::{operator::Operator, Node}; use std::slice::{Iter, IterMut}; /// An iterator that traverses an operator tree in pre-order. @@ -49,7 +49,7 @@ pub struct OperatorIterMut<'a> { impl<'a> OperatorIterMut<'a> { fn new(node: &'a mut Node) -> Self { OperatorIterMut { - stack: vec![node.children.iter_mut()] + stack: vec![node.children.iter_mut()], } } } @@ -92,4 +92,3 @@ impl Node { OperatorIterMut::new(self) } } - diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 35a3f96..5580031 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -98,12 +98,13 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut().filter_map(|operator| match operator { - Operator::VariableIdentifierWrite { identifier } - | Operator::VariableIdentifierRead { identifier } - | Operator::FunctionIdentifier { identifier } => Some(identifier), - _ => None - }) + self.iter_operator_mut() + .filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } + | Operator::VariableIdentifierRead { identifier } + | Operator::FunctionIdentifier { identifier } => Some(identifier), + _ => None, + }) } /// Returns an iterator over all variable identifiers in this expression. @@ -152,11 +153,12 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut().filter_map(|operator| match operator { - Operator::VariableIdentifierWrite { identifier } - | Operator::VariableIdentifierRead { identifier } => Some(identifier), - _ => None, - }) + self.iter_operator_mut() + .filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } + | Operator::VariableIdentifierRead { identifier } => Some(identifier), + _ => None, + }) } /// Returns an iterator over all read variable identifiers in this expression. @@ -205,10 +207,11 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_read_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut().filter_map(|operator| match operator { - Operator::VariableIdentifierRead { identifier } => Some(identifier), - _ => None, - }) + self.iter_operator_mut() + .filter_map(|operator| match operator { + Operator::VariableIdentifierRead { identifier } => Some(identifier), + _ => None, + }) } /// Returns an iterator over all write variable identifiers in this expression. @@ -255,10 +258,11 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_write_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut().filter_map(|operator| match operator { - Operator::VariableIdentifierWrite { identifier } => Some(identifier), - _ => None, - }) + self.iter_operator_mut() + .filter_map(|operator| match operator { + Operator::VariableIdentifierWrite { identifier } => Some(identifier), + _ => None, + }) } /// Returns an iterator over all function identifiers in this expression. @@ -305,10 +309,11 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_function_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut().filter_map(|operator| match operator { - Operator::FunctionIdentifier { identifier } => Some(identifier), - _ => None, - }) + self.iter_operator_mut() + .filter_map(|operator| match operator { + Operator::FunctionIdentifier { identifier } => Some(identifier), + _ => None, + }) } /// Evaluates the operator tree rooted at this node with the given context. From 49b61ff359b8f139f1ec57026cada1d3b3902985 Mon Sep 17 00:00:00 2001 From: Ben Weinstein-Raun Date: Sun, 4 Jun 2023 14:16:02 -0700 Subject: [PATCH 4/5] rename to iter_operators_mut --- src/tree/iter.rs | 2 +- src/tree/mod.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tree/iter.rs b/src/tree/iter.rs index d812001..0524361 100644 --- a/src/tree/iter.rs +++ b/src/tree/iter.rs @@ -88,7 +88,7 @@ impl Node { } /// Returns a mutable iterator over all operators in this tree. - pub fn iter_operator_mut(&mut self) -> impl Iterator { + pub fn iter_operators_mut(&mut self) -> impl Iterator { OperatorIterMut::new(self) } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 5580031..288f62f 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -98,7 +98,7 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut() + self.iter_operators_mut() .filter_map(|operator| match operator { Operator::VariableIdentifierWrite { identifier } | Operator::VariableIdentifierRead { identifier } @@ -153,7 +153,7 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut() + self.iter_operators_mut() .filter_map(|operator| match operator { Operator::VariableIdentifierWrite { identifier } | Operator::VariableIdentifierRead { identifier } => Some(identifier), @@ -207,7 +207,7 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_read_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut() + self.iter_operators_mut() .filter_map(|operator| match operator { Operator::VariableIdentifierRead { identifier } => Some(identifier), _ => None, @@ -258,7 +258,7 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_write_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut() + self.iter_operators_mut() .filter_map(|operator| match operator { Operator::VariableIdentifierWrite { identifier } => Some(identifier), _ => None, @@ -309,7 +309,7 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_function_variable_identifiers_mut(&mut self) -> impl Iterator { - self.iter_operator_mut() + self.iter_operators_mut() .filter_map(|operator| match operator { Operator::FunctionIdentifier { identifier } => Some(identifier), _ => None, From 2fdd4a16047729c5711fbbe2bb1b466be3fba04a Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Thu, 8 Jun 2023 15:40:30 +0300 Subject: [PATCH 5/5] Fix some names an docs. --- src/tree/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 288f62f..e835fd3 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -78,6 +78,7 @@ impl Node { /// Returns an iterator over all identifiers in this expression, allowing mutation. /// Each occurrence of an identifier is returned separately. + /// /// # Examples /// /// ```rust @@ -295,7 +296,7 @@ impl Node { /// /// let mut tree = build_operator_tree("d = a + f(b + c)").unwrap(); // Do proper error handling here /// - /// for identifier in tree.iter_function_variable_identifiers_mut() { + /// for identifier in tree.iter_function_identifiers_mut() { /// *identifier = String::from("x"); /// } /// @@ -308,7 +309,7 @@ impl Node { /// assert_eq!(iter.next(), Some("c")); /// assert_eq!(iter.next(), None); /// ``` - pub fn iter_function_variable_identifiers_mut(&mut self) -> impl Iterator { + pub fn iter_function_identifiers_mut(&mut self) -> impl Iterator { self.iter_operators_mut() .filter_map(|operator| match operator { Operator::FunctionIdentifier { identifier } => Some(identifier),