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

Code before:
    for subtree in tree.children() {
      visit.push(subtree);
    }
  }
  count
}

pub fn run_compiled(
  host: Arc<Mutex<Host>>,
  mem_size: Option<usize>,
  run_opts: RunOpts,
  hook: Option<impl FnMut(&Net)>,
  entrypoint: &str,
) -> (Net, RunStats) {
  let heap = Heap::new(mem_size).expect("memory allocation failed");
  let mut root = DynNet::new(&heap, run_opts.lazy_mode);
  let max_rwts = run_opts.max_rewrites.map(|x| x.clamp(usize::MIN, usize::MAX));
  // Expect won't be reached because there's
  // a pass that checks this.
  dispatch_dyn_net!(&mut root => {
    root.boot(host.lock().unwrap().defs.get(entrypoint).expect("No main function."));

    let start_time = Instant::now();

    if let Some(mut hook) = hook {
      if run_opts.lazy_mode {
        let mut visit = vec![hvmc::run::Port::new_var(root.root.addr())];
        while let Some(prev) = visit.pop() {
          let next = root.weak_normal(prev, root.root.clone());

          let readback = host.lock().unwrap().readback(root);
          hook(&readback);

          if next.is_full_node() {
            visit.push(hvmc::run::Port::new_var(next.addr()));
            visit.push(hvmc::run::Port::new_var(next.addr().other_half()));
          }
        }
      } else {
        while !root.redexes.is_empty() {
          let readback = host.lock().unwrap().readback(root);
          hook(&readback);
          root.reduce(1);
        }
      }
    } else if let Some(mut max_rwts) = max_rwts {
      if run_opts.lazy_mode {
        panic!("Lazy mode does not yet support rewrite limit");
      }
      if !run_opts.single_core {
        panic!("Parallel mode does not yet support rewrite limit");

Review comment (bug):
Can you separate each of these cases into separate functions?
So that our "run" function is simpler
```
match (hook, run_opts.lazy_mode, max_rwts) {
 (Some(hook), true, max_rwts) => normal_lazy_debug(),
 (...) => normal_strict_debug(),
 ...
}
```

Code after:
  let info = RunInfo { stats, diagnostics, net: res_lnet, book, labels };
  Ok((res_term, info))
}

/// Utility function to count the amount of nodes in an hvm-core AST net
pub fn count_nodes<'l>(net: &'l hvmc::ast::Net) -> usize {
  let mut visit: Vec<&'l hvmc::ast::Tree> = vec![&net.root];
  let mut count = 0usize;
  for (l, r) in &net.redexes {
    visit.push(l);
    visit.push(r);
  }
  while let Some(tree) = visit.pop() {
    // If it is not 0-ary, then we'll count it as a node.
    if tree.children().next().is_some() {
      count += 1;
    }
    for subtree in tree.children() {
      visit.push(subtree);
    }
  }
  count
}

pub fn run_compiled(
  host: Arc<Mutex<Host>>,
  mem_size: Option<usize>,
  run_opts: RunOpts,
  hook: Option<impl FnMut(&Net)>,
  entrypoint: &str,
) -> (Net, RunStats) {
  let heap = Heap::new(mem_size).expect("memory allocation failed");
  let mut root = DynNet::new(&heap, run_opts.lazy_mode);
  let max_rwts = run_opts.max_rewrites.map(|x| x.clamp(usize::MIN, usize::MAX));
  dispatch_dyn_net!(&mut root => {
    root.boot(host.lock().unwrap().defs.get(entrypoint).expect("No main function."));

    let start_time = Instant::now();

    match (hook, run_opts.lazy_mode, max_rwts) {
      (Some(hook), true, _) => normal_lazy_debug(hook, host.clone(), root),
      (Some(hook), false, _) => normal_strict_debug(hook, host.clone(), root),
      (_, lazy_mode, Some(max_rwts)) if !lazy_mode => {
        if !run_opts.single_core {
          panic!("Parallel mode does not yet support rewrite limit");
        }
        normal_strict_rwts(max_rwts, root);
      },
      (_, true, Some(_)) => {
        panic!("Lazy mode does not yet support rewrite limit");
      },