use super::types::{Expr, Node, REBUILD_COST_MAX};
use crate::Level;
const FLAG_FVAR: u32 = 1 << 29;
const FLAG_LEVEL_PARAM: u32 = 1 << 30;
const FLAG_LEVEL_MVAR: u32 = 1 << 31;
const _: () = assert!((FLAG_FVAR | FLAG_LEVEL_PARAM | FLAG_LEVEL_MVAR) & REBUILD_COST_MAX == 0);
impl Expr {
#[inline]
#[must_use]
pub(super) fn flags(&self) -> u32 {
fn level_flags(level: &Level) -> u32 {
let param = if level.has_param() {
FLAG_LEVEL_PARAM
} else {
0
};
let mvar = if level.has_mvar() { FLAG_LEVEL_MVAR } else { 0 };
param | mvar
}
match self {
Expr::Sort(level) => level_flags(level),
Expr::Const(_, levels) => levels
.iter()
.fold(0, |flags, level| flags | level_flags(level)),
Expr::FVar(_) => FLAG_FVAR,
Expr::BVar(_) | Expr::Lit(_) => 0,
Expr::App(f, a) => f.flags() | a.flags(),
Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => ty.flags() | body.flags(),
Expr::Let(_, ty, val, body) => ty.flags() | val.flags() | body.flags(),
Expr::Proj(_, _, inner) => inner.flags(),
}
}
#[inline]
#[must_use]
pub(crate) fn has_fvar(&self) -> bool {
self.flags() & FLAG_FVAR != 0
}
#[inline]
#[must_use]
pub(crate) fn has_level_param(&self) -> bool {
self.flags() & FLAG_LEVEL_PARAM != 0
}
#[inline]
#[must_use]
pub(crate) fn has_level_mvar(&self) -> bool {
self.flags() & FLAG_LEVEL_MVAR != 0
}
}
#[cfg(feature = "term-depth")]
impl Expr {
#[inline]
#[must_use]
pub(crate) fn depth(&self) -> u32 {
let below = match self {
Expr::Sort(_) | Expr::Const(_, _) | Expr::FVar(_) | Expr::BVar(_) | Expr::Lit(_) => 0,
Expr::App(f, a) => f.depth().max(a.depth()),
Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => ty.depth().max(body.depth()),
Expr::Let(_, ty, val, body) => ty.depth().max(val.depth()).max(body.depth()),
Expr::Proj(_, _, inner) => inner.depth(),
};
below.saturating_add(1)
}
}
impl Node {
#[inline]
#[must_use]
pub(crate) fn has_fvar(&self) -> bool {
self.flags() & FLAG_FVAR != 0
}
#[inline]
#[must_use]
pub(crate) fn has_level_param(&self) -> bool {
self.flags() & FLAG_LEVEL_PARAM != 0
}
}