zhc_ir 0.1.8

Graph-based intermediate representation framework with dialect support
Documentation
use std::{fmt::Debug, ops::Deref};

use zhc_utils::Dumpable;

use crate::{
    AnnOpRef, AnnValOriginRef, AnnValUseRef, Annotation, Dialect, Formatted, ValRef,
    annotation::view::AnnIRView,
};

/// Value reference with attached annotation data.
#[derive(Debug, Clone)]
pub struct AnnValRef<'ir, 'ann, D: Dialect, OpAnn: Annotation, ValAnn: Annotation> {
    pub(super) ir: AnnIRView<'ir, 'ann, D, OpAnn, ValAnn>,
    pub(super) valref: ValRef<'ir, D>,
    pub(super) ann: &'ann ValAnn,
}

impl<'ir, 'ann, D: Dialect, OpAnn: Annotation, ValAnn: Annotation>
    AnnValRef<'ir, 'ann, D, OpAnn, ValAnn>
{
    /// Returns the annotation for this value.
    pub fn get_annotation(&self) -> &ValAnn {
        self.ann
    }

    /// Returns the operation that produces this value with its annotation.
    pub fn get_origin(&self) -> AnnValOriginRef<'ir, 'ann, D, OpAnn, ValAnn> {
        let origin = self.valref.get_origin();
        let ann = &self.ir.op_annotations[*origin.opref];
        AnnValOriginRef {
            opref: AnnOpRef {
                ir: self.ir.clone(),
                opref: origin.opref.clone(),
                ann,
            },
            position: origin.position,
        }
    }

    /// Returns an iterator over use-sites of this value with position and annotation data.
    pub fn get_uses_iter(
        &self,
    ) -> impl Iterator<Item = AnnValUseRef<'ir, 'ann, D, OpAnn, ValAnn>> + use<'ir, 'ann, D, OpAnn, ValAnn>
    {
        let local_ir = self.ir.clone();
        self.valref.get_uses_iter().map(move |user| {
            let ann = &local_ir.op_annotations[*user.opref];
            AnnValUseRef {
                opref: AnnOpRef {
                    ir: local_ir.clone(),
                    opref: user.opref,
                    ann,
                },
                position: user.position,
            }
        })
    }

    /// Returns an iterator over operations that use this value with their annotations.
    pub fn get_users_iter(
        &self,
    ) -> impl Iterator<Item = AnnOpRef<'ir, 'ann, D, OpAnn, ValAnn>> + use<'ir, 'ann, D, OpAnn, ValAnn>
    {
        let local_ir = self.ir.clone();
        self.valref.get_users_iter().map(move |user| {
            let ann = &local_ir.op_annotations[*user];
            AnnOpRef {
                ir: local_ir.clone(),
                opref: user,
                ann,
            }
        })
    }

    /// Creates a configurable formatter for this annotated value.
    pub fn format(&self) -> Formatted<'_, Self> {
        Formatted::new(self)
    }
}

impl<'ir, 'ann, D: Dialect, OpAnn: Annotation, ValAnn: Annotation> Deref
    for AnnValRef<'ir, 'ann, D, OpAnn, ValAnn>
{
    type Target = ValRef<'ir, D>;

    fn deref(&self) -> &Self::Target {
        &self.valref
    }
}

impl<'ir, 'ann, D: Dialect, OpAnn: Annotation, ValAnn: Annotation> PartialEq
    for AnnValRef<'ir, 'ann, D, OpAnn, ValAnn>
{
    fn eq(&self, other: &Self) -> bool {
        self.valref == other.valref && *self.ann == *other.ann
    }
}

impl<'ir, 'ann, D: Dialect, OpAnn: Annotation, ValAnn: Annotation> Eq
    for AnnValRef<'ir, 'ann, D, OpAnn, ValAnn>
{
}

impl<D: Dialect, OpAnn: Annotation, ValAnn: Annotation> Dumpable
    for AnnValRef<'_, '_, D, OpAnn, ValAnn>
{
    fn dump_to_string(&self) -> String {
        self.format().dump_to_string()
    }
}