use crate::types::{Type, TypeBound};
use crate::Node;
use derive_more::From as DerFrom;
use smol_str::SmolStr;
use super::{AliasDecl, OpTag};
pub trait NodeHandle: Clone {
const TAG: OpTag;
fn node(&self) -> Node;
#[inline]
fn tag(&self) -> OpTag {
Self::TAG
}
fn try_cast<T: NodeHandle + From<Node>>(&self) -> Option<T> {
T::TAG.is_superset(Self::TAG).then(|| self.node().into())
}
fn can_hold(tag: OpTag) -> bool {
Self::TAG.is_superset(tag)
}
}
pub trait ContainerHandle: NodeHandle {
type ChildrenHandle: NodeHandle;
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct DataflowOpID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct DfgID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct CfgID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct ModuleRootID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct ModuleID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct FuncID<const DEF: bool>(Node);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AliasID<const DEF: bool> {
node: Node,
name: SmolStr,
bound: TypeBound,
}
impl<const DEF: bool> AliasID<DEF> {
pub fn new(node: Node, name: SmolStr, bound: TypeBound) -> Self {
Self { node, name, bound }
}
pub fn get_alias_type(&self) -> Type {
Type::new_alias(AliasDecl::new(self.name.clone(), self.bound))
}
pub fn get_name(&self) -> &SmolStr {
&self.name
}
}
#[derive(DerFrom, Debug, Clone, PartialEq, Eq)]
pub struct ConstID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct BasicBlockID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct CaseID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct TailLoopID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct ConditionalID(Node);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
pub struct DataflowParentID(Node);
macro_rules! impl_nodehandle {
($name:ident, $tag:expr) => {
impl_nodehandle!($name, $tag, 0);
};
($name:ident, $tag:expr, $node_attr:tt) => {
impl NodeHandle for $name {
const TAG: OpTag = $tag;
#[inline]
fn node(&self) -> Node {
self.$node_attr
}
}
};
}
impl_nodehandle!(DataflowParentID, OpTag::DataflowParent);
impl_nodehandle!(DataflowOpID, OpTag::DataflowChild);
impl_nodehandle!(ConditionalID, OpTag::Conditional);
impl_nodehandle!(CaseID, OpTag::Case);
impl_nodehandle!(DfgID, OpTag::Dfg);
impl_nodehandle!(TailLoopID, OpTag::TailLoop);
impl_nodehandle!(CfgID, OpTag::Cfg);
impl_nodehandle!(ModuleRootID, OpTag::ModuleRoot);
impl_nodehandle!(ModuleID, OpTag::ModuleOp);
impl_nodehandle!(ConstID, OpTag::Const);
impl_nodehandle!(BasicBlockID, OpTag::DataflowBlock);
impl<const DEF: bool> NodeHandle for FuncID<DEF> {
const TAG: OpTag = OpTag::Function;
#[inline]
fn node(&self) -> Node {
self.0
}
}
impl<const DEF: bool> NodeHandle for AliasID<DEF> {
const TAG: OpTag = OpTag::Alias;
#[inline]
fn node(&self) -> Node {
self.node
}
}
impl NodeHandle for Node {
const TAG: OpTag = OpTag::Any;
#[inline]
fn node(&self) -> Node {
*self
}
}
macro_rules! impl_containerHandle {
($name:path, $children:ident) => {
impl ContainerHandle for $name {
type ChildrenHandle = $children;
}
};
}
impl_containerHandle!(DataflowParentID, DataflowOpID);
impl_containerHandle!(DfgID, DataflowOpID);
impl_containerHandle!(TailLoopID, DataflowOpID);
impl_containerHandle!(ConditionalID, CaseID);
impl_containerHandle!(CaseID, DataflowOpID);
impl_containerHandle!(ModuleRootID, ModuleID);
impl_containerHandle!(CfgID, BasicBlockID);
impl_containerHandle!(BasicBlockID, DataflowOpID);
impl_containerHandle!(FuncID<true>, DataflowOpID);
impl_containerHandle!(AliasID<true>, DataflowOpID);