use std::fmt::Display;
use std::ops::BitAnd;
use super::*;
use crate::plans::conversion::is_regex_projection;
use crate::plans::ir::tree_format::TreeFmtVisitor;
use crate::plans::visitor::{AexprNode, TreeWalker};
pub struct MetaNameSpace(pub(crate) Expr);
impl MetaNameSpace {
pub fn pop(self) -> PolarsResult<Vec<Expr>> {
let mut arena = Arena::with_capacity(8);
let node = to_aexpr(self.0, &mut arena)?;
let ae = arena.get(node);
let mut inputs = Vec::with_capacity(2);
ae.nodes(&mut inputs);
Ok(inputs
.iter()
.map(|node| node_to_expr(*node, &arena))
.collect())
}
pub fn root_names(&self) -> Vec<PlSmallStr> {
expr_to_leaf_column_names(&self.0)
}
pub fn is_simple_projection(&self) -> bool {
let mut arena = Arena::with_capacity(8);
to_aexpr(self.0.clone(), &mut arena)
.map(|node| aexpr_is_simple_projection(node, &arena))
.unwrap_or(false)
}
pub fn output_name(&self) -> PolarsResult<PlSmallStr> {
expr_output_name(&self.0)
}
pub fn undo_aliases(self) -> Expr {
self.0.map_expr(|e| match e {
Expr::Alias(input, _)
| Expr::KeepName(input)
| Expr::RenameAlias { expr: input, .. } => Arc::unwrap_or_clone(input),
e => e,
})
}
pub fn has_multiple_outputs(&self) -> bool {
self.0.into_iter().any(|e| match e {
Expr::Selector(_) | Expr::Wildcard | Expr::Columns(_) | Expr::DtypeColumn(_) => true,
Expr::IndexColumn(idxs) => idxs.len() > 1,
Expr::Column(name) => is_regex_projection(name),
_ => false,
})
}
pub fn is_column(&self) -> bool {
match &self.0 {
Expr::Column(name) => !is_regex_projection(name),
_ => false,
}
}
pub fn is_column_selection(&self, allow_aliasing: bool) -> bool {
self.0.into_iter().all(|e| match e {
Expr::Column(_)
| Expr::Columns(_)
| Expr::DtypeColumn(_)
| Expr::Exclude(_, _)
| Expr::Nth(_)
| Expr::IndexColumn(_)
| Expr::Selector(_)
| Expr::Wildcard => true,
Expr::Alias(_, _) | Expr::KeepName(_) | Expr::RenameAlias { .. } if allow_aliasing => {
true
},
_ => false,
})
}
pub fn is_regex_projection(&self) -> bool {
self.0.into_iter().any(|e| match e {
Expr::Column(name) => is_regex_projection(name),
_ => false,
})
}
pub fn _selector_add(self, other: Expr) -> PolarsResult<Expr> {
if let Expr::Selector(mut s) = self.0 {
if let Expr::Selector(s_other) = other {
s = s + s_other;
} else {
s = s + Selector::Root(Box::new(other))
}
Ok(Expr::Selector(s))
} else {
polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
}
}
pub fn _selector_and(self, other: Expr) -> PolarsResult<Expr> {
if let Expr::Selector(mut s) = self.0 {
if let Expr::Selector(s_other) = other {
s = s.bitand(s_other);
} else {
s = s.bitand(Selector::Root(Box::new(other)))
}
Ok(Expr::Selector(s))
} else {
polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
}
}
pub fn _selector_sub(self, other: Expr) -> PolarsResult<Expr> {
if let Expr::Selector(mut s) = self.0 {
if let Expr::Selector(s_other) = other {
s = s - s_other;
} else {
s = s - Selector::Root(Box::new(other))
}
Ok(Expr::Selector(s))
} else {
polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
}
}
pub fn _selector_xor(self, other: Expr) -> PolarsResult<Expr> {
if let Expr::Selector(mut s) = self.0 {
if let Expr::Selector(s_other) = other {
s = s ^ s_other;
} else {
s = s ^ Selector::Root(Box::new(other))
}
Ok(Expr::Selector(s))
} else {
polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
}
}
pub fn _into_selector(self) -> Expr {
if let Expr::Selector(_) = self.0 {
self.0
} else {
Expr::Selector(Selector::new(self.0))
}
}
pub fn into_tree_formatter(self) -> PolarsResult<impl Display> {
let mut arena = Default::default();
let node = to_aexpr(self.0, &mut arena)?;
let mut visitor = TreeFmtVisitor::default();
AexprNode::new(node).visit(&mut visitor, &arena)?;
Ok(visitor)
}
}