1use super::{INet, INode, INodes, NodeId, NodeKind::*, Port, SlotId, ROOT};
2use crate::{
3 fun::Name,
4 net::{CtrKind, NodeKind},
5};
6use hvm::ast::{Net, Tree};
7
8pub fn hvm_to_net(net: &Net) -> INet {
9 let inodes = hvm_to_inodes(net);
10 inodes_to_inet(&inodes)
11}
12
13fn hvm_to_inodes(net: &Net) -> INodes {
14 let mut inodes = vec![];
15 let mut n_vars = 0;
16 let net_root = if let Tree::Var { nam } = &net.root { nam } else { "" };
17
18 if !matches!(&net.root, Tree::Var { .. }) {
20 let mut root = tree_to_inodes(&net.root, "_".to_string(), net_root, &mut n_vars);
21 inodes.append(&mut root);
22 }
23
24 for (i, (_, tree1, tree2)) in net.rbag.iter().enumerate() {
26 let tree_root = format!("%a{i}");
28 let mut tree1 = tree_to_inodes(tree1, tree_root.clone(), net_root, &mut n_vars);
29 inodes.append(&mut tree1);
30 let mut tree2 = tree_to_inodes(tree2, tree_root, net_root, &mut n_vars);
31 inodes.append(&mut tree2);
32 }
33 inodes
34}
35
36fn new_var(n_vars: &mut NodeId) -> String {
37 let new_var = format!("%x{n_vars}");
39 *n_vars += 1;
40 new_var
41}
42
43fn tree_to_inodes(tree: &Tree, tree_root: String, net_root: &str, n_vars: &mut NodeId) -> INodes {
44 fn process_node_subtree<'a>(
45 subtree: &'a Tree,
46 net_root: &str,
47 subtrees: &mut Vec<(String, &'a Tree)>,
48 n_vars: &mut NodeId,
49 ) -> String {
50 if let Tree::Var { nam } = subtree {
51 if nam == net_root {
52 "_".to_string()
53 } else {
54 nam.clone()
55 }
56 } else {
57 let var = new_var(n_vars);
58 subtrees.push((var.clone(), subtree));
59 var
60 }
61 }
62
63 let mut inodes = vec![];
64 let mut subtrees = vec![(tree_root, tree)];
65 while let Some((subtree_root, subtree)) = subtrees.pop() {
66 match subtree {
67 Tree::Era => {
68 let var = new_var(n_vars);
69 inodes.push(INode { kind: Era, ports: [subtree_root, var.clone(), var] });
70 }
71 Tree::Con { fst, snd } => {
72 let kind = NodeKind::Ctr(CtrKind::Con(None));
73 let fst = process_node_subtree(fst, net_root, &mut subtrees, n_vars);
74 let snd = process_node_subtree(snd, net_root, &mut subtrees, n_vars);
75 inodes.push(INode { kind, ports: [subtree_root, fst, snd] });
76 }
77 Tree::Dup { fst, snd } => {
78 let kind = NodeKind::Ctr(CtrKind::Dup(0));
79 let fst = process_node_subtree(fst, net_root, &mut subtrees, n_vars);
80 let snd = process_node_subtree(snd, net_root, &mut subtrees, n_vars);
81 inodes.push(INode { kind, ports: [subtree_root, fst, snd] });
82 }
83 Tree::Var { .. } => unreachable!(),
84 Tree::Ref { nam } => {
85 let kind = Ref { def_name: Name::new(nam) };
86 let var = new_var(n_vars);
87 inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
88 }
89 Tree::Num { val } => {
90 let kind = Num { val: val.0 };
91 let var = new_var(n_vars);
92 inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
93 }
94 Tree::Opr { fst, snd } => {
95 let kind = NodeKind::Opr;
96 let fst = process_node_subtree(fst, net_root, &mut subtrees, n_vars);
97 let snd = process_node_subtree(snd, net_root, &mut subtrees, n_vars);
98 inodes.push(INode { kind, ports: [subtree_root, fst, snd] });
99 }
100 Tree::Swi { fst, snd } => {
101 let kind = NodeKind::Swi;
102 let fst = process_node_subtree(fst, net_root, &mut subtrees, n_vars);
103 let snd = process_node_subtree(snd, net_root, &mut subtrees, n_vars);
104 inodes.push(INode { kind, ports: [subtree_root, fst, snd] });
105 }
106 }
107 }
108 inodes
109}
110
111fn inodes_to_inet(inodes: &INodes) -> INet {
113 let mut inet = INet::new();
114 let mut name_map = std::collections::HashMap::new();
116
117 for inode in inodes {
118 let node = inet.new_node(inode.kind.clone());
119 for (j, name) in inode.ports.iter().enumerate() {
120 let p = Port(node, j as SlotId);
121 if name == "_" {
122 inet.link(p, ROOT);
123 } else if let Some(&q) = name_map.get(name) {
124 inet.link(p, q);
125 name_map.remove(name);
126 } else {
127 name_map.insert(name.clone(), p);
128 }
129 }
130 }
131
132 inet
133}