Skip to content

Commit eba8b28

Browse files
authored
Rename accesses to annotations (#3803)
Signed-off-by: Nicholas Gates <[email protected]>
1 parent 427d26e commit eba8b28

File tree

9 files changed

+439
-449
lines changed

9 files changed

+439
-449
lines changed

vortex-expr/src/transform/access_analysis.rs

Lines changed: 0 additions & 81 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::hash::Hash;
5+
6+
use vortex_error::{VortexExpect, VortexResult};
7+
use vortex_utils::aliases::hash_map::HashMap;
8+
use vortex_utils::aliases::hash_set::HashSet;
9+
10+
use crate::traversal::{Node, NodeVisitor, TraversalOrder};
11+
use crate::{ExprRef, Identifier, VarVTable};
12+
13+
pub trait Annotation: Clone + Hash + Eq {}
14+
15+
impl<A> Annotation for A where A: Clone + Hash + Eq {}
16+
17+
pub trait AnnotationFn: Fn(&ExprRef) -> Vec<Self::Annotation> {
18+
type Annotation: Annotation;
19+
}
20+
21+
impl<A, F> AnnotationFn for F
22+
where
23+
A: Annotation,
24+
F: Fn(&ExprRef) -> Vec<A>,
25+
{
26+
type Annotation = A;
27+
}
28+
29+
pub type Annotations<'a, A> = HashMap<&'a ExprRef, HashSet<A>>;
30+
31+
/// Walk the expression tree and annotate each expression with zero or more annotations.
32+
///
33+
/// Returns a map of each expression to all annotations that any of its descendent (child)
34+
/// expressions are annotated with.
35+
pub fn descendent_annotations<A: AnnotationFn>(
36+
expr: &ExprRef,
37+
annotate: A,
38+
) -> Annotations<A::Annotation> {
39+
let mut visitor = AnnotationVisitor {
40+
annotations: Default::default(),
41+
annotate,
42+
};
43+
expr.accept(&mut visitor).vortex_expect("Infallible");
44+
visitor.annotations
45+
}
46+
47+
pub fn variable_scope_annotations<A: Annotation>(
48+
expr: &ExprRef,
49+
f: impl Fn(&Identifier) -> A,
50+
) -> Annotations<A> {
51+
descendent_annotations(expr, move |node| {
52+
if let Some(variable) = node.as_opt::<VarVTable>() {
53+
return vec![f(variable.var())];
54+
}
55+
vec![]
56+
})
57+
}
58+
59+
struct AnnotationVisitor<'a, A: AnnotationFn> {
60+
annotations: Annotations<'a, A::Annotation>,
61+
annotate: A,
62+
}
63+
64+
impl<'a, A: AnnotationFn> NodeVisitor<'a> for AnnotationVisitor<'a, A> {
65+
type NodeTy = ExprRef;
66+
67+
fn visit_down(&mut self, node: &'a Self::NodeTy) -> VortexResult<TraversalOrder> {
68+
let annotations = (self.annotate)(node);
69+
if annotations.is_empty() {
70+
// If the annotate fn returns empty, we do not annotate this node.
71+
Ok(TraversalOrder::Continue)
72+
} else {
73+
self.annotations
74+
.entry(node)
75+
.or_default()
76+
.extend(annotations);
77+
Ok(TraversalOrder::Skip)
78+
}
79+
}
80+
81+
fn visit_up(&mut self, node: &'a ExprRef) -> VortexResult<TraversalOrder> {
82+
let child_annotations = node
83+
.children()
84+
.iter()
85+
.filter_map(|c| self.annotations.get(c).cloned())
86+
.collect::<Vec<_>>();
87+
88+
let annotations = self.annotations.entry(node).or_default();
89+
child_annotations
90+
.into_iter()
91+
.for_each(|ps| annotations.extend(ps.iter().cloned()));
92+
93+
Ok(TraversalOrder::Continue)
94+
}
95+
}

