pub mod hvmc_to_net;
use crate::fun::Name;
pub type BendLab = u16;
use NodeKind::*;
#[derive(Debug, Clone)]
pub struct INet {
nodes: Vec<Node>,
}
#[derive(Debug, Clone)]
pub struct Node {
pub main: Port,
pub aux1: Port,
pub aux2: Port,
pub kind: NodeKind,
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Port(pub NodeId, pub SlotId);
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NodeKind {
Rot,
Era,
Ctr(CtrKind),
Ref { def_name: Name },
Num { val: u32 },
Opr,
Mat,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CtrKind {
Con(Option<BendLab>),
Tup(Option<BendLab>),
Dup(BendLab),
}
impl CtrKind {
pub fn to_lab(self) -> BendLab {
#[allow(clippy::identity_op)]
match self {
CtrKind::Con(None) => 0,
CtrKind::Con(Some(_)) => todo!("Tagged lambdas/applications not implemented for hvm32"),
CtrKind::Tup(None) => 0,
CtrKind::Tup(Some(_)) => todo!("Tagged tuples not implemented for hvm32"),
CtrKind::Dup(0) => 1,
CtrKind::Dup(_) => todo!("Tagged dups/sups not implemented for hvm32"),
}
}
fn from_lab(lab: u16) -> Self {
match lab {
0 => CtrKind::Con(None),
n => CtrKind::Dup(n - 1),
}
}
}
pub type NodeId = u64;
pub type SlotId = u64;
pub const ROOT: Port = Port(0, 1);
pub const TAG_WIDTH: u32 = 4;
pub const TAG: u32 = u64::BITS - TAG_WIDTH;
pub const LABEL_MASK: u64 = (1 << TAG) - 1;
pub const TAG_MASK: u64 = !LABEL_MASK;
impl INet {
pub fn new() -> Self {
Self::default()
}
pub fn new_node(&mut self, kind: NodeKind) -> NodeId {
let idx = self.nodes.len() as NodeId;
let node = Node::new(Port(idx, 0), Port(idx, 1), Port(idx, 2), kind);
self.nodes.extend([node]);
idx
}
pub fn node(&self, node: NodeId) -> &Node {
&self.nodes[node as usize]
}
pub fn enter_port(&self, port: Port) -> Port {
self.node(port.node()).port(port.slot())
}
pub fn link(&mut self, a: Port, b: Port) {
self.set(a, b);
self.set(b, a);
}
pub fn set(&mut self, src: Port, dst: Port) {
*self.nodes[src.node() as usize].port_mut(src.slot()) = dst;
}
}
impl Default for INet {
fn default() -> Self {
INet {
nodes: vec![Node::new(Port(0, 2), Port(0, 1), Port(0, 0), Rot)], }
}
}
impl Node {
pub fn new(main: Port, aux1: Port, aux2: Port, kind: NodeKind) -> Self {
Node { main, aux1, aux2, kind }
}
pub fn port(&self, slot: SlotId) -> Port {
match slot {
0 => self.main,
1 => self.aux1,
2 => self.aux2,
_ => unreachable!(),
}
}
pub fn port_mut(&mut self, slot: SlotId) -> &mut Port {
match slot {
0 => &mut self.main,
1 => &mut self.aux1,
2 => &mut self.aux2,
_ => unreachable!(),
}
}
}
impl Port {
pub fn node(self) -> NodeId {
self.0
}
pub fn slot(self) -> SlotId {
self.1
}
}
pub type INodes = Vec<INode>;
#[derive(Debug)]
pub struct INode {
pub kind: NodeKind,
pub ports: [String; 3],
}