bend/hvm/
check_net_size.rs

1use super::tree_children;
2use crate::{diagnostics::Diagnostics, fun::Name, CompilerTarget};
3use hvm::ast::{Book, Net, Tree};
4
5pub const MAX_NET_SIZE_C: usize = 4095;
6pub const MAX_NET_SIZE_CUDA: usize = 64;
7
8pub fn check_net_sizes(
9  book: &Book,
10  diagnostics: &mut Diagnostics,
11  target: &CompilerTarget,
12) -> Result<(), Diagnostics> {
13  let (net_size_bound, target_lang) = match target {
14    CompilerTarget::Cuda => (MAX_NET_SIZE_CUDA, "Cuda"),
15    _ => (MAX_NET_SIZE_C, "C"),
16  };
17  for (name, net) in &book.defs {
18    let nodes = count_nodes(net);
19    if nodes > net_size_bound {
20      diagnostics.add_function_error(
21        format!("Definition is too large for HVM {target_lang} (size={nodes}, max size={net_size_bound}). Please break it into smaller pieces."),
22        Name::new(name),
23        Default::default()
24      );
25    }
26  }
27
28  diagnostics.fatal(())
29}
30
31/// Utility function to count the amount of nodes in an hvm-core AST net
32pub fn count_nodes(net: &Net) -> usize {
33  let mut visit: Vec<&Tree> = vec![&net.root];
34  let mut count = 0usize;
35  for (_, l, r) in &net.rbag {
36    visit.push(l);
37    visit.push(r);
38  }
39  while let Some(tree) = visit.pop() {
40    // If it is not 0-ary, then we'll count it as a node.
41    if tree_children(tree).next().is_some() {
42      count += 1;
43    }
44    for subtree in tree_children(tree) {
45      visit.push(subtree);
46    }
47  }
48  count
49}