use std::hash::Hash;
use std::ops::Deref;
use super::{Dialect, IR, State, ValId};
use crate::val_use::ValUse;
use crate::{OpRef, ValOrigin, ValOriginRef, ValRefFormatter, ValUseRef};
use zhc_utils::iter::Deduped;
#[derive(Debug, Clone)]
pub struct ValRef<'ir, D: Dialect> {
pub(super) id: ValId,
pub(super) ir: &'ir IR<D>,
pub(super) users: &'ir [ValUse],
pub(super) origin: &'ir ValOrigin,
pub(super) typ: &'ir D::TypeSystem,
pub(super) state: &'ir State,
}
impl<'ir, D: Dialect> Hash for ValRef<'ir, D> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state)
}
}
impl<'ir, D: Dialect> PartialEq for ValRef<'ir, D> {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self.ir, other.ir) && self.id == other.id
}
}
impl<'ir, D: Dialect> Eq for ValRef<'ir, D> {}
impl<'ir, D: Dialect> Deref for ValRef<'ir, D> {
type Target = ValId;
fn deref(&self) -> &Self::Target {
&self.id
}
}
#[allow(unused)]
impl<'ir, D: Dialect> ValRef<'ir, D> {
pub(super) fn raw_get_uses_iter(
&self,
) -> impl Iterator<Item = ValUseRef<'ir, D>> + use<'ir, D> {
self.users.iter().map(|uze| ValUseRef {
opref: self.ir.raw_get_op(uze.opid),
position: uze.position,
})
}
pub(super) fn raw_get_origin(&self) -> ValOriginRef<'ir, D> {
ValOriginRef {
opref: self.ir.raw_get_op(self.origin.opid),
position: self.origin.position,
}
}
}
impl<'ir, D: Dialect> ValRef<'ir, D> {
pub fn is_active(&self) -> bool {
self.state.is_active()
}
pub fn is_inactive(&self) -> bool {
self.state.is_inactive()
}
pub fn get_id(&self) -> ValId {
self.id
}
pub fn get_type(&self) -> D::TypeSystem {
self.typ.clone()
}
pub fn get_origin(&self) -> ValOriginRef<'ir, D> {
let output = self.raw_get_origin();
assert!(output.opref.is_active());
output
}
pub fn get_uses_iter(&self) -> impl Iterator<Item = ValUseRef<'ir, D>> + use<'ir, D> {
self.raw_get_uses_iter().filter(|u| u.opref.is_active())
}
pub fn get_users_iter(&self) -> impl Iterator<Item = OpRef<'ir, D>> + use<'ir, D> {
self.raw_get_uses_iter()
.map(|uze| uze.opref)
.filter(|u| u.is_active())
.dedup()
}
pub fn has_users(&self) -> bool {
self.get_users_iter().next().is_some()
}
pub fn format(&self) -> ValRefFormatter<'_, 'ir, D> {
ValRefFormatter::new(self)
}
}