use vortex_error::VortexExpect;
use vortex_utils::aliases::hash_set::HashSet;
use crate::dtype::FieldName;
use crate::dtype::StructFields;
use crate::expr::Expression;
use crate::expr::analysis::AnnotationFn;
use crate::expr::analysis::Annotations;
use crate::expr::descendent_annotations;
use crate::scalar_fn::fns::get_item::GetItem;
use crate::scalar_fn::fns::root::Root;
use crate::scalar_fn::fns::select::Select;
pub type FieldAccesses<'a> = Annotations<'a, FieldName>;
pub fn make_free_field_annotator(
scope: &StructFields,
) -> impl AnnotationFn<Annotation = FieldName> {
move |expr: &Expression| {
if let Some(selection) = expr.as_opt::<Select>() {
if expr.child(0).is::<Root>() {
return selection
.normalize_to_included_fields(scope.names())
.vortex_expect("Select fields must be valid for scope")
.into_iter()
.collect();
}
} else if let Some(field_name) = expr.as_opt::<GetItem>() {
if expr.child(0).is::<Root>() {
return vec![field_name.clone()];
}
} else if expr.is::<Root>() {
return scope.names().iter().cloned().collect();
}
vec![]
}
}
pub fn immediate_scope_accesses<'a>(
expr: &'a Expression,
scope: &'a StructFields,
) -> FieldAccesses<'a> {
descendent_annotations(expr, make_free_field_annotator(scope))
}
pub fn immediate_scope_access<'a>(
expr: &'a Expression,
scope: &'a StructFields,
) -> HashSet<FieldName> {
immediate_scope_accesses(expr, scope)
.get(expr)
.vortex_expect("Expression missing from scope accesses, this is a internal bug")
.clone()
}