CSEVisitor

Struct CSEVisitor 

Source
struct CSEVisitor<'a, 'n, N, C>
where N: NormalizeEq, C: CSEController<Node = N>,
{ node_stats: &'a mut HashMap<Identifier<'n, N>, NodeEvaluation>, id_array: &'a mut Vec<(usize, Option<Identifier<'n, N>>)>, visit_stack: Vec<VisitRecord<'n, N>>, down_index: usize, up_index: usize, random_state: &'a RandomState, found_common: bool, conditional: bool, controller: &'a mut C, }
Expand description

Go through a TreeNode tree and generate identifiers for each subtrees.

An identifier contains information of the TreeNode itself and its subtrees. This visitor implementation use a stack visit_stack to track traversal, which lets us know when a subtree’s visiting is finished. When pre_visit is called (traversing to a new node), an EnterMark and an NodeItem will be pushed into stack. And try to pop out a EnterMark on leaving a node (f_up()). All NodeItem before the first EnterMark is considered to be sub-tree of the leaving node.

This visitor also records identifier in id_array. Makes the following traverse pass can get the identifier of a node without recalculate it. We assign each node in the tree a series number, start from 1, maintained by series_number. Series number represents the order we left (f_up()) a node. Has the property that child node’s series number always smaller than parent’s. While id_array is organized in the order we enter (f_down()) a node. node_count helps us to get the index of id_array for each node.

A TreeNode without any children (column, literal etc.) will not have identifier because they should not be recognized as common subtree.

Fields§

§node_stats: &'a mut HashMap<Identifier<'n, N>, NodeEvaluation>

statistics of TreeNodes

§id_array: &'a mut Vec<(usize, Option<Identifier<'n, N>>)>

cache to speed up second traversal

§visit_stack: Vec<VisitRecord<'n, N>>

inner states

§down_index: usize

preorder index, start from 0.

§up_index: usize

postorder index, start from 0.

§random_state: &'a RandomState

a RandomState to generate hashes during the first traversal

§found_common: bool

a flag to indicate that common TreeNodes found

§conditional: bool

if we are in a conditional branch. A conditional branch means that the TreeNode might not be executed depending on the runtime values of other TreeNodes, and thus can not be extracted as a common TreeNode.

§controller: &'a mut C

Implementations§

Source§

impl<'n, N, C> CSEVisitor<'_, 'n, N, C>
where N: TreeNode + HashNode + NormalizeEq, C: CSEController<Node = N>,

Source

fn pop_enter_mark( &mut self, can_normalize: bool, ) -> (usize, Option<Identifier<'n, N>>, bool)

Find the first EnterMark in the stack, and accumulates every NodeItem before it. Returns a tuple that contains:

  • The pre-order index of the TreeNode we marked.
  • The accumulated identifier of the children of the marked TreeNode.
  • An accumulated boolean flag from the children of the marked TreeNode if all children are valid for CSE (i.e. it is safe to extract the TreeNode as a common TreeNode from its children POV). (E.g. if any of the children of the marked expression is not valid (e.g. is volatile) then the expression is also not valid, so we can propagate this information up from children to parents via visit_stack during the first, visiting traversal and no need to test the expression’s validity beforehand with an extra traversal).

Trait Implementations§

Source§

impl<'n, N, C> TreeNodeVisitor<'n> for CSEVisitor<'_, 'n, N, C>
where N: TreeNode + HashNode + NormalizeEq, C: CSEController<Node = N>,

Source§

type Node = N

The node type which is visitable.
Source§

fn f_down(&mut self, node: &'n Self::Node) -> Result<TreeNodeRecursion>

Invoked while traversing down the tree, before any children are visited. Default implementation continues the recursion.
Source§

fn f_up(&mut self, node: &'n Self::Node) -> Result<TreeNodeRecursion>

Invoked while traversing up the tree after children are visited. Default implementation continues the recursion.

Auto Trait Implementations§

§

impl<'a, 'n, N, C> Freeze for CSEVisitor<'a, 'n, N, C>

§

impl<'a, 'n, N, C> RefUnwindSafe for CSEVisitor<'a, 'n, N, C>

§

impl<'a, 'n, N, C> Send for CSEVisitor<'a, 'n, N, C>
where C: Send, N: Sync,

§

impl<'a, 'n, N, C> Sync for CSEVisitor<'a, 'n, N, C>
where C: Sync, N: Sync,

§

impl<'a, 'n, N, C> Unpin for CSEVisitor<'a, 'n, N, C>

§

impl<'a, 'n, N, C> !UnwindSafe for CSEVisitor<'a, 'n, N, C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

§

impl<T> ErasedDestructor for T
where T: 'static,