Repository: HigherOrderCO/Bend
File: src/net/hvmc_to_net.rs (Rust)

Code before:
    }
  }

  let mut inodes = vec![];
  let mut subtrees = vec![(tree_root, tree)];
  while let Some((subtree_root, subtree)) = subtrees.pop() {
    match subtree {
      Tree::Era => {
        let var = new_var(n_vars);
        inodes.push(INode { kind: Era, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Ctr { lab, lft, rgt } => {
        // Dup labels in INet representation start at 0, while for hvmc::Net they start at 1
        let kind = match *lab {
          0 => Con,
          1 => Tup,
          _ => Dup { lab: *lab - 2 },
        };
        let lft = process_node_subtree(lft, net_root, &mut subtrees, n_vars);
        let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
        inodes.push(INode { kind, ports: [subtree_root, lft, rgt] })
      }
      Tree::Var { .. } => unreachable!(),
      Tree::Ref { nam } => {
        let kind = Ref { def_id: DefId::from_internal(*nam) };
        let var = new_var(n_vars);
        inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Num { val } => {
        let kind = Num { val: *val };
        let var = new_var(n_vars);
        inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Op2 { lft, rgt } => {
        let kind = Op2;
        let lft = process_node_subtree(lft, net_root, &mut subtrees, n_vars);
        let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
        inodes.push(INode { kind, ports: [subtree_root, lft, rgt] })
      }
      Tree::Mat { sel, ret } => {
        let kind = Mat;
        let sel = process_node_subtree(sel, net_root, &mut subtrees, n_vars);
        let ret = process_node_subtree(ret, net_root, &mut subtrees, n_vars);
        inodes.push(INode { kind, ports: [subtree_root, sel, ret] })
      }
    }
  }
  inodes
}

// Converts INodes to an INet by linking ports based on names.

Review comment (bug):
Also, could you put this `2` in a separate constant in `net::mods.rs` (maybe as member of NodeKind type)?
We'll possibly have to change it again later and having it spread out in multiple places increases the chance of doing it wrong.
Could be something like `const BASE_DUP_HVMC_LABEL: u8 = 2;`

Code after:
  fn process_node_subtree<'a>(
    subtree: &'a Tree,
    net_root: &str,
    subtrees: &mut Vec<(String, &'a Tree)>,
    n_vars: &mut NodeId,
  ) -> String {
    if let Tree::Var { nam } = subtree {
      if nam == net_root { "_".to_string() } else { nam.clone() }
    } else {
      let var = new_var(n_vars);
      subtrees.push((var.clone(), subtree));
      var
    }
  }

  let mut inodes = vec![];
  let mut subtrees = vec![(tree_root, tree)];
  while let Some((subtree_root, subtree)) = subtrees.pop() {
    match subtree {
      Tree::Era => {
        let var = new_var(n_vars);
        inodes.push(INode { kind: Era, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Ctr { lab, lft, rgt } => {
        // Dup labels in INet representation start at 0, while for hvmc::Net they start at 1
        let kind = match *lab {
          0 => Con,
          1 => Tup,
          _ => Dup { lab: *lab - BASE_DUP_HVMC_LABEL },
        };
        let lft = process_node_subtree(lft, net_root, &mut subtrees, n_vars);
        let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
        inodes.push(INode { kind, ports: [subtree_root, lft, rgt] })
      }
      Tree::Var { .. } => unreachable!(),
      Tree::Ref { nam } => {
        let kind = Ref { def_id: hvmc_name_to_id(*nam) };
        let var = new_var(n_vars);
        inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Num { val } => {
        let kind = Num { val: *val };
        let var = new_var(n_vars);
        inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
      }
      Tree::Op2 { lft, rgt } => {
        let kind = Op2;
        let lft = process_node_subtree(lft, net_root, &mut subtrees, n_vars);
        let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
        inodes.push(INode { kind, ports: [subtree_root, lft, rgt] })
      }