vortex_array/expr/analysis/
annotation.rs1use std::hash::Hash;
5
6use vortex_error::VortexExpect;
7use vortex_error::VortexResult;
8use vortex_utils::aliases::hash_map::HashMap;
9use vortex_utils::aliases::hash_set::HashSet;
10
11use crate::expr::BoundExpression;
12use crate::expr::ExactBoundExpr;
13use crate::expr::Expression;
14use crate::expr::traversal::Node;
15use crate::expr::traversal::NodeExt;
16use crate::expr::traversal::NodeVisitor;
17use crate::expr::traversal::TraversalOrder;
18
19pub trait Annotation: Clone + Hash + Eq {}
20
21impl<A> Annotation for A where A: Clone + Hash + Eq {}
22
23pub trait AnnotationFn<N = Expression>: Fn(&N) -> Vec<Self::Annotation> {
24 type Annotation: Annotation;
25}
26
27impl<N, A, F> AnnotationFn<N> for F
28where
29 A: Annotation,
30 F: Fn(&N) -> Vec<A>,
31{
32 type Annotation = A;
33}
34
35pub type Annotations<'a, A, N = Expression> = HashMap<&'a N, HashSet<A>>;
36
37pub type BoundAnnotations<A> = HashMap<ExactBoundExpr, HashSet<A>>;
42
43pub fn descendent_annotations<'a, N, A>(
48 expr: &'a N,
49 annotate: A,
50) -> Annotations<'a, A::Annotation, N>
51where
52 N: Node + Eq + Hash,
53 A: AnnotationFn<N>,
54{
55 let mut visitor = AnnotationVisitor {
56 annotations: Default::default(),
57 annotate,
58 propagate_up: true,
59 };
60 expr.accept(&mut visitor).vortex_expect("Infallible");
61 visitor.annotations
62}
63
64pub fn direct_annotations<'a, N, A>(expr: &'a N, annotate: A) -> Annotations<'a, A::Annotation, N>
70where
71 N: Node + Eq + Hash,
72 A: AnnotationFn<N>,
73{
74 let mut visitor = AnnotationVisitor {
75 annotations: Default::default(),
76 annotate,
77 propagate_up: false,
78 };
79 expr.accept(&mut visitor).vortex_expect("Infallible");
80 visitor.annotations
81}
82
83pub fn descendent_bound_annotations<A>(
88 expr: &BoundExpression,
89 annotate: A,
90) -> BoundAnnotations<A::Annotation>
91where
92 A: AnnotationFn<BoundExpression>,
93{
94 bound_annotations(expr, annotate, true)
95}
96
97pub fn direct_bound_annotations<A>(
101 expr: &BoundExpression,
102 annotate: A,
103) -> BoundAnnotations<A::Annotation>
104where
105 A: AnnotationFn<BoundExpression>,
106{
107 bound_annotations(expr, annotate, false)
108}
109
110fn bound_annotations<A>(
111 expr: &BoundExpression,
112 annotate: A,
113 propagate_up: bool,
114) -> BoundAnnotations<A::Annotation>
115where
116 A: AnnotationFn<BoundExpression>,
117{
118 let mut visitor = BoundAnnotationVisitor {
119 annotations: Default::default(),
120 annotate,
121 propagate_up,
122 };
123 expr.accept(&mut visitor).vortex_expect("Infallible");
124 visitor.annotations
125}
126
127struct AnnotationVisitor<'a, N, A>
128where
129 N: Node + Eq + Hash,
130 A: AnnotationFn<N>,
131{
132 annotations: Annotations<'a, A::Annotation, N>,
133 annotate: A,
134 propagate_up: bool,
135}
136
137impl<'a, N, A> NodeVisitor<'a> for AnnotationVisitor<'a, N, A>
138where
139 N: Node + Eq + Hash,
140 A: AnnotationFn<N>,
141{
142 type NodeTy = N;
143
144 fn visit_down(&mut self, node: &'a Self::NodeTy) -> VortexResult<TraversalOrder> {
145 let annotations = (self.annotate)(node);
146 if annotations.is_empty() {
147 Ok(TraversalOrder::Continue)
149 } else {
150 self.annotations
151 .entry(node)
152 .or_default()
153 .extend(annotations);
154 Ok(TraversalOrder::Skip)
155 }
156 }
157
158 fn visit_up(&mut self, node: &'a N) -> VortexResult<TraversalOrder> {
159 if !self.propagate_up {
160 return Ok(TraversalOrder::Continue);
161 }
162 let child_annotations = node.iter_children(|children| {
163 children
164 .filter_map(|child| self.annotations.get(child).cloned())
165 .collect::<Vec<_>>()
166 });
167
168 let annotations = self.annotations.entry(node).or_default();
169 child_annotations
170 .into_iter()
171 .for_each(|ps| annotations.extend(ps.iter().cloned()));
172
173 Ok(TraversalOrder::Continue)
174 }
175}
176
177struct BoundAnnotationVisitor<A>
178where
179 A: AnnotationFn<BoundExpression>,
180{
181 annotations: BoundAnnotations<A::Annotation>,
182 annotate: A,
183 propagate_up: bool,
184}
185
186impl<'a, A> NodeVisitor<'a> for BoundAnnotationVisitor<A>
187where
188 A: AnnotationFn<BoundExpression>,
189{
190 type NodeTy = BoundExpression;
191
192 fn visit_down(&mut self, node: &'a Self::NodeTy) -> VortexResult<TraversalOrder> {
193 let annotations = (self.annotate)(node);
194 if annotations.is_empty() {
195 return Ok(TraversalOrder::Continue);
196 }
197
198 self.annotations
199 .entry(ExactBoundExpr(node.clone()))
200 .or_default()
201 .extend(annotations);
202 Ok(TraversalOrder::Skip)
203 }
204
205 fn visit_up(&mut self, node: &'a Self::NodeTy) -> VortexResult<TraversalOrder> {
206 if !self.propagate_up {
207 return Ok(TraversalOrder::Continue);
208 }
209
210 let child_annotations = node
211 .children()
212 .iter()
213 .filter_map(|child| {
214 self.annotations
215 .get(&ExactBoundExpr(child.clone()))
216 .cloned()
217 })
218 .collect::<Vec<_>>();
219 let annotations = self
220 .annotations
221 .entry(ExactBoundExpr(node.clone()))
222 .or_default();
223 child_annotations
224 .into_iter()
225 .for_each(|child| annotations.extend(child));
226
227 Ok(TraversalOrder::Continue)
228 }
229}