vortex-expr/src/transform/immediate_access.rs

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,33 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use vortex_dtype::{FieldName, StructFields};
5-
use vortex_error::{VortexResult, vortex_err};
6-
use vortex_utils::aliases::hash_map::HashMap;
5+
use vortex_error::VortexExpect;
76
use vortex_utils::aliases::hash_set::HashSet;
87

9-
use crate::transform::access_analysis::AccessesAnalysis;
10-
use crate::traversal::TraversalOrder;
8+
use crate::transform::annotations::{AnnotationFn, Annotations, descendent_annotations};
119
use crate::{ExprRef, GetItemVTable, SelectVTable, is_root};
1210

13-
pub type FieldAccesses<'a> = HashMap<&'a ExprRef, HashSet<FieldName>>;
11+
pub type FieldAccesses<'a> = Annotations<'a, FieldName>;
12+
13+
/// An [`AnnotationFn`] for annotating scope accesses.
14+
pub fn annotate_scope_access(scope: &StructFields) -> impl AnnotationFn<Annotation = FieldName> {
15+
move |expr: &ExprRef| {
16+
assert!(
17+
!expr.is::<SelectVTable>(),
18+
"cannot analyse select, simplify the expression"
19+
);
20+
21+
if let Some(get_item) = expr.as_opt::<GetItemVTable>() {
22+
if is_root(get_item.child()) {
23+
return vec![get_item.field().clone()];
24+
}
25+
} else if is_root(expr) {
26+
return scope.names().iter().cloned().collect();
27+
}
28+
29+
vec![]
30+
}
31+
}
1432

1533
/// For all subexpressions in an expression, find the fields that are accessed directly from the
1634
/// scope, but not any fields in those fields
@@ -21,38 +39,18 @@ pub type FieldAccesses<'a> = HashMap<&'a ExprRef, HashSet<FieldName>>;
2139
/// by an expression.
2240
pub fn immediate_scope_accesses<'a>(
2341
expr: &'a ExprRef,
24-
scope_dtype: &'a StructFields,
25-
) -> VortexResult<FieldAccesses<'a>> {
26-
AccessesAnalysis::analyze(expr, move |node| {
27-
assert!(
28-
!node.is::<SelectVTable>(),
29-
"cannot analyse select, simplify the expression"
30-
);
31-
if let Some(get_item) = node.as_opt::<GetItemVTable>() {
32-
if is_root(get_item.child()) {
33-
return (TraversalOrder::Skip, vec![get_item.field().clone()]);
34-
}
35-
} else if is_root(node) {
36-
let st_dtype = &scope_dtype;
37-
return (
38-
TraversalOrder::Skip,
39-
st_dtype.names().iter().cloned().collect(),
40-
);
41-
}
42-
43-
(TraversalOrder::Continue, vec![])
44-
})
42+
scope: &'a StructFields,
43+
) -> FieldAccesses<'a> {
44+
descendent_annotations(expr, annotate_scope_access(scope))
4545
}
4646

4747
/// This returns the immediate scope_access (as explained `immediate_scope_accesses`) for `expr`.
4848
pub fn immediate_scope_access<'a>(
4949
expr: &'a ExprRef,
50-
scope_dtype: &'a StructFields,
51-
) -> VortexResult<HashSet<FieldName>> {
52-
immediate_scope_accesses(expr, scope_dtype)?
50+
scope: &'a StructFields,
51+
) -> HashSet<FieldName> {
52+
immediate_scope_accesses(expr, scope)
5353
.get(expr)
54-
.ok_or_else(|| {
55-
vortex_err!("Expression missing from scope accesses, this is a internal bug")
56-
})
57-
.cloned()
54+
.vortex_expect("Expression missing from scope accesses, this is a internal bug")
55+
.clone()
5856
}

vortex-expr/src/transform/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
//! A collection of transformations that can be applied to a [`crate::ExprRef`].
5-
mod access_analysis;
5+
pub mod annotations;
66
pub mod field_mask;
77
pub mod immediate_access;
88
pub(crate) mod match_between;

0 commit comments

Comments
 (0)